1 /*
2  * Copyright 2008-2009 Katholieke Universiteit Leuven
3  * Copyright 2010      INRIA Saclay
4  * Copyright 2012-2013 Ecole Normale Superieure
5  * Copyright 2014      INRIA Rocquencourt
6  *
7  * Use of this software is governed by the MIT license
8  *
9  * Written by Sven Verdoolaege, K.U.Leuven, Departement
10  * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
11  * and INRIA Saclay - Ile-de-France, Parc Club Orsay Universite,
12  * ZAC des vignes, 4 rue Jacques Monod, 91893 Orsay, France
13  * and Ecole Normale Superieure, 45 rue d’Ulm, 75230 Paris, France
14  * and Inria Paris - Rocquencourt, Domaine de Voluceau - Rocquencourt,
15  * B.P. 105 - 78153 Le Chesnay, France
16  */
17 
18 #include <assert.h>
19 #include <stdio.h>
20 #include <limits.h>
21 #include <isl_ctx_private.h>
22 #include <isl_map_private.h>
23 #include <isl_aff_private.h>
24 #include <isl_space_private.h>
25 #include <isl/id.h>
26 #include <isl/set.h>
27 #include <isl/flow.h>
28 #include <isl_constraint_private.h>
29 #include <isl/polynomial.h>
30 #include <isl/union_set.h>
31 #include <isl/union_map.h>
32 #include <isl_factorization.h>
33 #include <isl/schedule.h>
34 #include <isl/schedule_node.h>
35 #include <isl_options_private.h>
36 #include <isl_vertices_private.h>
37 #include <isl/ast_build.h>
38 #include <isl/val.h>
39 #include <isl/ilp.h>
40 #include <isl_ast_build_expr.h>
41 #include <isl/options.h>
42 
43 #include "isl_srcdir.c"
44 
45 #define ARRAY_SIZE(array) (sizeof(array)/sizeof(*array))
46 
get_filename(isl_ctx * ctx,const char * name,const char * suffix)47 static char *get_filename(isl_ctx *ctx, const char *name, const char *suffix) {
48 	char *filename;
49 	int length;
50 	char *pattern = "%s/test_inputs/%s.%s";
51 
52 	length = strlen(pattern) - 6 + strlen(srcdir) + strlen(name)
53 		+ strlen(suffix) + 1;
54 	filename = isl_alloc_array(ctx, char, length);
55 
56 	if (!filename)
57 		return NULL;
58 
59 	sprintf(filename, pattern, srcdir, name, suffix);
60 
61 	return filename;
62 }
63 
test_parse_map(isl_ctx * ctx,const char * str)64 void test_parse_map(isl_ctx *ctx, const char *str)
65 {
66 	isl_map *map;
67 
68 	map = isl_map_read_from_str(ctx, str);
69 	assert(map);
70 	isl_map_free(map);
71 }
72 
test_parse_map_equal(isl_ctx * ctx,const char * str,const char * str2)73 int test_parse_map_equal(isl_ctx *ctx, const char *str, const char *str2)
74 {
75 	isl_map *map, *map2;
76 	int equal;
77 
78 	map = isl_map_read_from_str(ctx, str);
79 	map2 = isl_map_read_from_str(ctx, str2);
80 	equal = isl_map_is_equal(map, map2);
81 	isl_map_free(map);
82 	isl_map_free(map2);
83 
84 	if (equal < 0)
85 		return -1;
86 	if (!equal)
87 		isl_die(ctx, isl_error_unknown, "maps not equal",
88 			return -1);
89 
90 	return 0;
91 }
92 
test_parse_pwqp(isl_ctx * ctx,const char * str)93 void test_parse_pwqp(isl_ctx *ctx, const char *str)
94 {
95 	isl_pw_qpolynomial *pwqp;
96 
97 	pwqp = isl_pw_qpolynomial_read_from_str(ctx, str);
98 	assert(pwqp);
99 	isl_pw_qpolynomial_free(pwqp);
100 }
101 
test_parse_pwaff(isl_ctx * ctx,const char * str)102 static void test_parse_pwaff(isl_ctx *ctx, const char *str)
103 {
104 	isl_pw_aff *pwaff;
105 
106 	pwaff = isl_pw_aff_read_from_str(ctx, str);
107 	assert(pwaff);
108 	isl_pw_aff_free(pwaff);
109 }
110 
111 /* Check that we can read an isl_multi_val from "str" without errors.
112  */
test_parse_multi_val(isl_ctx * ctx,const char * str)113 static int test_parse_multi_val(isl_ctx *ctx, const char *str)
114 {
115 	isl_multi_val *mv;
116 
117 	mv = isl_multi_val_read_from_str(ctx, str);
118 	isl_multi_val_free(mv);
119 
120 	return mv ? 0 : -1;
121 }
122 
123 /* String descriptions of multi piecewise affine expressions
124  * that are used for testing printing and parsing.
125  */
126 static const char *reparse_multi_pw_aff_tests[] = {
127 	"{ A[x, y] -> [] : x + y >= 0 }",
128 	"{ A[x, y] -> B[] : x + y >= 0 }",
129 	"{ A[x, y] -> [x] : x + y >= 0 }",
130 	"[N] -> { A[x, y] -> [x] : x + y <= N }",
131 	"{ A[x, y] -> [x, y] : x + y >= 0 }",
132 	"{ A[x, y] -> [(x : x >= 0), (y : y >= 0)] : x + y >= 0 }",
133 	"[N] -> { [] : N >= 0 }",
134 	"[N] -> { [] : N >= 0 }",
135 	"[N] -> { [N] : N >= 0 }",
136 	"[N] -> { [N, N + 1] : N >= 0 }",
137 	"[N, M] -> { [(N : N >= 0), (M : M >= 0)] : N + M >= 0 }",
138 	"{ [a] -> [b = a] }",
139 	"{ [a] -> [b = a] : a >= 0 }",
140 };
141 
142 #undef BASE
143 #define BASE multi_pw_aff
144 
145 #include "check_reparse_templ.c"
146 #include "check_reparse_test_templ.c"
147 
148 /* String descriptions that cannot be parsed
149  * as multi piecewise affine expressions.
150  */
151 static const char *parse_multi_pw_aff_fail_tests[] = {
152 	"{ [a] -> [b] : b = a }",
153 	"{ [a] -> [b = a] : b >= 0 }",
154 };
155 
156 #include "check_parse_fail_test_templ.c"
157 
158 /* String descriptions of piecewise multi affine expressions
159  * that are used for testing printing and parsing.
160  */
161 static const char *reparse_pw_multi_aff_tests[] = {
162 	"{ [x] -> [x] }",
163 	"{ [x] -> [x % 4] }",
164 	"{ [x] -> [x % 4] : x mod 3 = 1 }",
165 	"{ [x, x] -> [x % 4] }",
166 	"{ [x, x + 1] -> [x % 4] : x mod 3 = 1 }",
167 	"{ [x, x mod 2] -> [x % 4] }",
168 };
169 
170 #undef BASE
171 #define BASE pw_multi_aff
172 
173 #include "check_reparse_templ.c"
174 #include "check_reparse_test_templ.c"
175 
176 /* Test parsing of piecewise multi affine expressions by printing
177  * the expressions and checking that parsing the output results
178  * in the same expression.
179  * Do this for an expression converted from a map with an output
180  * dimension name that is equal to an automatically generated name, and
181  * a set of expressions parsed from strings.
182  */
test_parse_pma(isl_ctx * ctx)183 static isl_stat test_parse_pma(isl_ctx *ctx)
184 {
185 	isl_map *map;
186 	isl_pw_multi_aff *pma;
187 
188 	map = isl_map_read_from_str(ctx, "{ [a, a] -> [i1 = a + 1] }");
189 	pma = isl_pw_multi_aff_from_map(map);
190 	if (check_reparse_pw_multi_aff(ctx, pma) < 0)
191 		return isl_stat_error;
192 
193 	if (check_reparse_pw_multi_aff_tests(ctx) < 0)
194 		return isl_stat_error;
195 
196 	return isl_stat_ok;
197 }
198 
199 /* String descriptions that cannot be parsed
200  * as union piecewise multi affine expressions.
201  */
202 static const char *parse_union_pw_multi_aff_fail_tests[] = {
203 	"{ [a] -> [b] : b = a }",
204 	"{ [a] -> [b = a] : b >= 0 }",
205 };
206 
207 #undef BASE
208 #define BASE union_pw_multi_aff
209 
210 #include "check_parse_fail_test_templ.c"
211 
212 /* Test parsing of union piecewise multi affine expressions.
213  *
214  * In particular, check some cases where parsing is supposed to fail.
215  */
test_parse_upma(isl_ctx * ctx)216 static isl_stat test_parse_upma(isl_ctx *ctx)
217 {
218 	if (check_parse_union_pw_multi_aff_fail_tests(ctx) < 0)
219 		return isl_stat_error;
220 
221 	return isl_stat_ok;
222 }
223 
224 /* Test parsing of multi piecewise affine expressions by printing
225  * the expressions and checking that parsing the output results
226  * in the same expression.
227  * Do this for a couple of manually constructed expressions,
228  * an expression converted from a map with an output dimension name
229  * that is equal to an automatically generated name, and
230  * a set of expressions parsed from strings.
231  *
232  * Additionally, check some cases where parsing is supposed to fail.
233  */
test_parse_mpa(isl_ctx * ctx)234 static int test_parse_mpa(isl_ctx *ctx)
235 {
236 	isl_space *space;
237 	isl_set *dom;
238 	isl_map *map;
239 	isl_pw_multi_aff *pma;
240 	isl_multi_pw_aff *mpa;
241 	isl_stat r;
242 
243 	space = isl_space_set_alloc(ctx, 0, 0);
244 	space = isl_space_set_tuple_name(space, isl_dim_set, "A");
245 	mpa = isl_multi_pw_aff_zero(space);
246 	r = check_reparse_multi_pw_aff(ctx, mpa);
247 	if (r < 0)
248 		return -1;
249 
250 	space = isl_space_set_alloc(ctx, 1, 0);
251 	space = isl_space_set_dim_name(space, isl_dim_param, 0, "N");
252 	space = isl_space_set_tuple_name(space, isl_dim_set, "A");
253 	dom = isl_set_universe(isl_space_params(isl_space_copy(space)));
254 	dom = isl_set_lower_bound_si(dom, isl_dim_param, 0, 5);
255 	mpa = isl_multi_pw_aff_zero(space);
256 	mpa = isl_multi_pw_aff_intersect_domain(mpa, dom);
257 	r = check_reparse_multi_pw_aff(ctx, mpa);
258 	if (r < 0)
259 		return -1;
260 
261 	map = isl_map_read_from_str(ctx, "{ [a, a] -> [i1 = a + 1] }");
262 	pma = isl_pw_multi_aff_from_map(map);
263 	mpa = isl_multi_pw_aff_from_pw_multi_aff(pma);
264 	if (check_reparse_multi_pw_aff(ctx, mpa) < 0)
265 		return -1;
266 
267 	if (check_reparse_multi_pw_aff_tests(ctx) < 0)
268 		return -1;
269 	if (check_parse_multi_pw_aff_fail_tests(ctx) < 0)
270 		return -1;
271 
272 	return 0;
273 }
274 
275 /* String descriptions of multi union piecewise affine expressions
276  * that are used for testing printing and parsing.
277  */
278 static const char *reparse_multi_union_pw_aff_tests[] = {
279 	"[]",
280 	"A[]",
281 	"A[B[] -> C[]]",
282 	"(A[] : { S[x] : x > 0; T[y] : y >= 0 })",
283 	"(A[] : { })",
284 	"[N] -> (A[] : { })",
285 	"[N] -> (A[] : { : N >= 0 })",
286 	"[N] -> (A[] : { S[x] : x > N; T[y] : y >= 0 })",
287 	"(A[] : [N] -> { S[x] : x > N; T[y] : y >= 0 })",
288 	"A[{ S[x] -> [x + 1]; T[x] -> [x] }]",
289 	"(A[{ S[x] -> [x + 1]; T[x] -> [x] }] : "
290 		"{ S[x] : x > 0; T[y] : y >= 0 })",
291 };
292 
293 #undef BASE
294 #define BASE multi_union_pw_aff
295 
296 #include "check_reparse_templ.c"
297 #include "check_reparse_test_templ.c"
298 
299 /* Test parsing of multi union piecewise affine expressions by printing
300  * the expressions and checking that parsing the output results
301  * in the same expression.
302  * Do this for a couple of manually constructed expressions and
303  * a set of expressions parsed from strings.
304  */
test_parse_mupa(isl_ctx * ctx)305 static int test_parse_mupa(isl_ctx *ctx)
306 {
307 	isl_space *space;
308 	isl_multi_union_pw_aff *mupa;
309 	isl_set *dom;
310 	isl_union_set *uset;
311 	isl_stat r;
312 
313 	space = isl_space_set_alloc(ctx, 0, 0);
314 	space = isl_space_set_tuple_name(space, isl_dim_set, "A");
315 	mupa = isl_multi_union_pw_aff_zero(space);
316 	r = check_reparse_multi_union_pw_aff(ctx, mupa);
317 	if (r < 0)
318 		return -1;
319 
320 	space = isl_space_set_alloc(ctx, 1, 0);
321 	space = isl_space_set_dim_name(space, isl_dim_param, 0, "N");
322 	space = isl_space_set_tuple_name(space, isl_dim_set, "A");
323 	dom = isl_set_universe(space);
324 	dom = isl_set_lower_bound_si(dom, isl_dim_param, 0, 5);
325 	uset = isl_union_set_from_set(dom);
326 	space = isl_space_set_alloc(ctx, 1, 0);
327 	space = isl_space_set_dim_name(space, isl_dim_param, 0, "N");
328 	space = isl_space_set_tuple_name(space, isl_dim_set, "B");
329 	mupa = isl_multi_union_pw_aff_zero(space);
330 	mupa = isl_multi_union_pw_aff_intersect_domain(mupa, uset);
331 	r = check_reparse_multi_union_pw_aff(ctx, mupa);
332 	if (r < 0)
333 		return -1;
334 
335 	if (check_reparse_multi_union_pw_aff_tests(ctx) < 0)
336 		return -1;
337 
338 	return 0;
339 }
340 
341 /* Test parsing of multi expressions.
342  */
test_parse_multi(isl_ctx * ctx)343 static int test_parse_multi(isl_ctx *ctx)
344 {
345 	if (test_parse_mpa(ctx) < 0)
346 		return -1;
347 	if (test_parse_mupa(ctx) < 0)
348 		return -1;
349 
350 	return 0;
351 }
352 
353 /* Pairs of binary relation representations that should represent
354  * the same binary relations.
355  */
356 struct {
357 	const char *map1;
358 	const char *map2;
359 } parse_map_equal_tests[] = {
360 	{ "{ [x,y]  : [([x/2]+y)/3] >= 1 }",
361 	  "{ [x, y] : 2y >= 6 - x }" },
362 	{ "{ [x,y] : x <= min(y, 2*y+3) }",
363 	  "{ [x,y] : x <= y, 2*y + 3 }" },
364 	{ "{ [x,y] : x >= min(y, 2*y+3) }",
365 	  "{ [x, y] : (y <= x and y >= -3) or (2y <= -3 + x and y <= -4) }" },
366 	{ "[n] -> { [c1] : c1>=0 and c1<=floord(n-4,3) }",
367 	  "[n] -> { [c1] : c1 >= 0 and 3c1 <= -4 + n }" },
368 	{ "{ [i,j] -> [i] : i < j; [i,j] -> [j] : j <= i }",
369 	  "{ [i,j] -> [min(i,j)] }" },
370 	{ "{ [i,j] : i != j }",
371 	  "{ [i,j] : i < j or i > j }" },
372 	{ "{ [i,j] : (i+1)*2 >= j }",
373 	  "{ [i, j] : j <= 2 + 2i }" },
374 	{ "{ [i] -> [i > 0 ? 4 : 5] }",
375 	  "{ [i] -> [5] : i <= 0; [i] -> [4] : i >= 1 }" },
376 	{ "[N=2,M] -> { [i=[(M+N)/4]] }",
377 	  "[N, M] -> { [i] : N = 2 and 4i <= 2 + M and 4i >= -1 + M }" },
378 	{ "{ [x] : x >= 0 }",
379 	  "{ [x] : x-0 >= 0 }" },
380 	{ "{ [i] : ((i > 10)) }",
381 	  "{ [i] : i >= 11 }" },
382 	{ "{ [i] -> [0] }",
383 	  "{ [i] -> [0 * i] }" },
384 	{ "{ [a] -> [b] : (not false) }",
385 	  "{ [a] -> [b] : true }" },
386 	{ "{ [i] : i/2 <= 5 }",
387 	  "{ [i] : i <= 10 }" },
388 	{ "{Sym=[n] [i] : i <= n }",
389 	  "[n] -> { [i] : i <= n }" },
390 	{ "{ [*] }",
391 	  "{ [a] }" },
392 	{ "{ [i] : 2*floor(i/2) = i }",
393 	  "{ [i] : exists a : i = 2 a }" },
394 	{ "{ [a] -> [b] : a = 5 implies b = 5 }",
395 	  "{ [a] -> [b] : a != 5 or b = 5 }" },
396 	{ "{ [a] -> [a - 1 : a > 0] }",
397 	  "{ [a] -> [a - 1] : a > 0 }" },
398 	{ "{ [a] -> [a - 1 : a > 0; a : a <= 0] }",
399 	  "{ [a] -> [a - 1] : a > 0; [a] -> [a] : a <= 0 }" },
400 	{ "{ [a] -> [(a) * 2 : a >= 0; 0 : a < 0] }",
401 	  "{ [a] -> [2a] : a >= 0; [a] -> [0] : a < 0 }" },
402 	{ "{ [a] -> [(a * 2) : a >= 0; 0 : a < 0] }",
403 	  "{ [a] -> [2a] : a >= 0; [a] -> [0] : a < 0 }" },
404 	{ "{ [a] -> [(a * 2 : a >= 0); 0 : a < 0] }",
405 	  "{ [a] -> [2a] : a >= 0; [a] -> [0] : a < 0 }" },
406 	{ "{ [a] -> [(a * 2 : a >= 0; 0 : a < 0)] }",
407 	  "{ [a] -> [2a] : a >= 0; [a] -> [0] : a < 0 }" },
408 	{ "{ [a,b] -> [i,j] : a,b << i,j }",
409 	  "{ [a,b] -> [i,j] : a < i or (a = i and b < j) }" },
410 	{ "{ [a,b] -> [i,j] : a,b <<= i,j }",
411 	  "{ [a,b] -> [i,j] : a < i or (a = i and b <= j) }" },
412 	{ "{ [a,b] -> [i,j] : a,b >> i,j }",
413 	  "{ [a,b] -> [i,j] : a > i or (a = i and b > j) }" },
414 	{ "{ [a,b] -> [i,j] : a,b >>= i,j }",
415 	  "{ [a,b] -> [i,j] : a > i or (a = i and b >= j) }" },
416 	{ "{ [n] -> [i] : exists (a, b, c: 8b <= i - 32a and "
417 			    "8b >= -7 + i - 32 a and b >= 0 and b <= 3 and "
418 			    "8c < n - 32a and i < n and c >= 0 and "
419 			    "c <= 3 and c >= -4a) }",
420 	  "{ [n] -> [i] : 0 <= i < n }" },
421 	{ "{ [x] -> [] : exists (a, b: 0 <= a <= 1 and 0 <= b <= 3 and "
422 			    "2b <= x - 8a and 2b >= -1 + x - 8a) }",
423 	  "{ [x] -> [] : 0 <= x <= 15 }" },
424 	{ "{ [x] -> [x] : }",
425 	  "{ [x] -> [x] }" },
426 	{ "{ [x=4:5] -> [x + 1] }",
427 	  "{ [x] -> [x + 1] : 4 <= x <= 5 }" },
428 	{ "{ [x=4:5] -> [x + 1 : x + 1] }",
429 	  "{ [x=4:5] -> [x + 1] }" },
430 	{ "{ [x] -> [x - 1 : x + 1] }",
431 	  "{ [x] -> [y] : x - 1 <= y <= x + 1 }" },
432 	{ "{ [x=4:] -> [x + 1] }",
433 	  "{ [x] -> [x + 1] : 4 <= x }" },
434 	{ "{ [x=:5] -> [x + 1] }",
435 	  "{ [x] -> [x + 1] : x <= 5 }" },
436 	{ "{ [x=:] -> [x + 1] }",
437 	  "{ [x] -> [x + 1] }" },
438 	{ "{ [:] -> [:] }",
439 	  "{ [x] -> [y] }" },
440 	{ "{ [x, x//4] }",
441 	  "{ [x, floor(x/4)] }" },
442 	{ "{ [10//4] }",
443 	  "{ [2] }" },
444 };
445 
test_parse(struct isl_ctx * ctx)446 int test_parse(struct isl_ctx *ctx)
447 {
448 	int i;
449 	isl_map *map, *map2;
450 	const char *str, *str2;
451 
452 	if (test_parse_multi_val(ctx, "{ A[B[2] -> C[5, 7]] }") < 0)
453 		return -1;
454 	if (test_parse_multi_val(ctx, "[n] -> { [2] }") < 0)
455 		return -1;
456 	if (test_parse_multi_val(ctx, "{ A[4, infty, NaN, -1/2, 2/3] }") < 0)
457 		return -1;
458 	if (test_parse_multi(ctx) < 0)
459 		return -1;
460 	if (test_parse_pma(ctx) < 0)
461 		return -1;
462 	if (test_parse_upma(ctx) < 0)
463 		return -1;
464 
465 	str = "{ [i] -> [-i] }";
466 	map = isl_map_read_from_str(ctx, str);
467 	assert(map);
468 	isl_map_free(map);
469 
470 	str = "{ A[i] -> L[([i/3])] }";
471 	map = isl_map_read_from_str(ctx, str);
472 	assert(map);
473 	isl_map_free(map);
474 
475 	test_parse_map(ctx, "{[[s] -> A[i]] -> [[s+1] -> A[i]]}");
476 	test_parse_map(ctx, "{ [p1, y1, y2] -> [2, y1, y2] : "
477 				"p1 = 1 && (y1 <= y2 || y2 = 0) }");
478 
479 	for (i = 0; i < ARRAY_SIZE(parse_map_equal_tests); ++i) {
480 		str = parse_map_equal_tests[i].map1;
481 		str2 = parse_map_equal_tests[i].map2;
482 		if (test_parse_map_equal(ctx, str, str2) < 0)
483 			return -1;
484 	}
485 
486 	str = "{[new,old] -> [new+1-2*[(new+1)/2],old+1-2*[(old+1)/2]]}";
487 	map = isl_map_read_from_str(ctx, str);
488 	str = "{ [new, old] -> [o0, o1] : "
489 	       "exists (e0 = [(-1 - new + o0)/2], e1 = [(-1 - old + o1)/2]: "
490 	       "2e0 = -1 - new + o0 and 2e1 = -1 - old + o1 and o0 >= 0 and "
491 	       "o0 <= 1 and o1 >= 0 and o1 <= 1) }";
492 	map2 = isl_map_read_from_str(ctx, str);
493 	assert(isl_map_is_equal(map, map2));
494 	isl_map_free(map);
495 	isl_map_free(map2);
496 
497 	str = "{[new,old] -> [new+1-2*[(new+1)/2],old+1-2*[(old+1)/2]]}";
498 	map = isl_map_read_from_str(ctx, str);
499 	str = "{[new,old] -> [(new+1)%2,(old+1)%2]}";
500 	map2 = isl_map_read_from_str(ctx, str);
501 	assert(isl_map_is_equal(map, map2));
502 	isl_map_free(map);
503 	isl_map_free(map2);
504 
505 	test_parse_pwqp(ctx, "{ [i] -> i + [ (i + [i/3])/2 ] }");
506 	test_parse_map(ctx, "{ S1[i] -> [([i/10]),i%10] : 0 <= i <= 45 }");
507 	test_parse_pwaff(ctx, "{ [i] -> [i + 1] : i > 0; [a] -> [a] : a < 0 }");
508 	test_parse_pwqp(ctx, "{ [x] -> ([(x)/2] * [(x)/3]) }");
509 	test_parse_pwaff(ctx, "{ [] -> [(100)] }");
510 
511 	return 0;
512 }
513 
test_read(isl_ctx * ctx)514 static int test_read(isl_ctx *ctx)
515 {
516 	char *filename;
517 	FILE *input;
518 	isl_basic_set *bset1, *bset2;
519 	const char *str = "{[y]: Exists ( alpha : 2alpha = y)}";
520 	int equal;
521 
522 	filename = get_filename(ctx, "set", "omega");
523 	assert(filename);
524 	input = fopen(filename, "r");
525 	assert(input);
526 
527 	bset1 = isl_basic_set_read_from_file(ctx, input);
528 	bset2 = isl_basic_set_read_from_str(ctx, str);
529 
530 	equal = isl_basic_set_is_equal(bset1, bset2);
531 
532 	isl_basic_set_free(bset1);
533 	isl_basic_set_free(bset2);
534 	free(filename);
535 
536 	fclose(input);
537 
538 	if (equal < 0)
539 		return -1;
540 	if (!equal)
541 		isl_die(ctx, isl_error_unknown,
542 			"read sets not equal", return -1);
543 
544 	return 0;
545 }
546 
test_bounded(isl_ctx * ctx)547 static int test_bounded(isl_ctx *ctx)
548 {
549 	isl_set *set;
550 	isl_bool bounded;
551 
552 	set = isl_set_read_from_str(ctx, "[n] -> {[i] : 0 <= i <= n }");
553 	bounded = isl_set_is_bounded(set);
554 	isl_set_free(set);
555 
556 	if (bounded < 0)
557 		return -1;
558 	if (!bounded)
559 		isl_die(ctx, isl_error_unknown,
560 			"set not considered bounded", return -1);
561 
562 	set = isl_set_read_from_str(ctx, "{[n, i] : 0 <= i <= n }");
563 	bounded = isl_set_is_bounded(set);
564 	assert(!bounded);
565 	isl_set_free(set);
566 
567 	if (bounded < 0)
568 		return -1;
569 	if (bounded)
570 		isl_die(ctx, isl_error_unknown,
571 			"set considered bounded", return -1);
572 
573 	set = isl_set_read_from_str(ctx, "[n] -> {[i] : i <= n }");
574 	bounded = isl_set_is_bounded(set);
575 	isl_set_free(set);
576 
577 	if (bounded < 0)
578 		return -1;
579 	if (bounded)
580 		isl_die(ctx, isl_error_unknown,
581 			"set considered bounded", return -1);
582 
583 	return 0;
584 }
585 
586 /* Construct the basic set { [i] : 5 <= i <= N } */
test_construction_1(isl_ctx * ctx)587 static int test_construction_1(isl_ctx *ctx)
588 {
589 	isl_space *space;
590 	isl_local_space *ls;
591 	isl_basic_set *bset;
592 	isl_constraint *c;
593 
594 	space = isl_space_set_alloc(ctx, 1, 1);
595 	bset = isl_basic_set_universe(isl_space_copy(space));
596 	ls = isl_local_space_from_space(space);
597 
598 	c = isl_constraint_alloc_inequality(isl_local_space_copy(ls));
599 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, -1);
600 	c = isl_constraint_set_coefficient_si(c, isl_dim_param, 0, 1);
601 	bset = isl_basic_set_add_constraint(bset, c);
602 
603 	c = isl_constraint_alloc_inequality(isl_local_space_copy(ls));
604 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, 1);
605 	c = isl_constraint_set_constant_si(c, -5);
606 	bset = isl_basic_set_add_constraint(bset, c);
607 
608 	isl_local_space_free(ls);
609 	isl_basic_set_free(bset);
610 
611 	return 0;
612 }
613 
614 /* Construct the basic set { [x] : -100 <= x <= 100 }
615  * using isl_basic_set_{lower,upper}_bound_val and
616  * check that it is equal the same basic set parsed from a string.
617  */
test_construction_2(isl_ctx * ctx)618 static int test_construction_2(isl_ctx *ctx)
619 {
620 	isl_bool equal;
621 	isl_val *v;
622 	isl_space *space;
623 	isl_basic_set *bset1, *bset2;
624 
625 	v = isl_val_int_from_si(ctx, 100);
626 	space = isl_space_set_alloc(ctx, 0, 1);
627 	bset1 = isl_basic_set_universe(space);
628 	bset1 = isl_basic_set_upper_bound_val(bset1, isl_dim_set, 0,
629 						isl_val_copy(v));
630 	bset1 = isl_basic_set_lower_bound_val(bset1, isl_dim_set, 0,
631 						isl_val_neg(v));
632 	bset2 = isl_basic_set_read_from_str(ctx, "{ [x] : -100 <= x <= 100 }");
633 	equal = isl_basic_set_is_equal(bset1, bset2);
634 	isl_basic_set_free(bset1);
635 	isl_basic_set_free(bset2);
636 
637 	if (equal < 0)
638 		return -1;
639 	if (!equal)
640 		isl_die(ctx, isl_error_unknown,
641 			"failed construction", return -1);
642 
643 	return 0;
644 }
645 
646 /* Basic tests for constructing basic sets.
647  */
test_construction(isl_ctx * ctx)648 static int test_construction(isl_ctx *ctx)
649 {
650 	if (test_construction_1(ctx) < 0)
651 		return -1;
652 	if (test_construction_2(ctx) < 0)
653 		return -1;
654 	return 0;
655 }
656 
test_dim(isl_ctx * ctx)657 static int test_dim(isl_ctx *ctx)
658 {
659 	const char *str;
660 	isl_map *map1, *map2;
661 	int equal;
662 
663 	map1 = isl_map_read_from_str(ctx,
664 	    "[n] -> { [i] -> [j] : exists (a = [i/10] : i - 10a <= n ) }");
665 	map1 = isl_map_add_dims(map1, isl_dim_in, 1);
666 	map2 = isl_map_read_from_str(ctx,
667 	    "[n] -> { [i,k] -> [j] : exists (a = [i/10] : i - 10a <= n ) }");
668 	equal = isl_map_is_equal(map1, map2);
669 	isl_map_free(map2);
670 
671 	map1 = isl_map_project_out(map1, isl_dim_in, 0, 1);
672 	map2 = isl_map_read_from_str(ctx, "[n] -> { [i] -> [j] : n >= 0 }");
673 	if (equal >= 0 && equal)
674 		equal = isl_map_is_equal(map1, map2);
675 
676 	isl_map_free(map1);
677 	isl_map_free(map2);
678 
679 	if (equal < 0)
680 		return -1;
681 	if (!equal)
682 		isl_die(ctx, isl_error_unknown,
683 			"unexpected result", return -1);
684 
685 	str = "[n] -> { [i] -> [] : exists a : 0 <= i <= n and i = 2 a }";
686 	map1 = isl_map_read_from_str(ctx, str);
687 	str = "{ [i] -> [j] : exists a : 0 <= i <= j and i = 2 a }";
688 	map2 = isl_map_read_from_str(ctx, str);
689 	map1 = isl_map_move_dims(map1, isl_dim_out, 0, isl_dim_param, 0, 1);
690 	equal = isl_map_is_equal(map1, map2);
691 	isl_map_free(map1);
692 	isl_map_free(map2);
693 
694 	if (equal < 0)
695 		return -1;
696 	if (!equal)
697 		isl_die(ctx, isl_error_unknown,
698 			"unexpected result", return -1);
699 
700 	return 0;
701 }
702 
703 #undef BASE
704 #define BASE	multi_val
705 #include "isl_test_plain_equal_templ.c"
706 
707 #undef BASE
708 #define BASE	multi_aff
709 #include "isl_test_plain_equal_templ.c"
710 
711 /* Check that "val" is equal to the value described by "str".
712  * If "str" is "NaN", then check for a NaN value explicitly.
713  */
val_check_equal(__isl_keep isl_val * val,const char * str)714 static isl_stat val_check_equal(__isl_keep isl_val *val, const char *str)
715 {
716 	isl_bool ok, is_nan;
717 	isl_ctx *ctx;
718 	isl_val *res;
719 
720 	if (!val)
721 		return isl_stat_error;
722 
723 	ctx = isl_val_get_ctx(val);
724 	res = isl_val_read_from_str(ctx, str);
725 	is_nan = isl_val_is_nan(res);
726 	if (is_nan < 0)
727 		ok = isl_bool_error;
728 	else if (is_nan)
729 		ok = isl_val_is_nan(val);
730 	else
731 		ok = isl_val_eq(val, res);
732 	isl_val_free(res);
733 	if (ok < 0)
734 		return isl_stat_error;
735 	if (!ok)
736 		isl_die(ctx, isl_error_unknown,
737 			"unexpected result", return isl_stat_error);
738 	return isl_stat_ok;
739 }
740 
741 struct {
742 	__isl_give isl_val *(*op)(__isl_take isl_val *v);
743 	const char *arg;
744 	const char *res;
745 } val_un_tests[] = {
746 	{ &isl_val_neg, "0", "0" },
747 	{ &isl_val_abs, "0", "0" },
748 	{ &isl_val_pow2, "0", "1" },
749 	{ &isl_val_floor, "0", "0" },
750 	{ &isl_val_ceil, "0", "0" },
751 	{ &isl_val_neg, "1", "-1" },
752 	{ &isl_val_neg, "-1", "1" },
753 	{ &isl_val_neg, "1/2", "-1/2" },
754 	{ &isl_val_neg, "-1/2", "1/2" },
755 	{ &isl_val_neg, "infty", "-infty" },
756 	{ &isl_val_neg, "-infty", "infty" },
757 	{ &isl_val_neg, "NaN", "NaN" },
758 	{ &isl_val_abs, "1", "1" },
759 	{ &isl_val_abs, "-1", "1" },
760 	{ &isl_val_abs, "1/2", "1/2" },
761 	{ &isl_val_abs, "-1/2", "1/2" },
762 	{ &isl_val_abs, "infty", "infty" },
763 	{ &isl_val_abs, "-infty", "infty" },
764 	{ &isl_val_abs, "NaN", "NaN" },
765 	{ &isl_val_floor, "1", "1" },
766 	{ &isl_val_floor, "-1", "-1" },
767 	{ &isl_val_floor, "1/2", "0" },
768 	{ &isl_val_floor, "-1/2", "-1" },
769 	{ &isl_val_floor, "infty", "infty" },
770 	{ &isl_val_floor, "-infty", "-infty" },
771 	{ &isl_val_floor, "NaN", "NaN" },
772 	{ &isl_val_ceil, "1", "1" },
773 	{ &isl_val_ceil, "-1", "-1" },
774 	{ &isl_val_ceil, "1/2", "1" },
775 	{ &isl_val_ceil, "-1/2", "0" },
776 	{ &isl_val_ceil, "infty", "infty" },
777 	{ &isl_val_ceil, "-infty", "-infty" },
778 	{ &isl_val_ceil, "NaN", "NaN" },
779 	{ &isl_val_pow2, "-3", "1/8" },
780 	{ &isl_val_pow2, "-1", "1/2" },
781 	{ &isl_val_pow2, "1", "2" },
782 	{ &isl_val_pow2, "2", "4" },
783 	{ &isl_val_pow2, "3", "8" },
784 	{ &isl_val_inv, "1", "1" },
785 	{ &isl_val_inv, "2", "1/2" },
786 	{ &isl_val_inv, "1/2", "2" },
787 	{ &isl_val_inv, "-2", "-1/2" },
788 	{ &isl_val_inv, "-1/2", "-2" },
789 	{ &isl_val_inv, "0", "NaN" },
790 	{ &isl_val_inv, "NaN", "NaN" },
791 	{ &isl_val_inv, "infty", "0" },
792 	{ &isl_val_inv, "-infty", "0" },
793 };
794 
795 /* Perform some basic tests of unary operations on isl_val objects.
796  */
test_un_val(isl_ctx * ctx)797 static int test_un_val(isl_ctx *ctx)
798 {
799 	int i;
800 	isl_val *v;
801 	__isl_give isl_val *(*fn)(__isl_take isl_val *v);
802 
803 	for (i = 0; i < ARRAY_SIZE(val_un_tests); ++i) {
804 		isl_stat r;
805 
806 		v = isl_val_read_from_str(ctx, val_un_tests[i].arg);
807 		fn = val_un_tests[i].op;
808 		v = fn(v);
809 		r = val_check_equal(v, val_un_tests[i].res);
810 		isl_val_free(v);
811 		if (r < 0)
812 			return -1;
813 	}
814 
815 	return 0;
816 }
817 
818 struct {
819 	__isl_give isl_val *(*fn)(__isl_take isl_val *v1,
820 				__isl_take isl_val *v2);
821 } val_bin_op[] = {
822 	['+'] = { &isl_val_add },
823 	['-'] = { &isl_val_sub },
824 	['*'] = { &isl_val_mul },
825 	['/'] = { &isl_val_div },
826 	['g'] = { &isl_val_gcd },
827 	['m'] = { &isl_val_min },
828 	['M'] = { &isl_val_max },
829 };
830 
831 struct {
832 	const char *arg1;
833 	unsigned char op;
834 	const char *arg2;
835 	const char *res;
836 } val_bin_tests[] = {
837 	{ "0", '+', "0", "0" },
838 	{ "1", '+', "0", "1" },
839 	{ "1", '+', "1", "2" },
840 	{ "1", '-', "1", "0" },
841 	{ "1", '*', "1", "1" },
842 	{ "1", '/', "1", "1" },
843 	{ "2", '*', "3", "6" },
844 	{ "2", '*', "1/2", "1" },
845 	{ "2", '*', "1/3", "2/3" },
846 	{ "2/3", '*', "3/5", "2/5" },
847 	{ "2/3", '*', "7/5", "14/15" },
848 	{ "2", '/', "1/2", "4" },
849 	{ "-2", '/', "-1/2", "4" },
850 	{ "-2", '/', "1/2", "-4" },
851 	{ "2", '/', "-1/2", "-4" },
852 	{ "2", '/', "2", "1" },
853 	{ "2", '/', "3", "2/3" },
854 	{ "2/3", '/', "5/3", "2/5" },
855 	{ "2/3", '/', "5/7", "14/15" },
856 	{ "0", '/', "0", "NaN" },
857 	{ "42", '/', "0", "NaN" },
858 	{ "-42", '/', "0", "NaN" },
859 	{ "infty", '/', "0", "NaN" },
860 	{ "-infty", '/', "0", "NaN" },
861 	{ "NaN", '/', "0", "NaN" },
862 	{ "0", '/', "NaN", "NaN" },
863 	{ "42", '/', "NaN", "NaN" },
864 	{ "-42", '/', "NaN", "NaN" },
865 	{ "infty", '/', "NaN", "NaN" },
866 	{ "-infty", '/', "NaN", "NaN" },
867 	{ "NaN", '/', "NaN", "NaN" },
868 	{ "0", '/', "infty", "0" },
869 	{ "42", '/', "infty", "0" },
870 	{ "-42", '/', "infty", "0" },
871 	{ "infty", '/', "infty", "NaN" },
872 	{ "-infty", '/', "infty", "NaN" },
873 	{ "NaN", '/', "infty", "NaN" },
874 	{ "0", '/', "-infty", "0" },
875 	{ "42", '/', "-infty", "0" },
876 	{ "-42", '/', "-infty", "0" },
877 	{ "infty", '/', "-infty", "NaN" },
878 	{ "-infty", '/', "-infty", "NaN" },
879 	{ "NaN", '/', "-infty", "NaN" },
880 	{ "1", '-', "1/3", "2/3" },
881 	{ "1/3", '+', "1/2", "5/6" },
882 	{ "1/2", '+', "1/2", "1" },
883 	{ "3/4", '-', "1/4", "1/2" },
884 	{ "1/2", '-', "1/3", "1/6" },
885 	{ "infty", '+', "42", "infty" },
886 	{ "infty", '+', "infty", "infty" },
887 	{ "42", '+', "infty", "infty" },
888 	{ "infty", '-', "infty", "NaN" },
889 	{ "infty", '*', "infty", "infty" },
890 	{ "infty", '*', "-infty", "-infty" },
891 	{ "-infty", '*', "infty", "-infty" },
892 	{ "-infty", '*', "-infty", "infty" },
893 	{ "0", '*', "infty", "NaN" },
894 	{ "1", '*', "infty", "infty" },
895 	{ "infty", '*', "0", "NaN" },
896 	{ "infty", '*', "42", "infty" },
897 	{ "42", '-', "infty", "-infty" },
898 	{ "infty", '+', "-infty", "NaN" },
899 	{ "4", 'g', "6", "2" },
900 	{ "5", 'g', "6", "1" },
901 	{ "42", 'm', "3", "3" },
902 	{ "42", 'M', "3", "42" },
903 	{ "3", 'm', "42", "3" },
904 	{ "3", 'M', "42", "42" },
905 	{ "42", 'm', "infty", "42" },
906 	{ "42", 'M', "infty", "infty" },
907 	{ "42", 'm', "-infty", "-infty" },
908 	{ "42", 'M', "-infty", "42" },
909 	{ "42", 'm', "NaN", "NaN" },
910 	{ "42", 'M', "NaN", "NaN" },
911 	{ "infty", 'm', "-infty", "-infty" },
912 	{ "infty", 'M', "-infty", "infty" },
913 };
914 
915 /* Perform some basic tests of binary operations on isl_val objects.
916  */
test_bin_val(isl_ctx * ctx)917 static int test_bin_val(isl_ctx *ctx)
918 {
919 	int i;
920 	isl_val *v1, *v2, *res;
921 	__isl_give isl_val *(*fn)(__isl_take isl_val *v1,
922 				__isl_take isl_val *v2);
923 	int ok;
924 
925 	for (i = 0; i < ARRAY_SIZE(val_bin_tests); ++i) {
926 		v1 = isl_val_read_from_str(ctx, val_bin_tests[i].arg1);
927 		v2 = isl_val_read_from_str(ctx, val_bin_tests[i].arg2);
928 		res = isl_val_read_from_str(ctx, val_bin_tests[i].res);
929 		fn = val_bin_op[val_bin_tests[i].op].fn;
930 		v1 = fn(v1, v2);
931 		if (isl_val_is_nan(res))
932 			ok = isl_val_is_nan(v1);
933 		else
934 			ok = isl_val_eq(v1, res);
935 		isl_val_free(v1);
936 		isl_val_free(res);
937 		if (ok < 0)
938 			return -1;
939 		if (!ok)
940 			isl_die(ctx, isl_error_unknown,
941 				"unexpected result", return -1);
942 	}
943 
944 	return 0;
945 }
946 
947 /* Perform some basic tests on isl_val objects.
948  */
test_val(isl_ctx * ctx)949 static int test_val(isl_ctx *ctx)
950 {
951 	if (test_un_val(ctx) < 0)
952 		return -1;
953 	if (test_bin_val(ctx) < 0)
954 		return -1;
955 	return 0;
956 }
957 
958 /* Sets described using existentially quantified variables that
959  * can also be described without.
960  */
961 static const char *elimination_tests[] = {
962 	"{ [i,j] : 2 * [i/2] + 3 * [j/4] <= 10 and 2 i = j }",
963 	"{ [m, w] : exists a : w - 2m - 5 <= 3a <= m - 2w }",
964 	"{ [m, w] : exists a : w >= 0 and a < m and -1 + w <= a <= 2m - w }",
965 };
966 
967 /* Check that redundant existentially quantified variables are
968  * getting removed.
969  */
test_elimination(isl_ctx * ctx)970 static int test_elimination(isl_ctx *ctx)
971 {
972 	int i;
973 	isl_size n;
974 	isl_basic_set *bset;
975 
976 	for (i = 0; i < ARRAY_SIZE(elimination_tests); ++i) {
977 		bset = isl_basic_set_read_from_str(ctx, elimination_tests[i]);
978 		n = isl_basic_set_dim(bset, isl_dim_div);
979 		isl_basic_set_free(bset);
980 		if (n < 0)
981 			return -1;
982 		if (n != 0)
983 			isl_die(ctx, isl_error_unknown,
984 				"expecting no existentials", return -1);
985 	}
986 
987 	return 0;
988 }
989 
test_div(isl_ctx * ctx)990 static int test_div(isl_ctx *ctx)
991 {
992 	const char *str;
993 	int empty;
994 	isl_space *space;
995 	isl_set *set;
996 	isl_local_space *ls;
997 	struct isl_basic_set *bset;
998 	struct isl_constraint *c;
999 
1000 	/* test 1 */
1001 	space = isl_space_set_alloc(ctx, 0, 3);
1002 	bset = isl_basic_set_universe(isl_space_copy(space));
1003 	ls = isl_local_space_from_space(space);
1004 
1005 	c = isl_constraint_alloc_equality(isl_local_space_copy(ls));
1006 	c = isl_constraint_set_constant_si(c, -1);
1007 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, 1);
1008 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 1, 3);
1009 	bset = isl_basic_set_add_constraint(bset, c);
1010 
1011 	c = isl_constraint_alloc_equality(isl_local_space_copy(ls));
1012 	c = isl_constraint_set_constant_si(c, 1);
1013 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, -1);
1014 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 2, 3);
1015 	bset = isl_basic_set_add_constraint(bset, c);
1016 
1017 	bset = isl_basic_set_project_out(bset, isl_dim_set, 1, 2);
1018 
1019 	assert(bset && bset->n_div == 1);
1020 	isl_local_space_free(ls);
1021 	isl_basic_set_free(bset);
1022 
1023 	/* test 2 */
1024 	space = isl_space_set_alloc(ctx, 0, 3);
1025 	bset = isl_basic_set_universe(isl_space_copy(space));
1026 	ls = isl_local_space_from_space(space);
1027 
1028 	c = isl_constraint_alloc_equality(isl_local_space_copy(ls));
1029 	c = isl_constraint_set_constant_si(c, 1);
1030 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, -1);
1031 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 1, 3);
1032 	bset = isl_basic_set_add_constraint(bset, c);
1033 
1034 	c = isl_constraint_alloc_equality(isl_local_space_copy(ls));
1035 	c = isl_constraint_set_constant_si(c, -1);
1036 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, 1);
1037 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 2, 3);
1038 	bset = isl_basic_set_add_constraint(bset, c);
1039 
1040 	bset = isl_basic_set_project_out(bset, isl_dim_set, 1, 2);
1041 
1042 	assert(bset && bset->n_div == 1);
1043 	isl_local_space_free(ls);
1044 	isl_basic_set_free(bset);
1045 
1046 	/* test 3 */
1047 	space = isl_space_set_alloc(ctx, 0, 3);
1048 	bset = isl_basic_set_universe(isl_space_copy(space));
1049 	ls = isl_local_space_from_space(space);
1050 
1051 	c = isl_constraint_alloc_equality(isl_local_space_copy(ls));
1052 	c = isl_constraint_set_constant_si(c, 1);
1053 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, -1);
1054 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 1, 3);
1055 	bset = isl_basic_set_add_constraint(bset, c);
1056 
1057 	c = isl_constraint_alloc_equality(isl_local_space_copy(ls));
1058 	c = isl_constraint_set_constant_si(c, -3);
1059 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, 1);
1060 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 2, 4);
1061 	bset = isl_basic_set_add_constraint(bset, c);
1062 
1063 	bset = isl_basic_set_project_out(bset, isl_dim_set, 1, 2);
1064 
1065 	assert(bset && bset->n_div == 1);
1066 	isl_local_space_free(ls);
1067 	isl_basic_set_free(bset);
1068 
1069 	/* test 4 */
1070 	space = isl_space_set_alloc(ctx, 0, 3);
1071 	bset = isl_basic_set_universe(isl_space_copy(space));
1072 	ls = isl_local_space_from_space(space);
1073 
1074 	c = isl_constraint_alloc_equality(isl_local_space_copy(ls));
1075 	c = isl_constraint_set_constant_si(c, 2);
1076 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, -1);
1077 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 1, 3);
1078 	bset = isl_basic_set_add_constraint(bset, c);
1079 
1080 	c = isl_constraint_alloc_equality(isl_local_space_copy(ls));
1081 	c = isl_constraint_set_constant_si(c, -1);
1082 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, 1);
1083 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 2, 6);
1084 	bset = isl_basic_set_add_constraint(bset, c);
1085 
1086 	bset = isl_basic_set_project_out(bset, isl_dim_set, 1, 2);
1087 
1088 	assert(isl_basic_set_is_empty(bset));
1089 	isl_local_space_free(ls);
1090 	isl_basic_set_free(bset);
1091 
1092 	/* test 5 */
1093 	space = isl_space_set_alloc(ctx, 0, 3);
1094 	bset = isl_basic_set_universe(isl_space_copy(space));
1095 	ls = isl_local_space_from_space(space);
1096 
1097 	c = isl_constraint_alloc_equality(isl_local_space_copy(ls));
1098 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, -1);
1099 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 2, 3);
1100 	bset = isl_basic_set_add_constraint(bset, c);
1101 
1102 	c = isl_constraint_alloc_equality(isl_local_space_copy(ls));
1103 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, 1);
1104 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 1, -3);
1105 	bset = isl_basic_set_add_constraint(bset, c);
1106 
1107 	bset = isl_basic_set_project_out(bset, isl_dim_set, 2, 1);
1108 
1109 	assert(bset && bset->n_div == 0);
1110 	isl_basic_set_free(bset);
1111 	isl_local_space_free(ls);
1112 
1113 	/* test 6 */
1114 	space = isl_space_set_alloc(ctx, 0, 3);
1115 	bset = isl_basic_set_universe(isl_space_copy(space));
1116 	ls = isl_local_space_from_space(space);
1117 
1118 	c = isl_constraint_alloc_equality(isl_local_space_copy(ls));
1119 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, -1);
1120 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 2, 6);
1121 	bset = isl_basic_set_add_constraint(bset, c);
1122 
1123 	c = isl_constraint_alloc_equality(isl_local_space_copy(ls));
1124 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, 1);
1125 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 1, -3);
1126 	bset = isl_basic_set_add_constraint(bset, c);
1127 
1128 	bset = isl_basic_set_project_out(bset, isl_dim_set, 2, 1);
1129 
1130 	assert(bset && bset->n_div == 1);
1131 	isl_basic_set_free(bset);
1132 	isl_local_space_free(ls);
1133 
1134 	/* test 7 */
1135 	/* This test is a bit tricky.  We set up an equality
1136 	 *		a + 3b + 3c = 6 e0
1137 	 * Normalization of divs creates _two_ divs
1138 	 *		a = 3 e0
1139 	 *		c - b - e0 = 2 e1
1140 	 * Afterwards e0 is removed again because it has coefficient -1
1141 	 * and we end up with the original equality and div again.
1142 	 * Perhaps we can avoid the introduction of this temporary div.
1143 	 */
1144 	space = isl_space_set_alloc(ctx, 0, 4);
1145 	bset = isl_basic_set_universe(isl_space_copy(space));
1146 	ls = isl_local_space_from_space(space);
1147 
1148 	c = isl_constraint_alloc_equality(isl_local_space_copy(ls));
1149 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, -1);
1150 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 1, -3);
1151 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 2, -3);
1152 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 3, 6);
1153 	bset = isl_basic_set_add_constraint(bset, c);
1154 
1155 	bset = isl_basic_set_project_out(bset, isl_dim_set, 3, 1);
1156 
1157 	/* Test disabled for now */
1158 	/*
1159 	assert(bset && bset->n_div == 1);
1160 	*/
1161 	isl_local_space_free(ls);
1162 	isl_basic_set_free(bset);
1163 
1164 	/* test 8 */
1165 	space = isl_space_set_alloc(ctx, 0, 5);
1166 	bset = isl_basic_set_universe(isl_space_copy(space));
1167 	ls = isl_local_space_from_space(space);
1168 
1169 	c = isl_constraint_alloc_equality(isl_local_space_copy(ls));
1170 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, -1);
1171 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 1, -3);
1172 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 3, -3);
1173 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 4, 6);
1174 	bset = isl_basic_set_add_constraint(bset, c);
1175 
1176 	c = isl_constraint_alloc_equality(isl_local_space_copy(ls));
1177 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, -1);
1178 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 2, 1);
1179 	c = isl_constraint_set_constant_si(c, 1);
1180 	bset = isl_basic_set_add_constraint(bset, c);
1181 
1182 	bset = isl_basic_set_project_out(bset, isl_dim_set, 4, 1);
1183 
1184 	/* Test disabled for now */
1185 	/*
1186 	assert(bset && bset->n_div == 1);
1187 	*/
1188 	isl_local_space_free(ls);
1189 	isl_basic_set_free(bset);
1190 
1191 	/* test 9 */
1192 	space = isl_space_set_alloc(ctx, 0, 4);
1193 	bset = isl_basic_set_universe(isl_space_copy(space));
1194 	ls = isl_local_space_from_space(space);
1195 
1196 	c = isl_constraint_alloc_equality(isl_local_space_copy(ls));
1197 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, 1);
1198 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 1, -1);
1199 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 2, -2);
1200 	bset = isl_basic_set_add_constraint(bset, c);
1201 
1202 	c = isl_constraint_alloc_equality(isl_local_space_copy(ls));
1203 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, -1);
1204 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 3, 3);
1205 	c = isl_constraint_set_constant_si(c, 2);
1206 	bset = isl_basic_set_add_constraint(bset, c);
1207 
1208 	bset = isl_basic_set_project_out(bset, isl_dim_set, 2, 2);
1209 
1210 	bset = isl_basic_set_fix_si(bset, isl_dim_set, 0, 2);
1211 
1212 	assert(!isl_basic_set_is_empty(bset));
1213 
1214 	isl_local_space_free(ls);
1215 	isl_basic_set_free(bset);
1216 
1217 	/* test 10 */
1218 	space = isl_space_set_alloc(ctx, 0, 3);
1219 	bset = isl_basic_set_universe(isl_space_copy(space));
1220 	ls = isl_local_space_from_space(space);
1221 
1222 	c = isl_constraint_alloc_equality(isl_local_space_copy(ls));
1223 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, 1);
1224 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 2, -2);
1225 	bset = isl_basic_set_add_constraint(bset, c);
1226 
1227 	bset = isl_basic_set_project_out(bset, isl_dim_set, 2, 1);
1228 
1229 	bset = isl_basic_set_fix_si(bset, isl_dim_set, 0, 2);
1230 
1231 	isl_local_space_free(ls);
1232 	isl_basic_set_free(bset);
1233 
1234 	str = "{ [i] : exists (e0, e1: 3e1 >= 1 + 2e0 and "
1235 	    "8e1 <= -1 + 5i - 5e0 and 2e1 >= 1 + 2i - 5e0) }";
1236 	set = isl_set_read_from_str(ctx, str);
1237 	set = isl_set_compute_divs(set);
1238 	isl_set_free(set);
1239 	if (!set)
1240 		return -1;
1241 
1242 	if (test_elimination(ctx) < 0)
1243 		return -1;
1244 
1245 	str = "{ [i,j,k] : 3 + i + 2j >= 0 and 2 * [(i+2j)/4] <= k }";
1246 	set = isl_set_read_from_str(ctx, str);
1247 	set = isl_set_remove_divs_involving_dims(set, isl_dim_set, 0, 2);
1248 	set = isl_set_fix_si(set, isl_dim_set, 2, -3);
1249 	empty = isl_set_is_empty(set);
1250 	isl_set_free(set);
1251 	if (empty < 0)
1252 		return -1;
1253 	if (!empty)
1254 		isl_die(ctx, isl_error_unknown,
1255 			"result not as accurate as expected", return -1);
1256 
1257 	return 0;
1258 }
1259 
test_application_case(struct isl_ctx * ctx,const char * name)1260 void test_application_case(struct isl_ctx *ctx, const char *name)
1261 {
1262 	char *filename;
1263 	FILE *input;
1264 	struct isl_basic_set *bset1, *bset2;
1265 	struct isl_basic_map *bmap;
1266 
1267 	filename = get_filename(ctx, name, "omega");
1268 	assert(filename);
1269 	input = fopen(filename, "r");
1270 	assert(input);
1271 
1272 	bset1 = isl_basic_set_read_from_file(ctx, input);
1273 	bmap = isl_basic_map_read_from_file(ctx, input);
1274 
1275 	bset1 = isl_basic_set_apply(bset1, bmap);
1276 
1277 	bset2 = isl_basic_set_read_from_file(ctx, input);
1278 
1279 	assert(isl_basic_set_is_equal(bset1, bset2) == 1);
1280 
1281 	isl_basic_set_free(bset1);
1282 	isl_basic_set_free(bset2);
1283 	free(filename);
1284 
1285 	fclose(input);
1286 }
1287 
test_application(isl_ctx * ctx)1288 static int test_application(isl_ctx *ctx)
1289 {
1290 	test_application_case(ctx, "application");
1291 	test_application_case(ctx, "application2");
1292 
1293 	return 0;
1294 }
1295 
test_affine_hull_case(struct isl_ctx * ctx,const char * name)1296 void test_affine_hull_case(struct isl_ctx *ctx, const char *name)
1297 {
1298 	char *filename;
1299 	FILE *input;
1300 	struct isl_basic_set *bset1, *bset2;
1301 
1302 	filename = get_filename(ctx, name, "polylib");
1303 	assert(filename);
1304 	input = fopen(filename, "r");
1305 	assert(input);
1306 
1307 	bset1 = isl_basic_set_read_from_file(ctx, input);
1308 	bset2 = isl_basic_set_read_from_file(ctx, input);
1309 
1310 	bset1 = isl_basic_set_affine_hull(bset1);
1311 
1312 	assert(isl_basic_set_is_equal(bset1, bset2) == 1);
1313 
1314 	isl_basic_set_free(bset1);
1315 	isl_basic_set_free(bset2);
1316 	free(filename);
1317 
1318 	fclose(input);
1319 }
1320 
1321 /* Pairs of sets and the corresponding expected results of
1322  * isl_basic_set_recession_cone.
1323  */
1324 struct {
1325 	const char *set;
1326 	const char *cone;
1327 } recession_cone_tests[] = {
1328 	{ "{ [i] : 0 <= i <= 10 }", "{ [0] }" },
1329 	{ "{ [i] : 0 <= i }", "{ [i] : 0 <= i }" },
1330 	{ "{ [i] : i <= 10 }", "{ [i] : i <= 0 }" },
1331 	{ "{ [i] : false }", "{ [i] : false }" },
1332 };
1333 
1334 /* Perform some basic isl_basic_set_recession_cone tests.
1335  */
test_recession_cone(struct isl_ctx * ctx)1336 static int test_recession_cone(struct isl_ctx *ctx)
1337 {
1338 	int i;
1339 
1340 	for (i = 0; i < ARRAY_SIZE(recession_cone_tests); ++i) {
1341 		const char *str;
1342 		isl_basic_set *bset;
1343 		isl_basic_set *cone, *expected;
1344 		isl_bool equal;
1345 
1346 		str = recession_cone_tests[i].set;
1347 		bset = isl_basic_set_read_from_str(ctx, str);
1348 		str = recession_cone_tests[i].cone;
1349 		expected = isl_basic_set_read_from_str(ctx, str);
1350 		cone = isl_basic_set_recession_cone(bset);
1351 		equal = isl_basic_set_is_equal(cone, expected);
1352 		isl_basic_set_free(cone);
1353 		isl_basic_set_free(expected);
1354 		if (equal < 0)
1355 			return -1;
1356 		if (!equal)
1357 			isl_die(ctx, isl_error_unknown, "unexpected cone",
1358 				return -1);
1359 	}
1360 
1361 	return 0;
1362 }
1363 
test_affine_hull(struct isl_ctx * ctx)1364 int test_affine_hull(struct isl_ctx *ctx)
1365 {
1366 	const char *str;
1367 	isl_set *set;
1368 	isl_basic_set *bset, *bset2;
1369 	isl_size n;
1370 	isl_bool subset;
1371 
1372 	test_affine_hull_case(ctx, "affine2");
1373 	test_affine_hull_case(ctx, "affine");
1374 	test_affine_hull_case(ctx, "affine3");
1375 
1376 	str = "[m] -> { [i0] : exists (e0, e1: e1 <= 1 + i0 and "
1377 			"m >= 3 and 4i0 <= 2 + m and e1 >= i0 and "
1378 			"e1 >= 0 and e1 <= 2 and e1 >= 1 + 2e0 and "
1379 			"2e1 <= 1 + m + 4e0 and 2e1 >= 2 - m + 4i0 - 4e0) }";
1380 	set = isl_set_read_from_str(ctx, str);
1381 	bset = isl_set_affine_hull(set);
1382 	n = isl_basic_set_dim(bset, isl_dim_div);
1383 	isl_basic_set_free(bset);
1384 	if (n < 0)
1385 		return -1;
1386 	if (n != 0)
1387 		isl_die(ctx, isl_error_unknown, "not expecting any divs",
1388 			return -1);
1389 
1390 	/* Check that isl_map_affine_hull is not confused by
1391 	 * the reordering of divs in isl_map_align_divs.
1392 	 */
1393 	str = "{ [a, b, c, 0] : exists (e0 = [(b)/32], e1 = [(c)/32]: "
1394 				"32e0 = b and 32e1 = c); "
1395 		"[a, 0, c, 0] : exists (e0 = [(c)/32]: 32e0 = c) }";
1396 	set = isl_set_read_from_str(ctx, str);
1397 	bset = isl_set_affine_hull(set);
1398 	isl_basic_set_free(bset);
1399 	if (!bset)
1400 		return -1;
1401 
1402 	str = "{ [a] : exists e0, e1, e2: 32e1 = 31 + 31a + 31e0 and "
1403 			"32e2 = 31 + 31e0 }";
1404 	set = isl_set_read_from_str(ctx, str);
1405 	bset = isl_set_affine_hull(set);
1406 	str = "{ [a] : exists e : a = 32 e }";
1407 	bset2 = isl_basic_set_read_from_str(ctx, str);
1408 	subset = isl_basic_set_is_subset(bset, bset2);
1409 	isl_basic_set_free(bset);
1410 	isl_basic_set_free(bset2);
1411 	if (subset < 0)
1412 		return -1;
1413 	if (!subset)
1414 		isl_die(ctx, isl_error_unknown, "not as accurate as expected",
1415 			return -1);
1416 
1417 	return 0;
1418 }
1419 
1420 /* Test a special case of isl_set_plain_unshifted_simple_hull
1421  * where older versions of isl would include a redundant constraint
1422  * in the result.
1423  * Check that the result does not have any constraints.
1424  */
test_plain_unshifted_simple_hull_special(isl_ctx * ctx)1425 static isl_stat test_plain_unshifted_simple_hull_special(isl_ctx *ctx)
1426 {
1427 	const char *str;
1428 	isl_bool is_universe;
1429 	isl_set *set;
1430 	isl_basic_set *bset;
1431 
1432 	str = "{[x, y] : x = 0 or 2*((x+y)//2) <= y + 2 }";
1433 	set = isl_set_read_from_str(ctx, str);
1434 	bset = isl_set_plain_unshifted_simple_hull(set);
1435 	is_universe = isl_basic_set_plain_is_universe(bset);
1436 	isl_basic_set_free(bset);
1437 
1438 	if (is_universe < 0)
1439 		return isl_stat_error;
1440 	if (!is_universe)
1441 		isl_die(ctx, isl_error_unknown,
1442 			"hull should not have any constraints",
1443 			return isl_stat_error);
1444 
1445 	return isl_stat_ok;
1446 }
1447 
1448 /* Inputs for simple hull tests, consisting of
1449  * the specific simple hull function, the input set and the expected result.
1450  */
1451 struct {
1452 	__isl_give isl_basic_set *(*fn)(__isl_take isl_set *set);
1453 	const char *set;
1454 	const char *hull;
1455 } simple_hull_tests[] = {
1456 	{ &isl_set_plain_unshifted_simple_hull,
1457 	  "{ [i,j] : i >= 1 and j >= 1 or i >= 2 and j <= 10 }",
1458 	  "{ [i,j] : i >= 1 }" },
1459 	{ &isl_set_plain_unshifted_simple_hull,
1460 	  "{ [n,i,j,k] : (i mod 3 = 2 and j mod 4 = 2) or "
1461 		"(j mod 4 = 2 and k mod 6 = n) }",
1462 	  "{ [n,i,j,k] : j mod 4 = 2 }" },
1463 	{ &isl_set_unshifted_simple_hull,
1464 	  "{ [0,x,y] : x <= -1; [1,x,y] : x <= y <= -x; [2,x,y] : x <= 1 }",
1465 	  "{ [t,x,y] : 0 <= t <= 2 and x <= 1 }" },
1466 	{ &isl_set_simple_hull,
1467 	  "{ [a, b] : b <= 0 and "
1468 			"2*floor((-2*floor((b)/2))/5) >= a - floor((b)/2); "
1469 	    "[a, b] : a mod 2 = 0 }",
1470 	  "{ [a, b] }" },
1471 };
1472 
1473 /* Basic tests for various simple hull functions.
1474  */
test_various_simple_hull(isl_ctx * ctx)1475 static int test_various_simple_hull(isl_ctx *ctx)
1476 {
1477 	int i;
1478 	isl_set *set;
1479 	isl_basic_set *hull, *expected;
1480 	isl_bool equal;
1481 
1482 	for (i = 0; i < ARRAY_SIZE(simple_hull_tests); ++i) {
1483 		const char *str;
1484 		str = simple_hull_tests[i].set;
1485 		set = isl_set_read_from_str(ctx, str);
1486 		str = simple_hull_tests[i].hull;
1487 		expected = isl_basic_set_read_from_str(ctx, str);
1488 		hull = simple_hull_tests[i].fn(set);
1489 		equal = isl_basic_set_is_equal(hull, expected);
1490 		isl_basic_set_free(hull);
1491 		isl_basic_set_free(expected);
1492 		if (equal < 0)
1493 			return -1;
1494 		if (!equal)
1495 			isl_die(ctx, isl_error_unknown, "unexpected hull",
1496 				return -1);
1497 	}
1498 
1499 	return 0;
1500 }
1501 
test_simple_hull(struct isl_ctx * ctx)1502 static int test_simple_hull(struct isl_ctx *ctx)
1503 {
1504 	const char *str;
1505 	isl_set *set;
1506 	isl_basic_set *bset;
1507 	isl_bool is_empty;
1508 
1509 	str = "{ [x, y] : 3y <= 2x and y >= -2 + 2x and 2y >= 2 - x;"
1510 		"[y, x] : 3y <= 2x and y >= -2 + 2x and 2y >= 2 - x }";
1511 	set = isl_set_read_from_str(ctx, str);
1512 	bset = isl_set_simple_hull(set);
1513 	is_empty = isl_basic_set_is_empty(bset);
1514 	isl_basic_set_free(bset);
1515 
1516 	if (is_empty == isl_bool_error)
1517 		return -1;
1518 
1519 	if (is_empty == isl_bool_false)
1520 		isl_die(ctx, isl_error_unknown, "Empty set should be detected",
1521 			return -1);
1522 
1523 	if (test_plain_unshifted_simple_hull_special(ctx) < 0)
1524 		return -1;
1525 	if (test_various_simple_hull(ctx) < 0)
1526 		return -1;
1527 
1528 	return 0;
1529 }
1530 
1531 /* Inputs for isl_set_get_simple_fixed_box_hull tests.
1532  * "set" is the input set.
1533  * "offset" is the expected box offset.
1534  * "size" is the expected box size.
1535  */
1536 static struct {
1537 	const char *set;
1538 	const char *offset;
1539 	const char *size;
1540 } box_hull_tests[] = {
1541 	{ "{ S[x, y] : 0 <= x, y < 10 }", "{ S[0, 0] }", "{ S[10, 10] }" },
1542 	{ "[N] -> { S[x, y] : N <= x, y < N + 10 }",
1543 	  "[N] -> { S[N, N] }", "{ S[10, 10] }" },
1544 	{ "{ S[x, y] : 0 <= x + y, x - y < 10 }",
1545 	  "{ S[0, -4] }", "{ S[10, 9] }" },
1546 	{ "{ [i=0:10] : exists (e0, e1: 3e1 >= 1 + 2e0 and "
1547 	    "8e1 <= -1 + 5i - 5e0 and 2e1 >= 1 + 2i - 5e0) }",
1548 	  "{ [3] }", "{ [8] }" },
1549 	{ "[N] -> { [w = 0:17] : exists (e0: w < 2N and "
1550 	    "-1 + w <= e0 <= w and 2e0 >= N + w and w <= 2e0 <= 15 + w) }",
1551 	  "[N] -> { [N] }", "{ [9] }" },
1552 };
1553 
1554 /* Perform basic isl_set_get_simple_fixed_box_hull tests.
1555  */
test_box_hull(struct isl_ctx * ctx)1556 static int test_box_hull(struct isl_ctx *ctx)
1557 {
1558 	int i;
1559 
1560 	for (i = 0; i < ARRAY_SIZE(box_hull_tests); ++i) {
1561 		const char *str;
1562 		isl_stat r;
1563 		isl_set *set;
1564 		isl_multi_aff *offset;
1565 		isl_multi_val *size;
1566 		isl_fixed_box *box;
1567 
1568 		set = isl_set_read_from_str(ctx, box_hull_tests[i].set);
1569 		box = isl_set_get_simple_fixed_box_hull(set);
1570 		offset = isl_fixed_box_get_offset(box);
1571 		size = isl_fixed_box_get_size(box);
1572 		str = box_hull_tests[i].offset;
1573 		r = multi_aff_check_plain_equal(offset, str);
1574 		str = box_hull_tests[i].size;
1575 		if (r >= 0)
1576 			r = multi_val_check_plain_equal(size, str);
1577 		isl_multi_aff_free(offset);
1578 		isl_multi_val_free(size);
1579 		isl_fixed_box_free(box);
1580 		isl_set_free(set);
1581 		if (r < 0)
1582 			return -1;
1583 	}
1584 
1585 	return 0;
1586 }
1587 
test_convex_hull_case(struct isl_ctx * ctx,const char * name)1588 void test_convex_hull_case(struct isl_ctx *ctx, const char *name)
1589 {
1590 	char *filename;
1591 	FILE *input;
1592 	struct isl_basic_set *bset1, *bset2;
1593 	struct isl_set *set;
1594 
1595 	filename = get_filename(ctx, name, "polylib");
1596 	assert(filename);
1597 	input = fopen(filename, "r");
1598 	assert(input);
1599 
1600 	bset1 = isl_basic_set_read_from_file(ctx, input);
1601 	bset2 = isl_basic_set_read_from_file(ctx, input);
1602 
1603 	set = isl_basic_set_union(bset1, bset2);
1604 	bset1 = isl_set_convex_hull(set);
1605 
1606 	bset2 = isl_basic_set_read_from_file(ctx, input);
1607 
1608 	assert(isl_basic_set_is_equal(bset1, bset2) == 1);
1609 
1610 	isl_basic_set_free(bset1);
1611 	isl_basic_set_free(bset2);
1612 	free(filename);
1613 
1614 	fclose(input);
1615 }
1616 
1617 struct {
1618 	const char *set;
1619 	const char *hull;
1620 } convex_hull_tests[] = {
1621 	{ "{ [i0, i1, i2] : (i2 = 1 and i0 = 0 and i1 >= 0) or "
1622 	       "(i0 = 1 and i1 = 0 and i2 = 1) or "
1623 	       "(i0 = 0 and i1 = 0 and i2 = 0) }",
1624 	  "{ [i0, i1, i2] : i0 >= 0 and i2 >= i0 and i2 <= 1 and i1 >= 0 }" },
1625 	{ "[n] -> { [i0, i1, i0] : i0 <= -4 + n; "
1626 	    "[i0, i0, i2] : n = 6 and i0 >= 0 and i2 <= 7 - i0 and "
1627 	    "i2 <= 5 and i2 >= 4; "
1628 	    "[3, i1, 3] : n = 5 and i1 <= 2 and i1 >= 0 }",
1629 	  "[n] -> { [i0, i1, i2] : i2 <= -1 + n and 2i2 <= -6 + 3n - i0 and "
1630 	    "i2 <= 5 + i0 and i2 >= i0 }" },
1631 	{ "{ [x, y] : 3y <= 2x and y >= -2 + 2x and 2y >= 2 - x }",
1632 	    "{ [x, y] : 1 = 0 }" },
1633 	{ "{ [x, y, z] : 0 <= x, y, z <= 10; [x, y, 0] : x >= 0 and y > 0; "
1634 	    "[x, y, 0] : x >= 0 and y < 0 }",
1635 	    "{ [x, y, z] : x >= 0 and 0 <= z <= 10 }" },
1636 	{ "{ [a, b, c] : a <= 1 and -a < b <= 1 and 0 <= c <= 2 - a - b and "
1637 			    "c <= a; "
1638 	    "[0, 2, 0]; [3, 1, 0] }",
1639 	    "{ [a, b, c] : b > -a and 2b >= -1 + a and 0 <= c <= a and "
1640 			    "5c <= 6 - a - 3b }" },
1641 };
1642 
test_convex_hull_algo(isl_ctx * ctx,int convex)1643 static int test_convex_hull_algo(isl_ctx *ctx, int convex)
1644 {
1645 	int i;
1646 	int orig_convex = ctx->opt->convex;
1647 	ctx->opt->convex = convex;
1648 
1649 	test_convex_hull_case(ctx, "convex0");
1650 	test_convex_hull_case(ctx, "convex1");
1651 	test_convex_hull_case(ctx, "convex2");
1652 	test_convex_hull_case(ctx, "convex3");
1653 	test_convex_hull_case(ctx, "convex4");
1654 	test_convex_hull_case(ctx, "convex5");
1655 	test_convex_hull_case(ctx, "convex6");
1656 	test_convex_hull_case(ctx, "convex7");
1657 	test_convex_hull_case(ctx, "convex8");
1658 	test_convex_hull_case(ctx, "convex9");
1659 	test_convex_hull_case(ctx, "convex10");
1660 	test_convex_hull_case(ctx, "convex11");
1661 	test_convex_hull_case(ctx, "convex12");
1662 	test_convex_hull_case(ctx, "convex13");
1663 	test_convex_hull_case(ctx, "convex14");
1664 	test_convex_hull_case(ctx, "convex15");
1665 
1666 	for (i = 0; i < ARRAY_SIZE(convex_hull_tests); ++i) {
1667 		isl_set *set1, *set2;
1668 		int equal;
1669 
1670 		set1 = isl_set_read_from_str(ctx, convex_hull_tests[i].set);
1671 		set2 = isl_set_read_from_str(ctx, convex_hull_tests[i].hull);
1672 		set1 = isl_set_from_basic_set(isl_set_convex_hull(set1));
1673 		equal = isl_set_is_equal(set1, set2);
1674 		isl_set_free(set1);
1675 		isl_set_free(set2);
1676 
1677 		if (equal < 0)
1678 			return -1;
1679 		if (!equal)
1680 			isl_die(ctx, isl_error_unknown,
1681 				"unexpected convex hull", return -1);
1682 	}
1683 
1684 	ctx->opt->convex = orig_convex;
1685 
1686 	return 0;
1687 }
1688 
test_convex_hull(isl_ctx * ctx)1689 static int test_convex_hull(isl_ctx *ctx)
1690 {
1691 	if (test_convex_hull_algo(ctx, ISL_CONVEX_HULL_FM) < 0)
1692 		return -1;
1693 	if (test_convex_hull_algo(ctx, ISL_CONVEX_HULL_WRAP) < 0)
1694 		return -1;
1695 	return 0;
1696 }
1697 
1698 /* Check that computing the gist of "map" with respect to "context"
1699  * does not make any copy of "map" get marked empty.
1700  * Earlier versions of isl would end up doing that.
1701  */
test_gist_empty_pair(isl_ctx * ctx,const char * map,const char * context)1702 static isl_stat test_gist_empty_pair(isl_ctx *ctx, const char *map,
1703 	const char *context)
1704 {
1705 	isl_map *m1, *m2, *m3;
1706 	isl_bool empty_before, empty_after;
1707 
1708 	m1 = isl_map_read_from_str(ctx, map);
1709 	m2 = isl_map_read_from_str(ctx, context);
1710 	m3 = isl_map_copy(m1);
1711 	empty_before = isl_map_is_empty(m3);
1712 	m1 = isl_map_gist(m1, m2);
1713 	empty_after = isl_map_is_empty(m3);
1714 	isl_map_free(m1);
1715 	isl_map_free(m3);
1716 
1717 	if (empty_before < 0 || empty_after < 0)
1718 		return isl_stat_error;
1719 	if (empty_before)
1720 		isl_die(ctx, isl_error_unknown, "map should not be empty",
1721 			return isl_stat_error);
1722 	if (empty_after)
1723 		isl_die(ctx, isl_error_unknown, "map should still not be empty",
1724 			return isl_stat_error);
1725 
1726 	return isl_stat_ok;
1727 }
1728 
1729 /* Check that computing a gist does not make any copy of the input
1730  * get marked empty.
1731  * Earlier versions of isl would end up doing that on some pairs of inputs.
1732  */
test_gist_empty(isl_ctx * ctx)1733 static isl_stat test_gist_empty(isl_ctx *ctx)
1734 {
1735 	const char *map, *context;
1736 
1737 	map = "{ [] -> [a, b, c] : 2b = 1 + a }";
1738 	context = "{ [] -> [a, b, c] : 2c = 2 + a }";
1739 	if (test_gist_empty_pair(ctx, map, context) < 0)
1740 		return isl_stat_error;
1741 	map = "{ [] -> [0, 0] }";
1742 	context = "{ [] -> [a, b] : a > b }";
1743 	if (test_gist_empty_pair(ctx, map, context) < 0)
1744 		return isl_stat_error;
1745 
1746 	return isl_stat_ok;
1747 }
1748 
1749 /* Inputs to isl_map_plain_gist_basic_map, along with the expected output.
1750  */
1751 struct {
1752 	const char *map;
1753 	const char *context;
1754 	const char *gist;
1755 } plain_gist_tests[] = {
1756 	{ "{ [i] -> [j] : i >= 1 and j >= 1 or i >= 2 and j <= 10 }",
1757 	  "{ [i] -> [j] : i >= 1 }",
1758 	  "{ [i] -> [j] : j >= 1 or i >= 2 and j <= 10 }" },
1759 	{ "{ [n] -> [i,j,k] : (i mod 3 = 2 and j mod 4 = 2) or "
1760 		"(j mod 4 = 2 and k mod 6 = n) }",
1761 	  "{ [n] -> [i,j,k] : j mod 4 = 2 }",
1762 	  "{ [n] -> [i,j,k] : (i mod 3 = 2) or (k mod 6 = n) }" },
1763 	{ "{ [i] -> [j] : i > j and (exists a,b : i <= 2a + 5b <= 2) }",
1764 	  "{ [i] -> [j] : i > j }",
1765 	  "{ [i] -> [j] : exists a,b : i <= 2a + 5b <= 2 }" },
1766 };
1767 
1768 /* Basic tests for isl_map_plain_gist_basic_map.
1769  */
test_plain_gist(isl_ctx * ctx)1770 static int test_plain_gist(isl_ctx *ctx)
1771 {
1772 	int i;
1773 
1774 	for (i = 0; i < ARRAY_SIZE(plain_gist_tests); ++i) {
1775 		const char *str;
1776 		int equal;
1777 		isl_map *map, *gist;
1778 		isl_basic_map *context;
1779 
1780 		map = isl_map_read_from_str(ctx, plain_gist_tests[i].map);
1781 		str = plain_gist_tests[i].context;
1782 		context = isl_basic_map_read_from_str(ctx, str);
1783 		map = isl_map_plain_gist_basic_map(map, context);
1784 		gist = isl_map_read_from_str(ctx, plain_gist_tests[i].gist);
1785 		equal = isl_map_is_equal(map, gist);
1786 		isl_map_free(map);
1787 		isl_map_free(gist);
1788 		if (equal < 0)
1789 			return -1;
1790 		if (!equal)
1791 			isl_die(ctx, isl_error_unknown,
1792 				"incorrect gist result", return -1);
1793 	}
1794 
1795 	return 0;
1796 }
1797 
1798 /* Inputs for isl_basic_set_gist tests that are expected to fail.
1799  */
1800 struct {
1801 	const char *set;
1802 	const char *context;
1803 } gist_fail_tests[] = {
1804 	{ "{ [i] : exists (e0, e1: 3e1 >= 1 + 2e0 and "
1805 	    "8e1 <= -1 + 5i - 5e0 and 2e1 >= 1 + 2i - 5e0) }",
1806 	  "{ [i] : i >= 0 }" },
1807 };
1808 
1809 /* Check that isl_basic_set_gist fails (gracefully) when expected.
1810  * In particular, the user should be able to recover from the failure.
1811  */
test_gist_fail(struct isl_ctx * ctx)1812 static isl_stat test_gist_fail(struct isl_ctx *ctx)
1813 {
1814 	int i, n;
1815 	int on_error;
1816 
1817 	on_error = isl_options_get_on_error(ctx);
1818 	isl_options_set_on_error(ctx, ISL_ON_ERROR_CONTINUE);
1819 	n = ARRAY_SIZE(gist_fail_tests);
1820 	for (i = 0; i < n; ++i) {
1821 		const char *str;
1822 		isl_basic_set *bset, *context;
1823 
1824 		bset = isl_basic_set_read_from_str(ctx, gist_fail_tests[i].set);
1825 		str = gist_fail_tests[i].context;
1826 		context = isl_basic_set_read_from_str(ctx, str);
1827 		bset = isl_basic_set_gist(bset, context);
1828 		isl_basic_set_free(bset);
1829 		if (bset)
1830 			break;
1831 	}
1832 	isl_options_set_on_error(ctx, on_error);
1833 	if (i < n)
1834 		isl_die(ctx, isl_error_unknown,
1835 			"operation not expected to succeed",
1836 			return isl_stat_error);
1837 
1838 	return isl_stat_ok;
1839 }
1840 
1841 struct {
1842 	const char *set;
1843 	const char *context;
1844 	const char *gist;
1845 } gist_tests[] = {
1846 	{ "{ [1, -1, 3] }",
1847 	  "{ [1, b, 2 - b] : -1 <= b <= 2 }",
1848 	  "{ [a, -1, c] }" },
1849 	{ "{ [a, b, c] : a <= 15 and a >= 1 }",
1850 	  "{ [a, b, c] : exists (e0 = floor((-1 + a)/16): a >= 1 and "
1851 			"c <= 30 and 32e0 >= -62 + 2a + 2b - c and b >= 0) }",
1852 	  "{ [a, b, c] : a <= 15 }" },
1853 	{ "{ : }", "{ : 1 = 0 }", "{ : }" },
1854 	{ "{ : 1 = 0 }", "{ : 1 = 0 }", "{ : }" },
1855 	{ "[M] -> { [x] : exists (e0 = floor((-2 + x)/3): 3e0 = -2 + x) }",
1856 	  "[M] -> { [3M] }" , "[M] -> { [x] : 1 = 0 }" },
1857 	{ "{ [m, n, a, b] : a <= 2147 + n }",
1858 	  "{ [m, n, a, b] : (m >= 1 and n >= 1 and a <= 2148 - m and "
1859 			"b <= 2148 - n and b >= 0 and b >= 2149 - n - a) or "
1860 			"(n >= 1 and a >= 0 and b <= 2148 - n - a and "
1861 			"b >= 0) }",
1862 	  "{ [m, n, ku, kl] }" },
1863 	{ "{ [a, a, b] : a >= 10 }",
1864 	  "{ [a, b, c] : c >= a and c <= b and c >= 2 }",
1865 	  "{ [a, a, b] : a >= 10 }" },
1866 	{ "{ [i, j] : i >= 0 and i + j >= 0 }", "{ [i, j] : i <= 0 }",
1867 	  "{ [0, j] : j >= 0 }" },
1868 	/* Check that no constraints on i6 are introduced in the gist */
1869 	{ "[t1] -> { [i4, i6] : exists (e0 = floor((1530 - 4t1 - 5i4)/20): "
1870 		"20e0 <= 1530 - 4t1 - 5i4 and 20e0 >= 1511 - 4t1 - 5i4 and "
1871 		"5e0 <= 381 - t1 and i4 <= 1) }",
1872 	  "[t1] -> { [i4, i6] : exists (e0 = floor((-t1 + i6)/5): "
1873 		"5e0 = -t1 + i6 and i6 <= 6 and i6 >= 3) }",
1874 	  "[t1] -> { [i4, i6] : exists (e0 = floor((1530 - 4t1 - 5i4)/20): "
1875 		"i4 <= 1 and 5e0 <= 381 - t1 and 20e0 <= 1530 - 4t1 - 5i4 and "
1876 		"20e0 >= 1511 - 4t1 - 5i4) }" },
1877 	/* Check that no constraints on i6 are introduced in the gist */
1878 	{ "[t1, t2] -> { [i4, i5, i6] : exists (e0 = floor((1 + i4)/2), "
1879 		"e1 = floor((1530 - 4t1 - 5i4)/20), "
1880 		"e2 = floor((-4t1 - 5i4 + 10*floor((1 + i4)/2))/20), "
1881 		"e3 = floor((-1 + i4)/2): t2 = 0 and 2e3 = -1 + i4 and "
1882 			"20e2 >= -19 - 4t1 - 5i4 + 10e0 and 5e2 <= 1 - t1 and "
1883 			"2e0 <= 1 + i4 and 2e0 >= i4 and "
1884 			"20e1 <= 1530 - 4t1 - 5i4 and "
1885 			"20e1 >= 1511 - 4t1 - 5i4 and i4 <= 1 and "
1886 			"5e1 <= 381 - t1 and 20e2 <= -4t1 - 5i4 + 10e0) }",
1887 	  "[t1, t2] -> { [i4, i5, i6] : exists (e0 = floor((-17 + i4)/2), "
1888 		"e1 = floor((-t1 + i6)/5): 5e1 = -t1 + i6 and "
1889 			"2e0 <= -17 + i4 and 2e0 >= -18 + i4 and "
1890 			"10e0 <= -91 + 5i4 + 4i6 and "
1891 			"10e0 >= -105 + 5i4 + 4i6) }",
1892 	  "[t1, t2] -> { [i4, i5, i6] : exists (e0 = floor((381 - t1)/5), "
1893 		"e1 = floor((-1 + i4)/2): t2 = 0 and 2e1 = -1 + i4 and "
1894 		"i4 <= 1 and 5e0 <= 381 - t1 and 20e0 >= 1511 - 4t1 - 5i4) }" },
1895 	{ "{ [0, 0, q, p] : -5 <= q <= 5 and p >= 0 }",
1896 	  "{ [a, b, q, p] : b >= 1 + a }",
1897 	  "{ [a, b, q, p] : false }" },
1898 	{ "[n] -> { [x] : x = n && x mod 32 = 0 }",
1899 	  "[n] -> { [x] : x mod 32 = 0 }",
1900 	  "[n] -> { [x = n] }" },
1901 	{ "{ [x] : x mod 6 = 0 }", "{ [x] : x mod 3 = 0 }",
1902 	  "{ [x] : x mod 2 = 0 }" },
1903 	{ "{ [x] : x mod 3200 = 0 }", "{ [x] : x mod 10000 = 0 }",
1904 	  "{ [x] : x mod 128 = 0 }" },
1905 	{ "{ [x] : x mod 3200 = 0 }", "{ [x] : x mod 10 = 0 }",
1906 	  "{ [x] : x mod 3200 = 0 }" },
1907 	{ "{ [a, b, c] : a mod 2 = 0 and a = c }",
1908 	  "{ [a, b, c] : b mod 2 = 0 and b = c }",
1909 	  "{ [a, b, c = a] }" },
1910 	{ "{ [a, b, c] : a mod 6 = 0 and a = c }",
1911 	  "{ [a, b, c] : b mod 2 = 0 and b = c }",
1912 	  "{ [a, b, c = a] : a mod 3 = 0 }" },
1913 	{ "{ [x] : 0 <= x <= 4 or 6 <= x <= 9 }",
1914 	  "{ [x] : 1 <= x <= 3 or 7 <= x <= 8 }",
1915 	  "{ [x] }" },
1916 	{ "{ [x,y] : x < 0 and 0 <= y <= 4 or x >= -2 and -x <= y <= 10 + x }",
1917 	  "{ [x,y] : 1 <= y <= 3 }",
1918 	  "{ [x,y] }" },
1919 };
1920 
1921 /* Check that isl_set_gist behaves as expected.
1922  *
1923  * For the test cases in gist_tests, besides checking that the result
1924  * is as expected, also check that applying the gist operation does
1925  * not modify the input set (an earlier version of isl would do that) and
1926  * that the test case is consistent, i.e., that the gist has the same
1927  * intersection with the context as the input set.
1928  */
test_gist(struct isl_ctx * ctx)1929 static int test_gist(struct isl_ctx *ctx)
1930 {
1931 	int i;
1932 	const char *str;
1933 	isl_basic_set *bset1, *bset2;
1934 	isl_map *map1, *map2;
1935 	isl_bool equal;
1936 	isl_size n_div;
1937 
1938 	for (i = 0; i < ARRAY_SIZE(gist_tests); ++i) {
1939 		isl_bool equal_input, equal_intersection;
1940 		isl_set *set1, *set2, *copy, *context;
1941 
1942 		set1 = isl_set_read_from_str(ctx, gist_tests[i].set);
1943 		context = isl_set_read_from_str(ctx, gist_tests[i].context);
1944 		copy = isl_set_copy(set1);
1945 		set1 = isl_set_gist(set1, isl_set_copy(context));
1946 		set2 = isl_set_read_from_str(ctx, gist_tests[i].gist);
1947 		equal = isl_set_is_equal(set1, set2);
1948 		isl_set_free(set1);
1949 		set1 = isl_set_read_from_str(ctx, gist_tests[i].set);
1950 		equal_input = isl_set_is_equal(set1, copy);
1951 		isl_set_free(copy);
1952 		set1 = isl_set_intersect(set1, isl_set_copy(context));
1953 		set2 = isl_set_intersect(set2, context);
1954 		equal_intersection = isl_set_is_equal(set1, set2);
1955 		isl_set_free(set2);
1956 		isl_set_free(set1);
1957 		if (equal < 0 || equal_input < 0 || equal_intersection < 0)
1958 			return -1;
1959 		if (!equal)
1960 			isl_die(ctx, isl_error_unknown,
1961 				"incorrect gist result", return -1);
1962 		if (!equal_input)
1963 			isl_die(ctx, isl_error_unknown,
1964 				"gist modified input", return -1);
1965 		if (!equal_input)
1966 			isl_die(ctx, isl_error_unknown,
1967 				"inconsistent gist test case", return -1);
1968 	}
1969 
1970 	if (test_gist_fail(ctx) < 0)
1971 		return -1;
1972 
1973 	str = "[p0, p2, p3, p5, p6, p10] -> { [] : "
1974 	    "exists (e0 = [(15 + p0 + 15p6 + 15p10)/16], e1 = [(p5)/8], "
1975 	    "e2 = [(p6)/128], e3 = [(8p2 - p5)/128], "
1976 	    "e4 = [(128p3 - p6)/4096]: 8e1 = p5 and 128e2 = p6 and "
1977 	    "128e3 = 8p2 - p5 and 4096e4 = 128p3 - p6 and p2 >= 0 and "
1978 	    "16e0 >= 16 + 16p6 + 15p10 and  p2 <= 15 and p3 >= 0 and "
1979 	    "p3 <= 31 and  p6 >= 128p3 and p5 >= 8p2 and p10 >= 0 and "
1980 	    "16e0 <= 15 + p0 + 15p6 + 15p10 and 16e0 >= p0 + 15p6 + 15p10 and "
1981 	    "p10 <= 15 and p10 <= -1 + p0 - p6) }";
1982 	bset1 = isl_basic_set_read_from_str(ctx, str);
1983 	str = "[p0, p2, p3, p5, p6, p10] -> { [] : exists (e0 = [(p5)/8], "
1984 	    "e1 = [(p6)/128], e2 = [(8p2 - p5)/128], "
1985 	    "e3 = [(128p3 - p6)/4096]: 8e0 = p5 and 128e1 = p6 and "
1986 	    "128e2 = 8p2 - p5 and 4096e3 = 128p3 - p6 and p5 >= -7 and "
1987 	    "p2 >= 0 and 8p2 <= -1 + p0 and p2 <= 15 and p3 >= 0 and "
1988 	    "p3 <= 31 and 128p3 <= -1 + p0 and p6 >= -127 and "
1989 	    "p5 <= -1 + p0 and p6 <= -1 + p0 and p6 >= 128p3 and "
1990 	    "p0 >= 1 and p5 >= 8p2 and p10 >= 0 and p10 <= 15 ) }";
1991 	bset2 = isl_basic_set_read_from_str(ctx, str);
1992 	bset1 = isl_basic_set_gist(bset1, bset2);
1993 	assert(bset1 && bset1->n_div == 0);
1994 	isl_basic_set_free(bset1);
1995 
1996 	/* Check that the integer divisions of the second disjunct
1997 	 * do not spread to the first disjunct.
1998 	 */
1999 	str = "[t1] -> { S_0[] -> A[o0] : (exists (e0 = [(-t1 + o0)/16]: "
2000 		"16e0 = -t1 + o0 and o0 >= 0 and o0 <= 15 and t1 >= 0)) or "
2001 		"(exists (e0 = [(-1 + t1)/16], "
2002 			"e1 = [(-16 + t1 - 16e0)/4294967296]: "
2003 			"4294967296e1 = -16 + t1 - o0 - 16e0 and "
2004 			"16e0 <= -1 + t1 and 16e0 >= -16 + t1 and o0 >= 0 and "
2005 			"o0 <= 4294967295 and t1 <= -1)) }";
2006 	map1 = isl_map_read_from_str(ctx, str);
2007 	str = "[t1] -> { S_0[] -> A[o0] : t1 >= 0 and t1 <= 4294967295 }";
2008 	map2 = isl_map_read_from_str(ctx, str);
2009 	map1 = isl_map_gist(map1, map2);
2010 	if (!map1)
2011 		return -1;
2012 	if (map1->n != 1)
2013 		isl_die(ctx, isl_error_unknown, "expecting single disjunct",
2014 			isl_map_free(map1); return -1);
2015 	n_div = isl_basic_map_dim(map1->p[0], isl_dim_div);
2016 	isl_map_free(map1);
2017 	if (n_div < 0)
2018 		return -1;
2019 	if (n_div != 1)
2020 		isl_die(ctx, isl_error_unknown, "expecting single div",
2021 			return -1);
2022 
2023 	if (test_gist_empty(ctx) < 0)
2024 		return -1;
2025 	if (test_plain_gist(ctx) < 0)
2026 		return -1;
2027 
2028 	return 0;
2029 }
2030 
test_coalesce_set(isl_ctx * ctx,const char * str,int check_one)2031 int test_coalesce_set(isl_ctx *ctx, const char *str, int check_one)
2032 {
2033 	isl_set *set, *set2;
2034 	int equal;
2035 	int one;
2036 
2037 	set = isl_set_read_from_str(ctx, str);
2038 	set = isl_set_coalesce(set);
2039 	set2 = isl_set_read_from_str(ctx, str);
2040 	equal = isl_set_is_equal(set, set2);
2041 	one = set && set->n == 1;
2042 	isl_set_free(set);
2043 	isl_set_free(set2);
2044 
2045 	if (equal < 0)
2046 		return -1;
2047 	if (!equal)
2048 		isl_die(ctx, isl_error_unknown,
2049 			"coalesced set not equal to input", return -1);
2050 	if (check_one && !one)
2051 		isl_die(ctx, isl_error_unknown,
2052 			"coalesced set should not be a union", return -1);
2053 
2054 	return 0;
2055 }
2056 
2057 /* Inputs for coalescing tests with unbounded wrapping.
2058  * "str" is a string representation of the input set.
2059  * "single_disjunct" is set if we expect the result to consist of
2060  *	a single disjunct.
2061  */
2062 struct {
2063 	int single_disjunct;
2064 	const char *str;
2065 } coalesce_unbounded_tests[] = {
2066 	{ 1, "{ [x,y,z] : y + 2 >= 0 and x - y + 1 >= 0 and "
2067 			"-x - y + 1 >= 0 and -3 <= z <= 3;"
2068 		"[x,y,z] : -x+z + 20 >= 0 and -x-z + 20 >= 0 and "
2069 			"x-z + 20 >= 0 and x+z + 20 >= 0 and "
2070 			"-10 <= y <= 0}" },
2071 	{ 1, "{ [x,y] : 0 <= x,y <= 10; [5,y]: 4 <= y <= 11 }" },
2072 	{ 1, "{ [x,0,0] : -5 <= x <= 5; [0,y,1] : -5 <= y <= 5 }" },
2073 	{ 1, "{ [x,y] : 0 <= x <= 10 and 0 >= y >= -1 and x+y >= 0; [0,1] }" },
2074 	{ 1, "{ [x,y] : (0 <= x,y <= 4) or (2 <= x,y <= 5 and x + y <= 9) }" },
2075 	{ 0, "{ [x, y, z] : 0 <= x,y,z <= 100 and 0 < z <= 2 + 2x + 2y; "
2076 		"[x, y, 0] : x,y <= 100 and y <= 9 + 11x and x <= 9 + 11y }" },
2077 	{ 1, "{ [0:1, 0:1]; [0, 2:3] }" },
2078 	{ 1, "{ [0:1, 0:1]; [0, 2:3]; [1, -2:-1] }" },
2079 	{ 1, "{ [0:3, 0:1]; [1:2, 2:5] }" },
2080 	{ 1, "{ [0:3, 0:1]; [0:2, 2:5] }" },
2081 	{ 1, "{ [0:3, 0:1]; [1:3, 2:5] }" },
2082 	{ 0, "{ [0:3, 0:1]; [1:4, 2:5] }" },
2083 	{ 0, "{ [0:3, 0:1]; [1:5, 2:5] }" },
2084 };
2085 
2086 /* Test the functionality of isl_set_coalesce with the bounded wrapping
2087  * option turned off.
2088  */
test_coalesce_unbounded_wrapping(isl_ctx * ctx)2089 int test_coalesce_unbounded_wrapping(isl_ctx *ctx)
2090 {
2091 	int i;
2092 	int r = 0;
2093 	int bounded;
2094 
2095 	bounded = isl_options_get_coalesce_bounded_wrapping(ctx);
2096 	isl_options_set_coalesce_bounded_wrapping(ctx, 0);
2097 
2098 	for (i = 0; i < ARRAY_SIZE(coalesce_unbounded_tests); ++i) {
2099 		const char *str = coalesce_unbounded_tests[i].str;
2100 		int check_one = coalesce_unbounded_tests[i].single_disjunct;
2101 		if (test_coalesce_set(ctx, str, check_one) >= 0)
2102 			continue;
2103 		r = -1;
2104 		break;
2105 	}
2106 
2107 	isl_options_set_coalesce_bounded_wrapping(ctx, bounded);
2108 
2109 	return r;
2110 }
2111 
2112 /* Inputs for coalescing tests.
2113  * "str" is a string representation of the input set.
2114  * "single_disjunct" is set if we expect the result to consist of
2115  *	a single disjunct.
2116  */
2117 struct {
2118 	int single_disjunct;
2119 	const char *str;
2120 } coalesce_tests[] = {
2121 	{ 1, "{[x,y]: x >= 0 & x <= 10 & y >= 0 & y <= 10 or "
2122 		       "y >= x & x >= 2 & 5 >= y }" },
2123 	{ 1, "{[x,y]: y >= 0 & 2x + y <= 30 & y <= 10 & x >= 0 or "
2124 		       "x + y >= 10 & y <= x & x + y <= 20 & y >= 0}" },
2125 	{ 0, "{[x,y]: y >= 0 & 2x + y <= 30 & y <= 10 & x >= 0 or "
2126 		       "x + y >= 10 & y <= x & x + y <= 19 & y >= 0}" },
2127 	{ 1, "{[x,y]: y >= 0 & x <= 5 & y <= x or "
2128 		       "y >= 0 & x >= 6 & x <= 10 & y <= x}" },
2129 	{ 0, "{[x,y]: y >= 0 & x <= 5 & y <= x or "
2130 		       "y >= 0 & x >= 7 & x <= 10 & y <= x}" },
2131 	{ 0, "{[x,y]: y >= 0 & x <= 5 & y <= x or "
2132 		       "y >= 0 & x >= 6 & x <= 10 & y + 1 <= x}" },
2133 	{ 1, "{[x,y]: y >= 0 & x <= 5 & y <= x or y >= 0 & x = 6 & y <= 6}" },
2134 	{ 0, "{[x,y]: y >= 0 & x <= 5 & y <= x or y >= 0 & x = 7 & y <= 6}" },
2135 	{ 1, "{[x,y]: y >= 0 & x <= 5 & y <= x or y >= 0 & x = 6 & y <= 5}" },
2136 	{ 0, "{[x,y]: y >= 0 & x <= 5 & y <= x or y >= 0 & x = 6 & y <= 7}" },
2137 	{ 1, "[n] -> { [i] : i = 1 and n >= 2 or 2 <= i and i <= n }" },
2138 	{ 0, "{[x,y] : x >= 0 and y >= 0 or 0 <= y and y <= 5 and x = -1}" },
2139 	{ 1, "[n] -> { [i] : 1 <= i and i <= n - 1 or 2 <= i and i <= n }" },
2140 	{ 0, "[n] -> { [[i0] -> [o0]] : exists (e0 = [(i0)/4], e1 = [(o0)/4], "
2141 		"e2 = [(n)/2], e3 = [(-2 + i0)/4], e4 = [(-2 + o0)/4], "
2142 		"e5 = [(-2n + i0)/4]: 2e2 = n and 4e3 = -2 + i0 and "
2143 		"4e4 = -2 + o0 and i0 >= 8 + 2n and o0 >= 2 + i0 and "
2144 		"o0 <= 56 + 2n and o0 <= -12 + 4n and i0 <= 57 + 2n and "
2145 		"i0 <= -11 + 4n and o0 >= 6 + 2n and 4e0 <= i0 and "
2146 		"4e0 >= -3 + i0 and 4e1 <= o0 and 4e1 >= -3 + o0 and "
2147 		"4e5 <= -2n + i0 and 4e5 >= -3 - 2n + i0);"
2148 		"[[i0] -> [o0]] : exists (e0 = [(i0)/4], e1 = [(o0)/4], "
2149 		"e2 = [(n)/2], e3 = [(-2 + i0)/4], e4 = [(-2 + o0)/4], "
2150 		"e5 = [(-2n + i0)/4]: 2e2 = n and 4e3 = -2 + i0 and "
2151 		"4e4 = -2 + o0 and 2e0 >= 3 + n and e0 <= -4 + n and "
2152 		"2e0 <= 27 + n and e1 <= -4 + n and 2e1 <= 27 + n and "
2153 		"2e1 >= 2 + n and e1 >= 1 + e0 and i0 >= 7 + 2n and "
2154 		"i0 <= -11 + 4n and i0 <= 57 + 2n and 4e0 <= -2 + i0 and "
2155 		"4e0 >= -3 + i0 and o0 >= 6 + 2n and o0 <= -11 + 4n and "
2156 		"o0 <= 57 + 2n and 4e1 <= -2 + o0 and 4e1 >= -3 + o0 and "
2157 		"4e5 <= -2n + i0 and 4e5 >= -3 - 2n + i0 ) }" },
2158 	{ 0, "[n, m] -> { [o0, o2, o3] : (o3 = 1 and o0 >= 1 + m and "
2159 	      "o0 <= n + m and o2 <= m and o0 >= 2 + n and o2 >= 3) or "
2160 	      "(o0 >= 2 + n and o0 >= 1 + m and o0 <= n + m and n >= 1 and "
2161 	      "o3 <= -1 + o2 and o3 >= 1 - m + o2 and o3 >= 2 and o3 <= n) }" },
2162 	{ 0, "[M, N] -> { [[i0, i1, i2, i3, i4, i5, i6] -> "
2163 	  "[o0, o1, o2, o3, o4, o5, o6]] : "
2164 	  "(o6 <= -4 + 2M - 2N + i0 + i1 - i2 + i6 - o0 - o1 + o2 and "
2165 	  "o3 <= -2 + i3 and o6 >= 2 + i0 + i3 + i6 - o0 - o3 and "
2166 	  "o6 >= 2 - M + N + i3 + i4 + i6 - o3 - o4 and o0 <= -1 + i0 and "
2167 	  "o4 >= 4 - 3M + 3N - i0 - i1 + i2 + 2i3 + i4 + o0 + o1 - o2 - 2o3 "
2168 	  "and o6 <= -3 + 2M - 2N + i3 + i4 - i5 + i6 - o3 - o4 + o5 and "
2169 	  "2o6 <= -5 + 5M - 5N + 2i0 + i1 - i2 - i5 + 2i6 - 2o0 - o1 + o2 + o5 "
2170 	  "and o6 >= 2i0 + i1 + i6 - 2o0 - o1 and "
2171 	  "3o6 <= -5 + 4M - 4N + 2i0 + i1 - i2 + 2i3 + i4 - i5 + 3i6 "
2172 	  "- 2o0 - o1 + o2 - 2o3 - o4 + o5) or "
2173 	  "(N >= 2 and o3 <= -1 + i3 and o0 <= -1 + i0 and "
2174 	  "o6 >= i3 + i6 - o3 and M >= 0 and "
2175 	  "2o6 >= 1 + i0 + i3 + 2i6 - o0 - o3 and "
2176 	  "o6 >= 1 - M + i0 + i6 - o0 and N >= 2M and o6 >= i0 + i6 - o0) }" },
2177 	{ 0, "[M, N] -> { [o0] : (o0 = 0 and M >= 1 and N >= 2) or "
2178 		"(o0 = 0 and M >= 1 and N >= 2M and N >= 2 + M) or "
2179 		"(o0 = 0 and M >= 2 and N >= 3) or "
2180 		"(M = 0 and o0 = 0 and N >= 3) }" },
2181 	{ 0, "{ [i0, i1, i2, i3] : (i1 = 10i0 and i0 >= 1 and 10i0 <= 100 and "
2182 	    "i3 <= 9 + 10 i2 and i3 >= 1 + 10i2 and i3 >= 0) or "
2183 	    "(i1 <= 9 + 10i0 and i1 >= 1 + 10i0 and i2 >= 0 and "
2184 	    "i0 >= 0 and i1 <= 100 and i3 <= 9 + 10i2 and i3 >= 1 + 10i2) }" },
2185 	{ 0, "[M] -> { [i1] : (i1 >= 2 and i1 <= M) or (i1 = M and M >= 1) }" },
2186 	{ 0, "{[x,y] : x,y >= 0; [x,y] : 10 <= x <= 20 and y >= -1 }" },
2187 	{ 1, "{ [x, y] : (x >= 1 and y >= 1 and x <= 2 and y <= 2) or "
2188 		"(y = 3 and x = 1) }" },
2189 	{ 1, "[M] -> { [i0, i1, i2, i3, i4] : (i1 >= 3 and i4 >= 2 + i2 and "
2190 		"i2 >= 2 and i0 >= 2 and i3 >= 1 + i2 and i0 <= M and "
2191 		"i1 <= M and i3 <= M and i4 <= M) or "
2192 		"(i1 >= 2 and i4 >= 1 + i2 and i2 >= 2 and i0 >= 2 and "
2193 		"i3 >= 1 + i2 and i0 <= M and i1 <= -1 + M and i3 <= M and "
2194 		"i4 <= -1 + M) }" },
2195 	{ 1, "{ [x, y] : (x >= 0 and y >= 0 and x <= 10 and y <= 10) or "
2196 		"(x >= 1 and y >= 1 and x <= 11 and y <= 11) }" },
2197 	{ 0, "{[x,0] : x >= 0; [x,1] : x <= 20}" },
2198 	{ 1, "{ [x, 1 - x] : 0 <= x <= 1; [0,0] }" },
2199 	{ 1, "{ [0,0]; [i,i] : 1 <= i <= 10 }" },
2200 	{ 0, "{ [0,0]; [i,j] : 1 <= i,j <= 10 }" },
2201 	{ 1, "{ [0,0]; [i,2i] : 1 <= i <= 10 }" },
2202 	{ 0, "{ [0,0]; [i,2i] : 2 <= i <= 10 }" },
2203 	{ 0, "{ [1,0]; [i,2i] : 1 <= i <= 10 }" },
2204 	{ 0, "{ [0,1]; [i,2i] : 1 <= i <= 10 }" },
2205 	{ 0, "{ [a, b] : exists e : 2e = a and "
2206 		    "a >= 0 and (a <= 3 or (b <= 0 and b >= -4 + a)) }" },
2207 	{ 0, "{ [i, j, i', j'] : i <= 2 and j <= 2 and "
2208 			"j' >= -1 + 2i + j - 2i' and i' <= -1 + i and "
2209 			"j >= 1 and j' <= i + j - i' and i >= 1; "
2210 		"[1, 1, 1, 1] }" },
2211 	{ 1, "{ [i,j] : exists a,b : i = 2a and j = 3b; "
2212 		 "[i,j] : exists a : j = 3a }" },
2213 	{ 1, "{ [a, b, c] : (c <= 7 - b and b <= 1 and b >= 0 and "
2214 			"c >= 3 + b and b <= 3 + 8a and b >= -26 + 8a and "
2215 			"a >= 3) or "
2216 		    "(b <= 1 and c <= 7 and b >= 0 and c >= 4 + b and "
2217 			"b <= 3 + 8a and b >= -26 + 8a and a >= 3) }" },
2218 	{ 1, "{ [a, 0, c] : c >= 1 and c <= 29 and c >= -1 + 8a and "
2219 				"c <= 6 + 8a and a >= 3; "
2220 		"[a, -1, c] : c >= 1 and c <= 30 and c >= 8a and "
2221 				"c <= 7 + 8a and a >= 3 and a <= 4 }" },
2222 	{ 1, "{ [x,y] : 0 <= x <= 2 and y >= 0 and x + 2y <= 4; "
2223 		"[x,0] : 3 <= x <= 4 }" },
2224 	{ 1, "{ [x,y] : 0 <= x <= 3 and y >= 0 and x + 3y <= 6; "
2225 		"[x,0] : 4 <= x <= 5 }" },
2226 	{ 0, "{ [x,y] : 0 <= x <= 2 and y >= 0 and x + 2y <= 4; "
2227 		"[x,0] : 3 <= x <= 5 }" },
2228 	{ 0, "{ [x,y] : 0 <= x <= 2 and y >= 0 and x + y <= 4; "
2229 		"[x,0] : 3 <= x <= 4 }" },
2230 	{ 1, "{ [i0, i1] : i0 <= 122 and i0 >= 1 and 128i1 >= -249 + i0 and "
2231 			"i1 <= 0; "
2232 		"[i0, 0] : i0 >= 123 and i0 <= 124 }" },
2233 	{ 1, "{ [0,0]; [1,1] }" },
2234 	{ 1, "[n] -> { [k] : 16k <= -1 + n and k >= 1; [0] : n >= 2 }" },
2235 	{ 1, "{ [k, ii, k - ii] : ii >= -6 + k and ii <= 6 and ii >= 1 and "
2236 				"ii <= k;"
2237 		"[k, 0, k] : k <= 6 and k >= 1 }" },
2238 	{ 1, "{ [i,j] : i = 4 j and 0 <= i <= 100;"
2239 		"[i,j] : 1 <= i <= 100 and i >= 4j + 1 and i <= 4j + 2 }" },
2240 	{ 1, "{ [x,y] : x % 2 = 0 and y % 2 = 0; [x,x] : x % 2 = 0 }" },
2241 	{ 1, "[n] -> { [1] : n >= 0;"
2242 		    "[x] : exists (e0 = floor((x)/2): x >= 2 and "
2243 			"2e0 >= -1 + x and 2e0 <= x and 2e0 <= n) }" },
2244 	{ 1, "[n] -> { [x, y] : exists (e0 = floor((x)/2), e1 = floor((y)/3): "
2245 			"3e1 = y and x >= 2 and 2e0 >= -1 + x and "
2246 			"2e0 <= x and 2e0 <= n);"
2247 		    "[1, y] : exists (e0 = floor((y)/3): 3e0 = y and "
2248 			"n >= 0) }" },
2249 	{ 1, "[t1] -> { [i0] : (exists (e0 = floor((63t1)/64): "
2250 				"128e0 >= -134 + 127t1 and t1 >= 2 and "
2251 				"64e0 <= 63t1 and 64e0 >= -63 + 63t1)) or "
2252 				"t1 = 1 }" },
2253 	{ 1, "{ [i, i] : exists (e0 = floor((1 + 2i)/3): 3e0 <= 2i and "
2254 				"3e0 >= -1 + 2i and i <= 9 and i >= 1);"
2255 		"[0, 0] }" },
2256 	{ 1, "{ [t1] : exists (e0 = floor((-11 + t1)/2): 2e0 = -11 + t1 and "
2257 				"t1 >= 13 and t1 <= 16);"
2258 		"[t1] : t1 <= 15 and t1 >= 12 }" },
2259 	{ 1, "{ [x,y] : x = 3y and 0 <= y <= 2; [-3,-1] }" },
2260 	{ 1, "{ [x,y] : 2x = 3y and 0 <= y <= 4; [-3,-2] }" },
2261 	{ 0, "{ [x,y] : 2x = 3y and 0 <= y <= 4; [-2,-2] }" },
2262 	{ 0, "{ [x,y] : 2x = 3y and 0 <= y <= 4; [-3,-1] }" },
2263 	{ 1, "{ [i] : exists j : i = 4 j and 0 <= i <= 100;"
2264 		"[i] : exists j : 1 <= i <= 100 and i >= 4j + 1 and "
2265 				"i <= 4j + 2 }" },
2266 	{ 1, "{ [c0] : (exists (e0 : c0 - 1 <= 3e0 <= c0)) or "
2267 		"(exists (e0 : 3e0 = -2 + c0)) }" },
2268 	{ 0, "[n, b0, t0] -> "
2269 		"{ [i0, i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11, i12] : "
2270 		"(exists (e0 = floor((-32b0 + i4)/1048576), "
2271 		"e1 = floor((i8)/32): 1048576e0 = -32b0 + i4 and 32e1 = i8 and "
2272 		"n <= 2147483647 and b0 <= 32767 and b0 >= 0 and "
2273 		"32b0 <= -2 + n and t0 <= 31 and t0 >= 0 and i0 >= 8 + n and "
2274 		"3i4 <= -96 + 3t0 + i0 and 3i4 >= -95 - n + 3t0 + i0 and "
2275 		"i8 >= -157 + i0 - 4i4 and i8 >= 0 and "
2276 		"i8 <= -33 + i0 - 4i4 and 3i8 <= -91 + 4n - i0)) or "
2277 		"(exists (e0 = floor((-32b0 + i4)/1048576), "
2278 		"e1 = floor((i8)/32): 1048576e0 = -32b0 + i4 and 32e1 = i8 and "
2279 		"n <= 2147483647 and b0 <= 32767 and b0 >= 0 and "
2280 		"32b0 <= -2 + n and t0 <= 31 and t0 >= 0 and i0 <= 7 + n and "
2281 		"4i4 <= -3 + i0 and 3i4 <= -96 + 3t0 + i0 and "
2282 		"3i4 >= -95 - n + 3t0 + i0 and i8 >= -157 + i0 - 4i4 and "
2283 		"i8 >= 0 and i8 <= -4 + i0 - 3i4 and i8 <= -41 + i0));"
2284 		"[i0, i1, i2, i3, 0, i5, i6, i7, i8, i9, i10, i11, i12] : "
2285 		"(exists (e0 = floor((i8)/32): b0 = 0 and 32e0 = i8 and "
2286 		"n <= 2147483647 and t0 <= 31 and t0 >= 0 and i0 >= 11 and "
2287 		"i0 >= 96 - 3t0 and i0 <= 95 + n - 3t0 and i0 <= 7 + n and "
2288 		"i8 >= -40 + i0 and i8 <= -10 + i0)) }" },
2289 	{ 0, "{ [i0, i1, i2] : "
2290 		"(exists (e0, e1 = floor((i0)/32), e2 = floor((i1)/32): "
2291 		"32e1 = i0 and 32e2 = i1 and i1 >= -31 + i0 and "
2292 		"i1 <= 31 + i0 and i2 >= -30 + i0 and i2 >= -30 + i1 and "
2293 		"32e0 >= -30 + i0 and 32e0 >= -30 + i1 and "
2294 		"32e0 >= -31 + i2 and 32e0 <= 30 + i2 and 32e0 <= 31 + i1 and "
2295 		"32e0 <= 31 + i0)) or "
2296 		"i0 >= 0 }" },
2297 	{ 1, "{ [a, b, c] : 2b = 1 + a and 2c = 2 + a; [0, 0, 0] }" },
2298 	{ 1, "{ [a, a, b, c] : 32*floor((a)/32) = a and 2*floor((b)/2) = b and "
2299 				"2*floor((c)/2) = c and 0 <= a <= 192;"
2300 		"[224, 224, b, c] : 2*floor((b)/2) = b and 2*floor((c)/2) = c }"
2301 	},
2302 	{ 1, "[n] -> { [a,b] : (exists e : 1 <= a <= 7e and 9e <= b <= n) or "
2303 				"(0 <= a <= b <= n) }" },
2304 	{ 1, "{ [a, b] : 0 <= a <= 2 and b >= 0 and "
2305 		"((0 < b <= 13) or (2*floor((a + b)/2) >= -5 + a + 2b)) }" },
2306 	{ 1, "{ [a] : (2 <= a <= 5) or (a mod 2 = 1 and 1 <= a <= 5) }" },
2307 	{ 1, "{ [a, b, c] : (b = -1 + a and 0 < a <= 3 and "
2308 				"9*floor((-4a + 2c)/9) <= -3 - 4a + 2c) or "
2309 			"(exists (e0 = floor((-16 + 2c)/9): a = 4 and "
2310 				"b = 3 and 9e0 <= -19 + 2c)) }" },
2311 	{ 1, "{ [a, b, c] : (b = -1 + a and 0 < a <= 3 and "
2312 				"9*floor((-4a + 2c)/9) <= -3 - 4a + 2c) or "
2313 			"(a = 4 and b = 3 and "
2314 				"9*floor((-16 + 2c)/9) <= -19 + 2c) }" },
2315 	{ 0, "{ [a, b, c] : (b <= 2 and b <= -2 + a) or "
2316 			"(b = -1 + a and 0 < a <= 3 and "
2317 				"9*floor((-4a + 2c)/9) <= -3 - 4a + 2c) or "
2318 			"(exists (e0 = floor((-16 + 2c)/9): a = 4 and "
2319 				"b = 3 and 9e0 <= -19 + 2c)) }" },
2320 	{ 1, "{ [y, x] : (x - y) mod 3 = 2 and 2 <= y <= 200 and 0 <= x <= 2;"
2321 		"[1, 0] }" },
2322 	{ 1, "{ [x, y] : (x - y) mod 3 = 2 and 2 <= y <= 200 and 0 <= x <= 2;"
2323 		"[0, 1] }" },
2324 	{ 1, "{ [1, y] : -1 <= y <= 1; [x, -x] : 0 <= x <= 1 }" },
2325 	{ 1, "{ [1, y] : 0 <= y <= 1; [x, -x] : 0 <= x <= 1 }" },
2326 	{ 1, "{ [x, y] : 0 <= x <= 10 and x - 4*floor(x/4) <= 1 and y <= 0; "
2327 	       "[x, y] : 0 <= x <= 10 and x - 4*floor(x/4) > 1 and y <= 0; "
2328 	       "[x, y] : 0 <= x <= 10 and x - 5*floor(x/5) <= 1 and 0 < y; "
2329 	       "[x, y] : 0 <= x <= 10 and x - 5*floor(x/5) > 1 and 0 < y }" },
2330 	{ 1, "{ [x, 0] : 0 <= x <= 10 and x mod 2 = 0; "
2331 	       "[x, 0] : 0 <= x <= 10 and x mod 2 = 1; "
2332 	       "[x, y] : 0 <= x <= 10 and 1 <= y <= 10 }" },
2333 	{ 1, "{ [a] : a <= 8 and "
2334 			"(a mod 10 = 7 or a mod 10 = 8 or a mod 10 = 9) }" },
2335 	{ 1, "{ [x, y] : 2y = -x and x <= 0 or "
2336 			"x <= -1 and 2y <= -x - 1 and 2y >= x - 1 }" },
2337 	{ 0, "{ [x, y] : 2y = -x and x <= 0 or "
2338 			"x <= -2 and 2y <= -x - 1 and 2y >= x - 1 }" },
2339 	{ 1, "{ [a] : (a <= 0 and 3*floor((a)/3) = a) or "
2340 			"(a < 0 and 3*floor((a)/3) < a) }" },
2341 	{ 1, "{ [a] : (a <= 0 and 3*floor((a)/3) = a) or "
2342 			"(a < -1 and 3*floor((a)/3) < a) }" },
2343 	{ 1, "{ [a, b] : a <= 1024 and b >= 0 and "
2344 		"((-31 - a + b <= 32*floor((-1 - a)/32) <= -33 + b and "
2345 		  "32*floor((-1 - a)/32) <= -16 + b + 16*floor((-1 - a)/16))"
2346 		"or (2 <= a <= 15 and b < a)) }" },
2347 	{ 1, "{ [a] : a > 0 and ((16*floor((a)/16) < a and "
2348 			"32*floor((a)/32) < a) or a <= 15) }" },
2349 	{ 1, "{ [a, b, c, d] : (-a + d) mod 64 = 0 and a <= 8 and b <= 1 and "
2350 			"10 - a <= c <= 3 and d >= 5 and 9 - 64b <= d <= 70;"
2351 	    "[a, b = 1, c, d] : (-a + d) mod 64 = 0 and a <= 8 and c >= 4 and "
2352 			"10 - a <= c <= 5 and 5 <= d <= 73 - c }" },
2353 	{ 1, "[n, m] -> { S_0[i] : (-n + i) mod 3 = 0 and m >= 3 + n and "
2354 			    "i >= n and 3*floor((2 + n + 2m)/3) <= n + 3m - i; "
2355 			 "S_0[n] : n <= m <= 2 + n }" },
2356 	{ 1, "{ [a, b] : exists (e0: 0 <= a <= 1 and b >= 0 and "
2357 			"2e0 >= -5 + a + 2b and 2e0 >= -1 + a + b and "
2358 			"2e0 <= a + b); "
2359 		"[a, b] : exists (e0: 0 <= a <= 1 and 2e0 >= -5 + a + 2b and "
2360 			"2e0 >= -1 - a + b and 2e0 <= -a + b and "
2361 			"2e0 < -a + 2b) }" },
2362 	{ 1, "{ [i, j, i - 8j] : 8 <= i <= 63 and -7 + i <= 8j <= i; "
2363 		"[i, 0, i] : 0 <= i <= 7 }" },
2364 	{ 1, "{ [a, b] : a >= 0 and 0 <= b <= 1 - a; [1, 1] }" },
2365 	{ 0, "{ [a, b] : a >= 0 and 0 <= b <= 1 - a; [0, 2] }" },
2366 	{ 0, "{ [a, b] : a >= 0 and 0 <= b <= 1 - a; [-1, 3] }" },
2367 	{ 1, "{ [a, b] : a, b >= 0 and a + 2b <= 2; [1, 1] }" },
2368 	{ 0, "{ [a, b] : a, b >= 0 and a + 2b <= 2; [2, 1] }" },
2369 	{ 0, "{ [a, c] : (2 + a) mod 4 = 0 or "
2370 		"(c = 4 + a and 4 * floor((a)/4) = a and a >= 0 and a <= 4) or "
2371 		"(c = 3 + a and 4 * floor((-1 + a)/4) = -1 + a and "
2372 		    "a > 0 and a <= 5) }" },
2373 	{ 1, "{ [1, 0, 0]; [a, b, c] : -1 <= -a < b <= 0 and 2c > b }" },
2374 	{ 0, "{ [j, a, l] : a mod 2 = 0 and j <= 29 and a >= 2 and "
2375 			"2a <= -5 + j and 32j + 2a + 2 <= 4l < 33j; "
2376 		"[j, 0, l] : 4 <= j <= 29 and -3 + 33j <= 4l <= 33j }" },
2377 	{ 0, "{ [0:1, 0:1]; [0, 2:3] }" },
2378 	{ 1, "{ [a] : (a = 0 or ((1 + a) mod 2 = 0 and 0 < a <= 15) or "
2379 		"((a) mod 2 = 0 and 0 < a <= 15)) }" },
2380 };
2381 
2382 /* A specialized coalescing test case that would result
2383  * in a segmentation fault or a failed assertion in earlier versions of isl.
2384  */
test_coalesce_special(struct isl_ctx * ctx)2385 static int test_coalesce_special(struct isl_ctx *ctx)
2386 {
2387 	const char *str;
2388 	isl_map *map1, *map2;
2389 
2390 	str = "[y] -> { [S_L220_OUT[] -> T7[]] -> "
2391 	    "[[S_L309_IN[] -> T11[]] -> ce_imag2[1, o1]] : "
2392 	    "(y = 201 and o1 <= 239 and o1 >= 212) or "
2393 	    "(exists (e0 = [(y)/3]: 3e0 = y and y <= 198 and y >= 3 and "
2394 		"o1 <= 239 and o1 >= 212)) or "
2395 	    "(exists (e0 = [(y)/3]: 3e0 = y and y <= 201 and y >= 3 and "
2396 		"o1 <= 241 and o1 >= 240));"
2397 	    "[S_L220_OUT[] -> T7[]] -> "
2398 	    "[[S_L309_IN[] -> T11[]] -> ce_imag2[0, o1]] : "
2399 	    "(y = 2 and o1 <= 241 and o1 >= 212) or "
2400 	    "(exists (e0 = [(-2 + y)/3]: 3e0 = -2 + y and y <= 200 and "
2401 		"y >= 5 and o1 <= 241 and o1 >= 212)) }";
2402 	map1 = isl_map_read_from_str(ctx, str);
2403 	map1 = isl_map_align_divs_internal(map1);
2404 	map1 = isl_map_coalesce(map1);
2405 	str = "[y] -> { [S_L220_OUT[] -> T7[]] -> "
2406 	    "[[S_L309_IN[] -> T11[]] -> ce_imag2[o0, o1]] : "
2407 	    "exists (e0 = [(-1 - y + o0)/3]: 3e0 = -1 - y + o0 and "
2408 		"y <= 201 and o0 <= 2 and o1 >= 212 and o1 <= 241 and "
2409 		"o0 >= 3 - y and o0 <= -2 + y and o0 >= 0) }";
2410 	map2 = isl_map_read_from_str(ctx, str);
2411 	map2 = isl_map_union(map2, map1);
2412 	map2 = isl_map_align_divs_internal(map2);
2413 	map2 = isl_map_coalesce(map2);
2414 	isl_map_free(map2);
2415 	if (!map2)
2416 		return -1;
2417 
2418 	return 0;
2419 }
2420 
2421 /* Check that the union of the basic sets described by "str1" and "str2"
2422  * can be coalesced.
2423  * The explicit call to isl_basic_set_union prevents the implicit
2424  * equality constraints in the basic maps from being detected prior
2425  * to the call to isl_set_coalesce, at least at the point
2426  * where this function was introduced.
2427  */
test_coalesce_union(isl_ctx * ctx,const char * str1,const char * str2)2428 static isl_stat test_coalesce_union(isl_ctx *ctx, const char *str1,
2429 	const char *str2)
2430 {
2431 	isl_basic_set *bset1, *bset2;
2432 	isl_set *set;
2433 
2434 	bset1 = isl_basic_set_read_from_str(ctx, str1);
2435 	bset2 = isl_basic_set_read_from_str(ctx, str2);
2436 	set = isl_basic_set_union(bset1, bset2);
2437 	set = isl_set_coalesce(set);
2438 	isl_set_free(set);
2439 
2440 	return isl_stat_non_null(set);
2441 }
2442 
2443 /* A specialized coalescing test case that would result in an assertion
2444  * in an earlier version of isl.  Use test_coalesce_union with
2445  * an explicit call to isl_basic_set_union to prevent the implicit
2446  * equality constraints in the first basic map from being detected prior
2447  * to the call to isl_set_coalesce, at least at the point
2448  * where this test case was introduced.
2449  */
test_coalesce_special2(struct isl_ctx * ctx)2450 static isl_stat test_coalesce_special2(struct isl_ctx *ctx)
2451 {
2452 	const char *str1;
2453 	const char *str2;
2454 
2455 	str1 = "{ [x, y] : x, y >= 0 and x + 2y <= 1 and 2x + y <= 1 }";
2456 	str2 = "{ [x,0] : -1 <= x <= 1 and x mod 2 = 1 }";
2457 	return test_coalesce_union(ctx, str1, str2);
2458 }
2459 
2460 /* Check that calling isl_set_coalesce does not leave other sets
2461  * that may share some information with the input to isl_set_coalesce
2462  * in an inconsistent state.
2463  * In particular, older versions of isl would modify all copies
2464  * of the basic sets in the isl_set_coalesce input in a way
2465  * that could leave them in an inconsistent state.
2466  * The result of printing any other set containing one of these
2467  * basic sets would then result in an invalid set description.
2468  */
test_coalesce_special3(isl_ctx * ctx)2469 static int test_coalesce_special3(isl_ctx *ctx)
2470 {
2471 	const char *str;
2472 	char *s;
2473 	isl_set *set1, *set2;
2474 	isl_printer *p;
2475 
2476 	set1 = isl_set_read_from_str(ctx, "{ [0, 0, 0] }");
2477 	str = "{ [a, b, a + b] : a >= 0 and b >= 0 and 0 < a + b }";
2478 	set2 = isl_set_read_from_str(ctx, str);
2479 	set1 = isl_set_union(set1, isl_set_copy(set2));
2480 	set1 = isl_set_coalesce(set1);
2481 	isl_set_free(set1);
2482 
2483 	p = isl_printer_to_str(ctx);
2484 	p = isl_printer_print_set(p, set2);
2485 	isl_set_free(set2);
2486 	s = isl_printer_get_str(p);
2487 	isl_printer_free(p);
2488 	set1 = isl_set_read_from_str(ctx, s);
2489 	free(s);
2490 	isl_set_free(set1);
2491 
2492 	if (!set1)
2493 		return -1;
2494 
2495 	return 0;
2496 }
2497 
2498 /* Check that calling isl_set_coalesce on the intersection of
2499  * the sets described by "s1" and "s2" does not leave other sets
2500  * that may share some information with the input to isl_set_coalesce
2501  * in an inconsistent state.
2502  * In particular, when isl_set_coalesce detects equality constraints,
2503  * it does not immediately perform Gaussian elimination on them,
2504  * but then it needs to ensure that it is performed at some point.
2505  * The input set has implicit equality constraints in the first disjunct.
2506  * It is constructed as an intersection, because otherwise
2507  * those equality constraints would already be detected during parsing.
2508  */
test_coalesce_intersection(isl_ctx * ctx,const char * s1,const char * s2)2509 static isl_stat test_coalesce_intersection(isl_ctx *ctx,
2510 	const char *s1, const char *s2)
2511 {
2512 	isl_set *set1, *set2;
2513 
2514 	set1 = isl_set_read_from_str(ctx, s1);
2515 	set2 = isl_set_read_from_str(ctx, s2);
2516 	set1 = isl_set_intersect(set1, set2);
2517 	isl_set_free(isl_set_coalesce(isl_set_copy(set1)));
2518 	set1 = isl_set_coalesce(set1);
2519 	isl_set_free(set1);
2520 
2521 	if (!set1)
2522 		return isl_stat_error;
2523 
2524 	return isl_stat_ok;
2525 }
2526 
2527 /* Check that calling isl_set_coalesce does not leave other sets
2528  * that may share some information with the input to isl_set_coalesce
2529  * in an inconsistent state, for the case where one disjunct
2530  * is a subset of the other.
2531  */
test_coalesce_special4(isl_ctx * ctx)2532 static isl_stat test_coalesce_special4(isl_ctx *ctx)
2533 {
2534 	const char *s1, *s2;
2535 
2536 	s1 = "{ [a, b] : b <= 0 or a <= 1 }";
2537 	s2 = "{ [a, b] : -1 <= -a < b }";
2538 	return test_coalesce_intersection(ctx, s1, s2);
2539 }
2540 
2541 /* Check that calling isl_set_coalesce does not leave other sets
2542  * that may share some information with the input to isl_set_coalesce
2543  * in an inconsistent state, for the case where two disjuncts
2544  * can be fused.
2545  */
test_coalesce_special5(isl_ctx * ctx)2546 static isl_stat test_coalesce_special5(isl_ctx *ctx)
2547 {
2548 	const char *s1, *s2;
2549 
2550 	s1 = "{ [a, b, c] : b <= 0 }";
2551 	s2 = "{ [a, b, c] : -1 <= -a < b and (c >= 0 or c < 0) }";
2552 	return test_coalesce_intersection(ctx, s1, s2);
2553 }
2554 
2555 /* Check that calling isl_set_coalesce does not leave other sets
2556  * that may share some information with the input to isl_set_coalesce
2557  * in an inconsistent state, for the case where two disjuncts
2558  * can be fused and where both disjuncts have implicit equality constraints.
2559  */
test_coalesce_special6(isl_ctx * ctx)2560 static isl_stat test_coalesce_special6(isl_ctx *ctx)
2561 {
2562 	const char *s1, *s2;
2563 
2564 	s1 = "{ [a, b, c] : c <= 0 }";
2565 	s2 = "{ [a, b, c] : 0 <= a <= b <= c or (0 <= b <= c and a > 0) }";
2566 	return test_coalesce_intersection(ctx, s1, s2);
2567 }
2568 
2569 /* A specialized coalescing test case that would result in an assertion failure
2570  * in an earlier version of isl.  Use test_coalesce_union with
2571  * an explicit call to isl_basic_set_union to prevent the implicit
2572  * equality constraints in the basic maps from being detected prior
2573  * to the call to isl_set_coalesce, at least at the point
2574  * where this test case was introduced.
2575  */
test_coalesce_special7(isl_ctx * ctx)2576 static isl_stat test_coalesce_special7(isl_ctx *ctx)
2577 {
2578 	const char *str1;
2579 	const char *str2;
2580 
2581 	str1 = "{ [a, b, c=0:17] : a <= 7 and 2b <= 11 - a and "
2582 			"c <= -7 + 2a and 2c >= - 3 + 3a - 2b }";
2583 	str2 = "{ [a, b, c] : c > -15a and c >= -7 + 2a and c < 0 and "
2584 			"3c <= -5 + 5a - 3b and 2b >= 11 - a }";
2585 	return test_coalesce_union(ctx, str1, str2);
2586 }
2587 
2588 /* Test the functionality of isl_set_coalesce.
2589  * That is, check that the output is always equal to the input
2590  * and in some cases that the result consists of a single disjunct.
2591  */
test_coalesce(struct isl_ctx * ctx)2592 static int test_coalesce(struct isl_ctx *ctx)
2593 {
2594 	int i;
2595 
2596 	for (i = 0; i < ARRAY_SIZE(coalesce_tests); ++i) {
2597 		const char *str = coalesce_tests[i].str;
2598 		int check_one = coalesce_tests[i].single_disjunct;
2599 		if (test_coalesce_set(ctx, str, check_one) < 0)
2600 			return -1;
2601 	}
2602 
2603 	if (test_coalesce_unbounded_wrapping(ctx) < 0)
2604 		return -1;
2605 	if (test_coalesce_special(ctx) < 0)
2606 		return -1;
2607 	if (test_coalesce_special2(ctx) < 0)
2608 		return -1;
2609 	if (test_coalesce_special3(ctx) < 0)
2610 		return -1;
2611 	if (test_coalesce_special4(ctx) < 0)
2612 		return -1;
2613 	if (test_coalesce_special5(ctx) < 0)
2614 		return -1;
2615 	if (test_coalesce_special6(ctx) < 0)
2616 		return -1;
2617 	if (test_coalesce_special7(ctx) < 0)
2618 		return -1;
2619 
2620 
2621 	return 0;
2622 }
2623 
2624 /* Construct a representation of the graph on the right of Figure 1
2625  * in "Computing the Transitive Closure of a Union of
2626  * Affine Integer Tuple Relations".
2627  */
cocoa_fig_1_right_graph(isl_ctx * ctx)2628 static __isl_give isl_map *cocoa_fig_1_right_graph(isl_ctx *ctx)
2629 {
2630 	isl_set *dom;
2631 	isl_map *up, *right;
2632 
2633 	dom = isl_set_read_from_str(ctx,
2634 		"{ [x,y] : x >= 0 and -2 x + 3 y >= 0 and x <= 3 and "
2635 			"2 x - 3 y + 3 >= 0 }");
2636 	right = isl_map_read_from_str(ctx,
2637 		"{ [x,y] -> [x2,y2] : x2 = x + 1 and y2 = y }");
2638 	up = isl_map_read_from_str(ctx,
2639 		"{ [x,y] -> [x2,y2] : x2 = x and y2 = y + 1 }");
2640 	right = isl_map_intersect_domain(right, isl_set_copy(dom));
2641 	right = isl_map_intersect_range(right, isl_set_copy(dom));
2642 	up = isl_map_intersect_domain(up, isl_set_copy(dom));
2643 	up = isl_map_intersect_range(up, dom);
2644 	return isl_map_union(up, right);
2645 }
2646 
2647 /* Construct a representation of the power of the graph
2648  * on the right of Figure 1 in "Computing the Transitive Closure of
2649  * a Union of Affine Integer Tuple Relations".
2650  */
cocoa_fig_1_right_power(isl_ctx * ctx)2651 static __isl_give isl_map *cocoa_fig_1_right_power(isl_ctx *ctx)
2652 {
2653 	return isl_map_read_from_str(ctx,
2654 		"{ [1] -> [[0,0] -> [0,1]]; [2] -> [[0,0] -> [1,1]]; "
2655 		"  [1] -> [[0,1] -> [1,1]]; [1] -> [[2,2] -> [3,2]]; "
2656 		"  [2] -> [[2,2] -> [3,3]]; [1] -> [[3,2] -> [3,3]] }");
2657 }
2658 
2659 /* Construct a representation of the transitive closure of the graph
2660  * on the right of Figure 1 in "Computing the Transitive Closure of
2661  * a Union of Affine Integer Tuple Relations".
2662  */
cocoa_fig_1_right_tc(isl_ctx * ctx)2663 static __isl_give isl_map *cocoa_fig_1_right_tc(isl_ctx *ctx)
2664 {
2665 	return isl_set_unwrap(isl_map_range(cocoa_fig_1_right_power(ctx)));
2666 }
2667 
test_closure(isl_ctx * ctx)2668 static int test_closure(isl_ctx *ctx)
2669 {
2670 	const char *str;
2671 	isl_map *map, *map2;
2672 	isl_bool exact, equal;
2673 
2674 	/* COCOA example 1 */
2675 	map = isl_map_read_from_str(ctx,
2676 		"[n] -> { [i,j] -> [i2,j2] : i2 = i + 1 and j2 = j + 1 and "
2677 			"1 <= i and i < n and 1 <= j and j < n or "
2678 			"i2 = i + 1 and j2 = j - 1 and "
2679 			"1 <= i and i < n and 2 <= j and j <= n }");
2680 	map = isl_map_power(map, &exact);
2681 	assert(exact);
2682 	isl_map_free(map);
2683 
2684 	/* COCOA example 1 */
2685 	map = isl_map_read_from_str(ctx,
2686 		"[n] -> { [i,j] -> [i2,j2] : i2 = i + 1 and j2 = j + 1 and "
2687 			"1 <= i and i < n and 1 <= j and j < n or "
2688 			"i2 = i + 1 and j2 = j - 1 and "
2689 			"1 <= i and i < n and 2 <= j and j <= n }");
2690 	map = isl_map_transitive_closure(map, &exact);
2691 	assert(exact);
2692 	map2 = isl_map_read_from_str(ctx,
2693 		"[n] -> { [i,j] -> [i2,j2] : exists (k1,k2,k : "
2694 			"1 <= i and i < n and 1 <= j and j <= n and "
2695 			"2 <= i2 and i2 <= n and 1 <= j2 and j2 <= n and "
2696 			"i2 = i + k1 + k2 and j2 = j + k1 - k2 and "
2697 			"k1 >= 0 and k2 >= 0 and k1 + k2 = k and k >= 1 )}");
2698 	assert(isl_map_is_equal(map, map2));
2699 	isl_map_free(map2);
2700 	isl_map_free(map);
2701 
2702 	map = isl_map_read_from_str(ctx,
2703 		"[n] -> { [x] -> [y] : y = x + 1 and 0 <= x and x <= n and "
2704 				     " 0 <= y and y <= n }");
2705 	map = isl_map_transitive_closure(map, &exact);
2706 	map2 = isl_map_read_from_str(ctx,
2707 		"[n] -> { [x] -> [y] : y > x and 0 <= x and x <= n and "
2708 				     " 0 <= y and y <= n }");
2709 	assert(isl_map_is_equal(map, map2));
2710 	isl_map_free(map2);
2711 	isl_map_free(map);
2712 
2713 	/* COCOA example 2 */
2714 	map = isl_map_read_from_str(ctx,
2715 		"[n] -> { [i,j] -> [i2,j2] : i2 = i + 2 and j2 = j + 2 and "
2716 			"1 <= i and i < n - 1 and 1 <= j and j < n - 1 or "
2717 			"i2 = i + 2 and j2 = j - 2 and "
2718 			"1 <= i and i < n - 1 and 3 <= j and j <= n }");
2719 	map = isl_map_transitive_closure(map, &exact);
2720 	assert(exact);
2721 	map2 = isl_map_read_from_str(ctx,
2722 		"[n] -> { [i,j] -> [i2,j2] : exists (k1,k2,k : "
2723 			"1 <= i and i < n - 1 and 1 <= j and j <= n and "
2724 			"3 <= i2 and i2 <= n and 1 <= j2 and j2 <= n and "
2725 			"i2 = i + 2 k1 + 2 k2 and j2 = j + 2 k1 - 2 k2 and "
2726 			"k1 >= 0 and k2 >= 0 and k1 + k2 = k and k >= 1) }");
2727 	assert(isl_map_is_equal(map, map2));
2728 	isl_map_free(map);
2729 	isl_map_free(map2);
2730 
2731 	/* COCOA Fig.2 left */
2732 	map = isl_map_read_from_str(ctx,
2733 		"[n] -> { [i,j] -> [i2,j2] : i2 = i + 2 and j2 = j and "
2734 			"i <= 2 j - 3 and i <= n - 2 and j <= 2 i - 1 and "
2735 			"j <= n or "
2736 			"i2 = i and j2 = j + 2 and i <= 2 j - 1 and i <= n and "
2737 			"j <= 2 i - 3 and j <= n - 2 or "
2738 			"i2 = i + 1 and j2 = j + 1 and i <= 2 j - 1 and "
2739 			"i <= n - 1 and j <= 2 i - 1 and j <= n - 1 }");
2740 	map = isl_map_transitive_closure(map, &exact);
2741 	assert(exact);
2742 	isl_map_free(map);
2743 
2744 	/* COCOA Fig.2 right */
2745 	map = isl_map_read_from_str(ctx,
2746 		"[n] -> { [i,j] -> [i2,j2] : i2 = i + 3 and j2 = j and "
2747 			"i <= 2 j - 4 and i <= n - 3 and j <= 2 i - 1 and "
2748 			"j <= n or "
2749 			"i2 = i and j2 = j + 3 and i <= 2 j - 1 and i <= n and "
2750 			"j <= 2 i - 4 and j <= n - 3 or "
2751 			"i2 = i + 1 and j2 = j + 1 and i <= 2 j - 1 and "
2752 			"i <= n - 1 and j <= 2 i - 1 and j <= n - 1 }");
2753 	map = isl_map_power(map, &exact);
2754 	assert(exact);
2755 	isl_map_free(map);
2756 
2757 	/* COCOA Fig.2 right */
2758 	map = isl_map_read_from_str(ctx,
2759 		"[n] -> { [i,j] -> [i2,j2] : i2 = i + 3 and j2 = j and "
2760 			"i <= 2 j - 4 and i <= n - 3 and j <= 2 i - 1 and "
2761 			"j <= n or "
2762 			"i2 = i and j2 = j + 3 and i <= 2 j - 1 and i <= n and "
2763 			"j <= 2 i - 4 and j <= n - 3 or "
2764 			"i2 = i + 1 and j2 = j + 1 and i <= 2 j - 1 and "
2765 			"i <= n - 1 and j <= 2 i - 1 and j <= n - 1 }");
2766 	map = isl_map_transitive_closure(map, &exact);
2767 	assert(exact);
2768 	map2 = isl_map_read_from_str(ctx,
2769 		"[n] -> { [i,j] -> [i2,j2] : exists (k1,k2,k3,k : "
2770 			"i <= 2 j - 1 and i <= n and j <= 2 i - 1 and "
2771 			"j <= n and 3 + i + 2 j <= 3 n and "
2772 			"3 + 2 i + j <= 3n and i2 <= 2 j2 -1 and i2 <= n and "
2773 			"i2 <= 3 j2 - 4 and j2 <= 2 i2 -1 and j2 <= n and "
2774 			"13 + 4 j2 <= 11 i2 and i2 = i + 3 k1 + k3 and "
2775 			"j2 = j + 3 k2 + k3 and k1 >= 0 and k2 >= 0 and "
2776 			"k3 >= 0 and k1 + k2 + k3 = k and k > 0) }");
2777 	assert(isl_map_is_equal(map, map2));
2778 	isl_map_free(map2);
2779 	isl_map_free(map);
2780 
2781 	map = cocoa_fig_1_right_graph(ctx);
2782 	map = isl_map_transitive_closure(map, &exact);
2783 	assert(exact);
2784 	map2 = cocoa_fig_1_right_tc(ctx);
2785 	assert(isl_map_is_equal(map, map2));
2786 	isl_map_free(map2);
2787 	isl_map_free(map);
2788 
2789 	map = cocoa_fig_1_right_graph(ctx);
2790 	map = isl_map_power(map, &exact);
2791 	map2 = cocoa_fig_1_right_power(ctx);
2792 	equal = isl_map_is_equal(map, map2);
2793 	isl_map_free(map2);
2794 	isl_map_free(map);
2795 	if (equal < 0)
2796 		return -1;
2797 	if (!exact)
2798 		isl_die(ctx, isl_error_unknown, "power not exact", return -1);
2799 	if (!equal)
2800 		isl_die(ctx, isl_error_unknown, "unexpected power", return -1);
2801 
2802 	/* COCOA Theorem 1 counter example */
2803 	map = isl_map_read_from_str(ctx,
2804 		"{ [i,j] -> [i2,j2] : i = 0 and 0 <= j and j <= 1 and "
2805 			"i2 = 1 and j2 = j or "
2806 			"i = 0 and j = 0 and i2 = 0 and j2 = 1 }");
2807 	map = isl_map_transitive_closure(map, &exact);
2808 	assert(exact);
2809 	isl_map_free(map);
2810 
2811 	map = isl_map_read_from_str(ctx,
2812 		"[m,n] -> { [i,j] -> [i2,j2] : i2 = i and j2 = j + 2 and "
2813 			"1 <= i,i2 <= n and 1 <= j,j2 <= m or "
2814 			"i2 = i + 1 and 3 <= j2 - j <= 4 and "
2815 			"1 <= i,i2 <= n and 1 <= j,j2 <= m }");
2816 	map = isl_map_transitive_closure(map, &exact);
2817 	assert(exact);
2818 	isl_map_free(map);
2819 
2820 	/* Kelly et al 1996, fig 12 */
2821 	map = isl_map_read_from_str(ctx,
2822 		"[n] -> { [i,j] -> [i2,j2] : i2 = i and j2 = j + 1 and "
2823 			"1 <= i,j,j+1 <= n or "
2824 			"j = n and j2 = 1 and i2 = i + 1 and "
2825 			"1 <= i,i+1 <= n }");
2826 	map = isl_map_transitive_closure(map, &exact);
2827 	assert(exact);
2828 	map2 = isl_map_read_from_str(ctx,
2829 		"[n] -> { [i,j] -> [i2,j2] : 1 <= j < j2 <= n and "
2830 			"1 <= i <= n and i = i2 or "
2831 			"1 <= i < i2 <= n and 1 <= j <= n and "
2832 			"1 <= j2 <= n }");
2833 	assert(isl_map_is_equal(map, map2));
2834 	isl_map_free(map2);
2835 	isl_map_free(map);
2836 
2837 	/* Omega's closure4 */
2838 	map = isl_map_read_from_str(ctx,
2839 		"[m,n] -> { [x,y] -> [x2,y2] : x2 = x and y2 = y + 1 and "
2840 			"1 <= x,y <= 10 or "
2841 			"x2 = x + 1 and y2 = y and "
2842 			"1 <= x <= 20 && 5 <= y <= 15 }");
2843 	map = isl_map_transitive_closure(map, &exact);
2844 	assert(exact);
2845 	isl_map_free(map);
2846 
2847 	map = isl_map_read_from_str(ctx,
2848 		"[n] -> { [x] -> [y]: 1 <= n <= y - x <= 10 }");
2849 	map = isl_map_transitive_closure(map, &exact);
2850 	assert(!exact);
2851 	map2 = isl_map_read_from_str(ctx,
2852 		"[n] -> { [x] -> [y] : 1 <= n <= 10 and y >= n + x }");
2853 	assert(isl_map_is_equal(map, map2));
2854 	isl_map_free(map);
2855 	isl_map_free(map2);
2856 
2857 	str = "[n, m] -> { [i0, i1, i2, i3] -> [o0, o1, o2, o3] : "
2858 	    "i3 = 1 and o0 = i0 and o1 = -1 + i1 and o2 = -1 + i2 and "
2859 	    "o3 = -2 + i2 and i1 <= -1 + i0 and i1 >= 1 - m + i0 and "
2860 	    "i1 >= 2 and i1 <= n and i2 >= 3 and i2 <= 1 + n and i2 <= m }";
2861 	map = isl_map_read_from_str(ctx, str);
2862 	map = isl_map_transitive_closure(map, &exact);
2863 	assert(exact);
2864 	map2 = isl_map_read_from_str(ctx, str);
2865 	assert(isl_map_is_equal(map, map2));
2866 	isl_map_free(map);
2867 	isl_map_free(map2);
2868 
2869 	str = "{[0] -> [1]; [2] -> [3]}";
2870 	map = isl_map_read_from_str(ctx, str);
2871 	map = isl_map_transitive_closure(map, &exact);
2872 	assert(exact);
2873 	map2 = isl_map_read_from_str(ctx, str);
2874 	assert(isl_map_is_equal(map, map2));
2875 	isl_map_free(map);
2876 	isl_map_free(map2);
2877 
2878 	str = "[n] -> { [[i0, i1, 1, 0, i0] -> [i5, 1]] -> "
2879 	    "[[i0, -1 + i1, 2, 0, i0] -> [-1 + i5, 2]] : "
2880 	    "exists (e0 = [(3 - n)/3]: i5 >= 2 and i1 >= 2 and "
2881 	    "3i0 <= -1 + n and i1 <= -1 + n and i5 <= -1 + n and "
2882 	    "3e0 >= 1 - n and 3e0 <= 2 - n and 3i0 >= -2 + n); "
2883 	    "[[i0, i1, 2, 0, i0] -> [i5, 1]] -> "
2884 	    "[[i0, i1, 1, 0, i0] -> [-1 + i5, 2]] : "
2885 	    "exists (e0 = [(3 - n)/3]: i5 >= 2 and i1 >= 1 and "
2886 	    "3i0 <= -1 + n and i1 <= -1 + n and i5 <= -1 + n and "
2887 	    "3e0 >= 1 - n and 3e0 <= 2 - n and 3i0 >= -2 + n); "
2888 	    "[[i0, i1, 1, 0, i0] -> [i5, 2]] -> "
2889 	    "[[i0, -1 + i1, 2, 0, i0] -> [i5, 1]] : "
2890 	    "exists (e0 = [(3 - n)/3]: i1 >= 2 and i5 >= 1 and "
2891 	    "3i0 <= -1 + n and i1 <= -1 + n and i5 <= -1 + n and "
2892 	    "3e0 >= 1 - n and 3e0 <= 2 - n and 3i0 >= -2 + n); "
2893 	    "[[i0, i1, 2, 0, i0] -> [i5, 2]] -> "
2894 	    "[[i0, i1, 1, 0, i0] -> [i5, 1]] : "
2895 	    "exists (e0 = [(3 - n)/3]: i5 >= 1 and i1 >= 1 and "
2896 	    "3i0 <= -1 + n and i1 <= -1 + n and i5 <= -1 + n and "
2897 	    "3e0 >= 1 - n and 3e0 <= 2 - n and 3i0 >= -2 + n) }";
2898 	map = isl_map_read_from_str(ctx, str);
2899 	map = isl_map_transitive_closure(map, NULL);
2900 	assert(map);
2901 	isl_map_free(map);
2902 
2903 	return 0;
2904 }
2905 
2906 /* Check that the actual result of a boolean operation is equal
2907  * to the expected result.
2908  */
check_bool(isl_ctx * ctx,isl_bool actual,isl_bool expected)2909 static isl_stat check_bool(isl_ctx *ctx, isl_bool actual, isl_bool expected)
2910 {
2911 	if (actual != expected)
2912 		isl_die(ctx, isl_error_unknown,
2913 			"incorrect boolean operation", return isl_stat_error);
2914 	return isl_stat_ok;
2915 }
2916 
2917 /* Test operations on isl_bool values.
2918  *
2919  * This tests:
2920  *
2921  * 	isl_bool_not
2922  * 	isl_bool_ok
2923  */
test_isl_bool(isl_ctx * ctx)2924 static int test_isl_bool(isl_ctx *ctx)
2925 {
2926 	if (check_bool(ctx, isl_bool_not(isl_bool_true), isl_bool_false) < 0)
2927 		return -1;
2928 	if (check_bool(ctx, isl_bool_not(isl_bool_false), isl_bool_true) < 0)
2929 		return -1;
2930 	if (check_bool(ctx, isl_bool_not(isl_bool_error), isl_bool_error) < 0)
2931 		return -1;
2932 	if (check_bool(ctx, isl_bool_ok(0), isl_bool_false) < 0)
2933 		return -1;
2934 	if (check_bool(ctx, isl_bool_ok(1), isl_bool_true) < 0)
2935 		return -1;
2936 	if (check_bool(ctx, isl_bool_ok(-1), isl_bool_true) < 0)
2937 		return -1;
2938 	if (check_bool(ctx, isl_bool_ok(2), isl_bool_true) < 0)
2939 		return -1;
2940 	if (check_bool(ctx, isl_bool_ok(-2), isl_bool_true) < 0)
2941 		return -1;
2942 
2943 	return 0;
2944 }
2945 
test_lex(struct isl_ctx * ctx)2946 static int test_lex(struct isl_ctx *ctx)
2947 {
2948 	isl_space *space;
2949 	isl_map *map;
2950 	int empty;
2951 
2952 	space = isl_space_set_alloc(ctx, 0, 0);
2953 	map = isl_map_lex_le(space);
2954 	empty = isl_map_is_empty(map);
2955 	isl_map_free(map);
2956 
2957 	if (empty < 0)
2958 		return -1;
2959 	if (empty)
2960 		isl_die(ctx, isl_error_unknown,
2961 			"expecting non-empty result", return -1);
2962 
2963 	return 0;
2964 }
2965 
2966 /* Inputs for isl_map_lexmin tests.
2967  * "map" is the input and "lexmin" is the expected result.
2968  */
2969 struct {
2970 	const char *map;
2971 	const char *lexmin;
2972 } lexmin_tests [] = {
2973 	{ "{ [x] -> [y] : x <= y <= 10; [x] -> [5] : -8 <= x <= 8 }",
2974 	  "{ [x] -> [5] : 6 <= x <= 8; "
2975 	    "[x] -> [x] : x <= 5 or (9 <= x <= 10) }" },
2976 	{ "{ [x] -> [y] : 4y = x or 4y = -1 + x or 4y = -2 + x }",
2977 	  "{ [x] -> [y] : 4y = x or 4y = -1 + x or 4y = -2 + x }" },
2978 	{ "{ [x] -> [y] : x = 4y; [x] -> [y] : x = 2y }",
2979 	  "{ [x] -> [y] : (4y = x and x >= 0) or "
2980 		"(exists (e0 = [(x)/4], e1 = [(-2 + x)/4]: 2y = x and "
2981 		"4e1 = -2 + x and 4e0 <= -1 + x and 4e0 >= -3 + x)) or "
2982 		"(exists (e0 = [(x)/4]: 2y = x and 4e0 = x and x <= -4)) }" },
2983 	{ "{ T[a] -> S[b, c] : a = 4b-2c and c >= b }",
2984 	  "{ T[a] -> S[b, c] : 2b = a and 2c = a }" },
2985 	/* Check that empty pieces are properly combined. */
2986 	{ "[K, N] -> { [x, y] -> [a, b] : K+2<=N<=K+4 and x>=4 and "
2987 		"2N-6<=x<K+N and N-1<=a<=K+N-1 and N+b-6<=a<=2N-4 and "
2988 		"b<=2N-3K+a and 3b<=4N-K+1 and b>=N and a>=x+1 }",
2989 	  "[K, N] -> { [x, y] -> [1 + x, N] : x >= -6 + 2N and "
2990 		"x <= -5 + 2N and x >= -1 + 3K - N and x <= -2 + K + N and "
2991 		"x >= 4 }" },
2992 	{ "{ [i, k, j] -> [a, b, c, d] : 8*floor((b)/8) = b and k <= 255 and "
2993 		"a <= 255 and c <= 255 and d <= 255 - j and "
2994 		"255 - j <= 7d <= 7 - i and 240d <= 239 + a and "
2995 		"247d <= 247 + k - j and 247d <= 247 + k - b and "
2996 		"247d <= 247 + i and 248 - b <= 248d <= c and "
2997 		"254d >= i - a + b and 254d >= -a + b and "
2998 		"255d >= -i + a - b and 1792d >= -63736 + 257b }",
2999 	  "{ [i, k, j] -> "
3000 	    "[-127762 + i + 502j, -62992 + 248j, 63240 - 248j, 255 - j] : "
3001 		"k <= 255 and 7j >= 1778 + i and 246j >= 62738 - k and "
3002 		"247j >= 62738 - i and 509j <= 129795 + i and "
3003 		"742j >= 188724 - i; "
3004 	    "[0, k, j] -> [1, 0, 248, 1] : k <= 255 and 248 <= j <= 254, k }" },
3005 	{ "{ [a] -> [b] : 0 <= b <= 255 and -509 + a <= 512b < a and "
3006 			"16*floor((8 + b)/16) <= 7 + b; "
3007 	    "[a] -> [1] }",
3008 	  "{ [a] -> [b = 1] : a >= 510 or a <= 0; "
3009 	    "[a] -> [b = 0] : 0 < a <= 509 }" },
3010 	{ "{ rat: [i] : 1 <= 2i <= 9 }", "{ rat: [i] : 2i = 1 }" },
3011 	{ "{ rat: [i] : 1 <= 2i <= 9 or i >= 10 }", "{ rat: [i] : 2i = 1 }" },
3012 	{ "{ rat: [i] : 21 <= 2i <= 29 or i = 5 }", "{ rat: [5] }" },
3013 };
3014 
test_lexmin(struct isl_ctx * ctx)3015 static int test_lexmin(struct isl_ctx *ctx)
3016 {
3017 	int i;
3018 	int equal;
3019 	const char *str;
3020 	isl_basic_map *bmap;
3021 	isl_map *map, *map2;
3022 	isl_set *set;
3023 	isl_set *set2;
3024 	isl_pw_multi_aff *pma;
3025 
3026 	str = "[p0, p1] -> { [] -> [] : "
3027 	    "exists (e0 = [(2p1)/3], e1, e2, e3 = [(3 - p1 + 3e0)/3], "
3028 	    "e4 = [(p1)/3], e5 = [(p1 + 3e4)/3]: "
3029 	    "3e0 >= -2 + 2p1 and 3e0 >= p1 and 3e3 >= 1 - p1 + 3e0 and "
3030 	    "3e0 <= 2p1 and 3e3 >= -2 + p1 and 3e3 <= -1 + p1 and p1 >= 3 and "
3031 	    "3e5 >= -2 + 2p1 and 3e5 >= p1 and 3e5 <= -1 + p1 + 3e4 and "
3032 	    "3e4 <= p1 and 3e4 >= -2 + p1 and e3 <= -1 + e0 and "
3033 	    "3e4 >= 6 - p1 + 3e1 and 3e1 >= p1 and 3e5 >= -2 + p1 + 3e4 and "
3034 	    "2e4 >= 3 - p1 + 2e1 and e4 <= e1 and 3e3 <= 2 - p1 + 3e0 and "
3035 	    "e5 >= 1 + e1 and 3e4 >= 6 - 2p1 + 3e1 and "
3036 	    "p0 >= 2 and p1 >= p0 and 3e2 >= p1 and 3e4 >= 6 - p1 + 3e2 and "
3037 	    "e2 <= e1 and e3 >= 1 and e4 <= e2) }";
3038 	map = isl_map_read_from_str(ctx, str);
3039 	map = isl_map_lexmin(map);
3040 	isl_map_free(map);
3041 	if (!map)
3042 		return -1;
3043 
3044 	str = "[C] -> { [obj,a,b,c] : obj <= 38 a + 7 b + 10 c and "
3045 	    "a + b <= 1 and c <= 10 b and c <= C and a,b,c,C >= 0 }";
3046 	set = isl_set_read_from_str(ctx, str);
3047 	set = isl_set_lexmax(set);
3048 	str = "[C] -> { [obj,a,b,c] : C = 8 }";
3049 	set2 = isl_set_read_from_str(ctx, str);
3050 	set = isl_set_intersect(set, set2);
3051 	assert(!isl_set_is_empty(set));
3052 	isl_set_free(set);
3053 
3054 	for (i = 0; i < ARRAY_SIZE(lexmin_tests); ++i) {
3055 		map = isl_map_read_from_str(ctx, lexmin_tests[i].map);
3056 		map = isl_map_lexmin(map);
3057 		map2 = isl_map_read_from_str(ctx, lexmin_tests[i].lexmin);
3058 		equal = isl_map_is_equal(map, map2);
3059 		isl_map_free(map);
3060 		isl_map_free(map2);
3061 
3062 		if (equal < 0)
3063 			return -1;
3064 		if (!equal)
3065 			isl_die(ctx, isl_error_unknown,
3066 				"unexpected result", return -1);
3067 	}
3068 
3069 	str = "{ [i] -> [i', j] : j = i - 8i' and i' >= 0 and i' <= 7 and "
3070 				" 8i' <= i and 8i' >= -7 + i }";
3071 	bmap = isl_basic_map_read_from_str(ctx, str);
3072 	pma = isl_basic_map_lexmin_pw_multi_aff(isl_basic_map_copy(bmap));
3073 	map2 = isl_map_from_pw_multi_aff(pma);
3074 	map = isl_map_from_basic_map(bmap);
3075 	assert(isl_map_is_equal(map, map2));
3076 	isl_map_free(map);
3077 	isl_map_free(map2);
3078 
3079 	str = "[i] -> { [i', j] : j = i - 8i' and i' >= 0 and i' <= 7 and "
3080 				" 8i' <= i and 8i' >= -7 + i }";
3081 	set = isl_set_read_from_str(ctx, str);
3082 	pma = isl_set_lexmin_pw_multi_aff(isl_set_copy(set));
3083 	set2 = isl_set_from_pw_multi_aff(pma);
3084 	equal = isl_set_is_equal(set, set2);
3085 	isl_set_free(set);
3086 	isl_set_free(set2);
3087 	if (equal < 0)
3088 		return -1;
3089 	if (!equal)
3090 		isl_die(ctx, isl_error_unknown,
3091 			"unexpected difference between set and "
3092 			"piecewise affine expression", return -1);
3093 
3094 	return 0;
3095 }
3096 
3097 /* Inputs for isl_pw_multi_aff_max_multi_val tests.
3098  * "pma" is the input.
3099  * "res" is the expected result.
3100  */
3101 static struct {
3102 	const char *pma;
3103 	const char *res;
3104 } opt_pw_tests[] = {
3105 	{ "{ [-1] -> [-1]; [1] -> [1] }", "{ [1] }" },
3106 	{ "{ [a, b] -> [floor((b - 2*floor((-a)/4))/5)] : "
3107 	    "0 <= a, b <= 100 and b mod 2 = 0}", "{ [30] }" },
3108 	{ "[N] -> { [i,j] -> A[i, -i, i + j] : 0 <= i,j <= N <= 10 }",
3109 	  "{ A[10, 0, 20] }" },
3110 	{ "[N] -> {A[N, -N, 2N] : 0 <= N }", "{ A[infty, 0, infty] }" },
3111 };
3112 
3113 /* Perform basic isl_pw_multi_aff_max_multi_val tests.
3114  */
test_pw_max(struct isl_ctx * ctx)3115 static isl_stat test_pw_max(struct isl_ctx *ctx)
3116 {
3117 	int i;
3118 	isl_pw_multi_aff *pma;
3119 	isl_multi_val *mv;
3120 	isl_stat r;
3121 
3122 	for (i = 0; i < ARRAY_SIZE(opt_pw_tests); ++i) {
3123 		pma = isl_pw_multi_aff_read_from_str(ctx, opt_pw_tests[i].pma);
3124 		mv = isl_pw_multi_aff_max_multi_val(pma);
3125 		r = multi_val_check_plain_equal(mv, opt_pw_tests[i].res);
3126 		isl_multi_val_free(mv);
3127 
3128 		if (r < 0)
3129 			return isl_stat_error;
3130 	}
3131 
3132 	return isl_stat_ok;
3133 }
3134 
3135 /* A specialized isl_set_min_val test case that would return the wrong result
3136  * in earlier versions of isl.
3137  * The explicit call to isl_basic_set_union prevents the second basic set
3138  * from being determined to be empty prior to the call to isl_set_min_val,
3139  * at least at the point where this test case was introduced.
3140  */
test_min_special(isl_ctx * ctx)3141 static int test_min_special(isl_ctx *ctx)
3142 {
3143 	const char *str;
3144 	isl_basic_set *bset1, *bset2;
3145 	isl_set *set;
3146 	isl_aff *obj;
3147 	isl_val *res;
3148 	int ok;
3149 
3150 	str = "{ [a, b] : a >= 2 and b >= 0 and 14 - a <= b <= 9 }";
3151 	bset1 = isl_basic_set_read_from_str(ctx, str);
3152 	str = "{ [a, b] : 1 <= a, b and a + b <= 1 }";
3153 	bset2 = isl_basic_set_read_from_str(ctx, str);
3154 	set = isl_basic_set_union(bset1, bset2);
3155 	obj = isl_aff_read_from_str(ctx, "{ [a, b] -> [a] }");
3156 
3157 	res = isl_set_min_val(set, obj);
3158 	ok = isl_val_cmp_si(res, 5) == 0;
3159 
3160 	isl_aff_free(obj);
3161 	isl_set_free(set);
3162 	isl_val_free(res);
3163 
3164 	if (!res)
3165 		return -1;
3166 	if (!ok)
3167 		isl_die(ctx, isl_error_unknown, "unexpected minimum",
3168 			return -1);
3169 
3170 	return 0;
3171 }
3172 
3173 /* A specialized isl_set_min_val test case that would return an error
3174  * in earlier versions of isl.
3175  */
test_min_special2(isl_ctx * ctx)3176 static int test_min_special2(isl_ctx *ctx)
3177 {
3178 	const char *str;
3179 	isl_basic_set *bset;
3180 	isl_aff *obj;
3181 	isl_val *res;
3182 
3183 	str = "{ [i, j, k] : 2j = i and 2k = i + 1 and i >= 2 }";
3184 	bset = isl_basic_set_read_from_str(ctx, str);
3185 
3186 	obj = isl_aff_read_from_str(ctx, "{ [i, j, k] -> [i] }");
3187 
3188 	res = isl_basic_set_max_val(bset, obj);
3189 
3190 	isl_basic_set_free(bset);
3191 	isl_aff_free(obj);
3192 	isl_val_free(res);
3193 
3194 	if (!res)
3195 		return -1;
3196 
3197 	return 0;
3198 }
3199 
3200 /* Check that the result of isl_set_min_multi_pw_aff
3201  * on the union of the sets with string descriptions "s1" and "s2"
3202  * consists of a single expression (on a single cell).
3203  */
check_single_expr_min(isl_ctx * ctx,const char * s1,const char * s2)3204 static isl_stat check_single_expr_min(isl_ctx *ctx, const char *s1,
3205 	const char *s2)
3206 {
3207 	isl_size n;
3208 	isl_set *set1, *set2;
3209 	isl_multi_pw_aff *mpa;
3210 	isl_pw_multi_aff *pma;
3211 
3212 	set1 = isl_set_read_from_str(ctx, s1);
3213 	set2 = isl_set_read_from_str(ctx, s2);
3214 	set1 = isl_set_union(set1, set2);
3215 	mpa = isl_set_min_multi_pw_aff(set1);
3216 	pma = isl_pw_multi_aff_from_multi_pw_aff(mpa);
3217 	n = isl_pw_multi_aff_n_piece(pma);
3218 	isl_pw_multi_aff_free(pma);
3219 
3220 	if (n < 0)
3221 		return isl_stat_error;
3222 	if (n != 1)
3223 		isl_die(ctx, isl_error_unknown, "expecting single expression",
3224 			return isl_stat_error);
3225 	return isl_stat_ok;
3226 }
3227 
3228 /* A specialized isl_set_min_multi_pw_aff test that checks
3229  * that the minimum of 2N and 3N for N >= 0 is represented
3230  * by a single expression, without splitting off the special case N = 0.
3231  * Do this for both orderings.
3232  */
test_min_mpa(isl_ctx * ctx)3233 static int test_min_mpa(isl_ctx *ctx)
3234 {
3235 	const char *s1, *s2;
3236 
3237 	s1 = "[N=0:] -> { [1, 3N:] }";
3238 	s2 = "[N=0:] -> { [10, 2N:] }";
3239 	if (check_single_expr_min(ctx, s1, s2) < 0)
3240 		return -1;
3241 	if (check_single_expr_min(ctx, s2, s1) < 0)
3242 		return -1;
3243 
3244 	return 0;
3245 }
3246 
3247 struct {
3248 	const char *set;
3249 	const char *obj;
3250 	__isl_give isl_val *(*fn)(__isl_keep isl_set *set,
3251 		__isl_keep isl_aff *obj);
3252 	const char *res;
3253 } opt_tests[] = {
3254 	{ "{ [-1]; [1] }", "{ [x] -> [x] }", &isl_set_min_val, "-1" },
3255 	{ "{ [-1]; [1] }", "{ [x] -> [x] }", &isl_set_max_val, "1" },
3256 	{ "{ [a, b] : 0 <= a, b <= 100 and b mod 2 = 0}",
3257 	  "{ [a, b] -> [floor((b - 2*floor((-a)/4))/5)] }",
3258 	  &isl_set_max_val, "30" },
3259 
3260 };
3261 
3262 /* Perform basic isl_set_min_val and isl_set_max_val tests.
3263  * In particular, check the results on non-convex inputs.
3264  */
test_min(struct isl_ctx * ctx)3265 static int test_min(struct isl_ctx *ctx)
3266 {
3267 	int i;
3268 	isl_set *set;
3269 	isl_aff *obj;
3270 	isl_val *val, *res;
3271 	isl_bool ok;
3272 
3273 	for (i = 0; i < ARRAY_SIZE(opt_tests); ++i) {
3274 		set = isl_set_read_from_str(ctx, opt_tests[i].set);
3275 		obj = isl_aff_read_from_str(ctx, opt_tests[i].obj);
3276 		res = isl_val_read_from_str(ctx, opt_tests[i].res);
3277 		val = opt_tests[i].fn(set, obj);
3278 		ok = isl_val_eq(res, val);
3279 		isl_val_free(res);
3280 		isl_val_free(val);
3281 		isl_aff_free(obj);
3282 		isl_set_free(set);
3283 
3284 		if (ok < 0)
3285 			return -1;
3286 		if (!ok)
3287 			isl_die(ctx, isl_error_unknown,
3288 				"unexpected optimum", return -1);
3289 	}
3290 
3291 	if (test_pw_max(ctx) < 0)
3292 		return -1;
3293 	if (test_min_special(ctx) < 0)
3294 		return -1;
3295 	if (test_min_special2(ctx) < 0)
3296 		return -1;
3297 
3298 	return 0;
3299 }
3300 
3301 struct must_may {
3302 	isl_map *must;
3303 	isl_map *may;
3304 };
3305 
collect_must_may(__isl_take isl_map * dep,int must,void * dep_user,void * user)3306 static isl_stat collect_must_may(__isl_take isl_map *dep, int must,
3307 	void *dep_user, void *user)
3308 {
3309 	struct must_may *mm = (struct must_may *)user;
3310 
3311 	if (must)
3312 		mm->must = isl_map_union(mm->must, dep);
3313 	else
3314 		mm->may = isl_map_union(mm->may, dep);
3315 
3316 	return isl_stat_ok;
3317 }
3318 
common_space(void * first,void * second)3319 static int common_space(void *first, void *second)
3320 {
3321 	int depth = *(int *)first;
3322 	return 2 * depth;
3323 }
3324 
map_is_equal(__isl_keep isl_map * map,const char * str)3325 static int map_is_equal(__isl_keep isl_map *map, const char *str)
3326 {
3327 	isl_map *map2;
3328 	int equal;
3329 
3330 	if (!map)
3331 		return -1;
3332 
3333 	map2 = isl_map_read_from_str(map->ctx, str);
3334 	equal = isl_map_is_equal(map, map2);
3335 	isl_map_free(map2);
3336 
3337 	return equal;
3338 }
3339 
map_check_equal(__isl_keep isl_map * map,const char * str)3340 static int map_check_equal(__isl_keep isl_map *map, const char *str)
3341 {
3342 	int equal;
3343 
3344 	equal = map_is_equal(map, str);
3345 	if (equal < 0)
3346 		return -1;
3347 	if (!equal)
3348 		isl_die(isl_map_get_ctx(map), isl_error_unknown,
3349 			"result not as expected", return -1);
3350 	return 0;
3351 }
3352 
3353 /* Is "set" equal to the set described by "str"?
3354  */
set_is_equal(__isl_keep isl_set * set,const char * str)3355 static isl_bool set_is_equal(__isl_keep isl_set *set, const char *str)
3356 {
3357 	isl_set *set2;
3358 	isl_bool equal;
3359 
3360 	if (!set)
3361 		return isl_bool_error;
3362 
3363 	set2 = isl_set_read_from_str(isl_set_get_ctx(set), str);
3364 	equal = isl_set_is_equal(set, set2);
3365 	isl_set_free(set2);
3366 
3367 	return equal;
3368 }
3369 
3370 /* Check that "set" is equal to the set described by "str".
3371  */
set_check_equal(__isl_keep isl_set * set,const char * str)3372 static isl_stat set_check_equal(__isl_keep isl_set *set, const char *str)
3373 {
3374 	isl_bool equal;
3375 
3376 	equal = set_is_equal(set, str);
3377 	if (equal < 0)
3378 		return isl_stat_error;
3379 	if (!equal)
3380 		isl_die(isl_set_get_ctx(set), isl_error_unknown,
3381 			"result not as expected", return isl_stat_error);
3382 	return isl_stat_ok;
3383 }
3384 
3385 /* Is "uset" equal to the union set described by "str"?
3386  */
uset_is_equal(__isl_keep isl_union_set * uset,const char * str)3387 static isl_bool uset_is_equal(__isl_keep isl_union_set *uset, const char *str)
3388 {
3389 	isl_union_set *uset2;
3390 	isl_bool equal;
3391 
3392 	if (!uset)
3393 		return isl_bool_error;
3394 
3395 	uset2 = isl_union_set_read_from_str(isl_union_set_get_ctx(uset), str);
3396 	equal = isl_union_set_is_equal(uset, uset2);
3397 	isl_union_set_free(uset2);
3398 
3399 	return equal;
3400 }
3401 
3402 /* Check that "uset" is equal to the union set described by "str".
3403  */
uset_check_equal(__isl_keep isl_union_set * uset,const char * str)3404 static isl_stat uset_check_equal(__isl_keep isl_union_set *uset,
3405 	const char *str)
3406 {
3407 	isl_bool equal;
3408 
3409 	equal = uset_is_equal(uset, str);
3410 	if (equal < 0)
3411 		return isl_stat_error;
3412 	if (!equal)
3413 		isl_die(isl_union_set_get_ctx(uset), isl_error_unknown,
3414 			"result not as expected", return isl_stat_error);
3415 	return isl_stat_ok;
3416 }
3417 
test_dep(struct isl_ctx * ctx)3418 static int test_dep(struct isl_ctx *ctx)
3419 {
3420 	const char *str;
3421 	isl_space *space;
3422 	isl_map *map;
3423 	isl_access_info *ai;
3424 	isl_flow *flow;
3425 	int depth;
3426 	struct must_may mm;
3427 
3428 	depth = 3;
3429 
3430 	str = "{ [2,i,0] -> [i] : 0 <= i <= 10 }";
3431 	map = isl_map_read_from_str(ctx, str);
3432 	ai = isl_access_info_alloc(map, &depth, &common_space, 2);
3433 
3434 	str = "{ [0,i,0] -> [i] : 0 <= i <= 10 }";
3435 	map = isl_map_read_from_str(ctx, str);
3436 	ai = isl_access_info_add_source(ai, map, 1, &depth);
3437 
3438 	str = "{ [1,i,0] -> [5] : 0 <= i <= 10 }";
3439 	map = isl_map_read_from_str(ctx, str);
3440 	ai = isl_access_info_add_source(ai, map, 1, &depth);
3441 
3442 	flow = isl_access_info_compute_flow(ai);
3443 	space = isl_space_alloc(ctx, 0, 3, 3);
3444 	mm.must = isl_map_empty(isl_space_copy(space));
3445 	mm.may = isl_map_empty(space);
3446 
3447 	isl_flow_foreach(flow, collect_must_may, &mm);
3448 
3449 	str = "{ [0,i,0] -> [2,i,0] : (0 <= i <= 4) or (6 <= i <= 10); "
3450 	      "  [1,10,0] -> [2,5,0] }";
3451 	assert(map_is_equal(mm.must, str));
3452 	str = "{ [i,j,k] -> [l,m,n] : 1 = 0 }";
3453 	assert(map_is_equal(mm.may, str));
3454 
3455 	isl_map_free(mm.must);
3456 	isl_map_free(mm.may);
3457 	isl_flow_free(flow);
3458 
3459 
3460 	str = "{ [2,i,0] -> [i] : 0 <= i <= 10 }";
3461 	map = isl_map_read_from_str(ctx, str);
3462 	ai = isl_access_info_alloc(map, &depth, &common_space, 2);
3463 
3464 	str = "{ [0,i,0] -> [i] : 0 <= i <= 10 }";
3465 	map = isl_map_read_from_str(ctx, str);
3466 	ai = isl_access_info_add_source(ai, map, 1, &depth);
3467 
3468 	str = "{ [1,i,0] -> [5] : 0 <= i <= 10 }";
3469 	map = isl_map_read_from_str(ctx, str);
3470 	ai = isl_access_info_add_source(ai, map, 0, &depth);
3471 
3472 	flow = isl_access_info_compute_flow(ai);
3473 	space = isl_space_alloc(ctx, 0, 3, 3);
3474 	mm.must = isl_map_empty(isl_space_copy(space));
3475 	mm.may = isl_map_empty(space);
3476 
3477 	isl_flow_foreach(flow, collect_must_may, &mm);
3478 
3479 	str = "{ [0,i,0] -> [2,i,0] : (0 <= i <= 4) or (6 <= i <= 10) }";
3480 	assert(map_is_equal(mm.must, str));
3481 	str = "{ [0,5,0] -> [2,5,0]; [1,i,0] -> [2,5,0] : 0 <= i <= 10 }";
3482 	assert(map_is_equal(mm.may, str));
3483 
3484 	isl_map_free(mm.must);
3485 	isl_map_free(mm.may);
3486 	isl_flow_free(flow);
3487 
3488 
3489 	str = "{ [2,i,0] -> [i] : 0 <= i <= 10 }";
3490 	map = isl_map_read_from_str(ctx, str);
3491 	ai = isl_access_info_alloc(map, &depth, &common_space, 2);
3492 
3493 	str = "{ [0,i,0] -> [i] : 0 <= i <= 10 }";
3494 	map = isl_map_read_from_str(ctx, str);
3495 	ai = isl_access_info_add_source(ai, map, 0, &depth);
3496 
3497 	str = "{ [1,i,0] -> [5] : 0 <= i <= 10 }";
3498 	map = isl_map_read_from_str(ctx, str);
3499 	ai = isl_access_info_add_source(ai, map, 0, &depth);
3500 
3501 	flow = isl_access_info_compute_flow(ai);
3502 	space = isl_space_alloc(ctx, 0, 3, 3);
3503 	mm.must = isl_map_empty(isl_space_copy(space));
3504 	mm.may = isl_map_empty(space);
3505 
3506 	isl_flow_foreach(flow, collect_must_may, &mm);
3507 
3508 	str = "{ [0,i,0] -> [2,i,0] : 0 <= i <= 10; "
3509 	      "  [1,i,0] -> [2,5,0] : 0 <= i <= 10 }";
3510 	assert(map_is_equal(mm.may, str));
3511 	str = "{ [i,j,k] -> [l,m,n] : 1 = 0 }";
3512 	assert(map_is_equal(mm.must, str));
3513 
3514 	isl_map_free(mm.must);
3515 	isl_map_free(mm.may);
3516 	isl_flow_free(flow);
3517 
3518 
3519 	str = "{ [0,i,2] -> [i] : 0 <= i <= 10 }";
3520 	map = isl_map_read_from_str(ctx, str);
3521 	ai = isl_access_info_alloc(map, &depth, &common_space, 2);
3522 
3523 	str = "{ [0,i,0] -> [i] : 0 <= i <= 10 }";
3524 	map = isl_map_read_from_str(ctx, str);
3525 	ai = isl_access_info_add_source(ai, map, 0, &depth);
3526 
3527 	str = "{ [0,i,1] -> [5] : 0 <= i <= 10 }";
3528 	map = isl_map_read_from_str(ctx, str);
3529 	ai = isl_access_info_add_source(ai, map, 0, &depth);
3530 
3531 	flow = isl_access_info_compute_flow(ai);
3532 	space = isl_space_alloc(ctx, 0, 3, 3);
3533 	mm.must = isl_map_empty(isl_space_copy(space));
3534 	mm.may = isl_map_empty(space);
3535 
3536 	isl_flow_foreach(flow, collect_must_may, &mm);
3537 
3538 	str = "{ [0,i,0] -> [0,i,2] : 0 <= i <= 10; "
3539 	      "  [0,i,1] -> [0,5,2] : 0 <= i <= 5 }";
3540 	assert(map_is_equal(mm.may, str));
3541 	str = "{ [i,j,k] -> [l,m,n] : 1 = 0 }";
3542 	assert(map_is_equal(mm.must, str));
3543 
3544 	isl_map_free(mm.must);
3545 	isl_map_free(mm.may);
3546 	isl_flow_free(flow);
3547 
3548 
3549 	str = "{ [0,i,1] -> [i] : 0 <= i <= 10 }";
3550 	map = isl_map_read_from_str(ctx, str);
3551 	ai = isl_access_info_alloc(map, &depth, &common_space, 2);
3552 
3553 	str = "{ [0,i,0] -> [i] : 0 <= i <= 10 }";
3554 	map = isl_map_read_from_str(ctx, str);
3555 	ai = isl_access_info_add_source(ai, map, 0, &depth);
3556 
3557 	str = "{ [0,i,2] -> [5] : 0 <= i <= 10 }";
3558 	map = isl_map_read_from_str(ctx, str);
3559 	ai = isl_access_info_add_source(ai, map, 0, &depth);
3560 
3561 	flow = isl_access_info_compute_flow(ai);
3562 	space = isl_space_alloc(ctx, 0, 3, 3);
3563 	mm.must = isl_map_empty(isl_space_copy(space));
3564 	mm.may = isl_map_empty(space);
3565 
3566 	isl_flow_foreach(flow, collect_must_may, &mm);
3567 
3568 	str = "{ [0,i,0] -> [0,i,1] : 0 <= i <= 10; "
3569 	      "  [0,i,2] -> [0,5,1] : 0 <= i <= 4 }";
3570 	assert(map_is_equal(mm.may, str));
3571 	str = "{ [i,j,k] -> [l,m,n] : 1 = 0 }";
3572 	assert(map_is_equal(mm.must, str));
3573 
3574 	isl_map_free(mm.must);
3575 	isl_map_free(mm.may);
3576 	isl_flow_free(flow);
3577 
3578 
3579 	depth = 5;
3580 
3581 	str = "{ [1,i,0,0,0] -> [i,j] : 0 <= i <= 10 and 0 <= j <= 10 }";
3582 	map = isl_map_read_from_str(ctx, str);
3583 	ai = isl_access_info_alloc(map, &depth, &common_space, 1);
3584 
3585 	str = "{ [0,i,0,j,0] -> [i,j] : 0 <= i <= 10 and 0 <= j <= 10 }";
3586 	map = isl_map_read_from_str(ctx, str);
3587 	ai = isl_access_info_add_source(ai, map, 1, &depth);
3588 
3589 	flow = isl_access_info_compute_flow(ai);
3590 	space = isl_space_alloc(ctx, 0, 5, 5);
3591 	mm.must = isl_map_empty(isl_space_copy(space));
3592 	mm.may = isl_map_empty(space);
3593 
3594 	isl_flow_foreach(flow, collect_must_may, &mm);
3595 
3596 	str = "{ [0,i,0,j,0] -> [1,i,0,0,0] : 0 <= i,j <= 10 }";
3597 	assert(map_is_equal(mm.must, str));
3598 	str = "{ [0,0,0,0,0] -> [0,0,0,0,0] : 1 = 0 }";
3599 	assert(map_is_equal(mm.may, str));
3600 
3601 	isl_map_free(mm.must);
3602 	isl_map_free(mm.may);
3603 	isl_flow_free(flow);
3604 
3605 	return 0;
3606 }
3607 
3608 /* Check that the dependence analysis proceeds without errors.
3609  * Earlier versions of isl would break down during the analysis
3610  * due to the use of the wrong spaces.
3611  */
test_flow(isl_ctx * ctx)3612 static int test_flow(isl_ctx *ctx)
3613 {
3614 	const char *str;
3615 	isl_union_map *access, *schedule;
3616 	isl_union_map *must_dep, *may_dep;
3617 	int r;
3618 
3619 	str = "{ S0[j] -> i[]; S1[j,i] -> i[]; S2[] -> i[]; S3[] -> i[] }";
3620 	access = isl_union_map_read_from_str(ctx, str);
3621 	str = "{ S0[j] -> [0,j,0,0] : 0 <= j < 10; "
3622 		"S1[j,i] -> [0,j,1,i] : 0 <= j < i < 10; "
3623 		"S2[] -> [1,0,0,0]; "
3624 		"S3[] -> [-1,0,0,0] }";
3625 	schedule = isl_union_map_read_from_str(ctx, str);
3626 	r = isl_union_map_compute_flow(access, isl_union_map_copy(access),
3627 					isl_union_map_copy(access), schedule,
3628 					&must_dep, &may_dep, NULL, NULL);
3629 	isl_union_map_free(may_dep);
3630 	isl_union_map_free(must_dep);
3631 
3632 	return r;
3633 }
3634 
3635 struct {
3636 	const char *map;
3637 	int sv;
3638 } sv_tests[] = {
3639 	{ "[N] -> { [i] -> [f] : 0 <= i <= N and 0 <= i - 10 f <= 9 }", 1 },
3640 	{ "[N] -> { [i] -> [f] : 0 <= i <= N and 0 <= i - 10 f <= 10 }", 0 },
3641 	{ "{ [i] -> [3*floor(i/2) + 5*floor(i/3)] }", 1 },
3642 	{ "{ S1[i] -> [i] : 0 <= i <= 9; S2[i] -> [i] : 0 <= i <= 9 }", 1 },
3643 	{ "{ [i] -> S1[i] : 0 <= i <= 9; [i] -> S2[i] : 0 <= i <= 9 }", 0 },
3644 	{ "{ A[i] -> [i]; B[i] -> [i]; B[i] -> [i + 1] }", 0 },
3645 	{ "{ A[i] -> [i]; B[i] -> [i] : i < 0; B[i] -> [i + 1] : i > 0 }", 1 },
3646 	{ "{ A[i] -> [i]; B[i] -> A[i] : i < 0; B[i] -> [i + 1] : i > 0 }", 1 },
3647 	{ "{ A[i] -> [i]; B[i] -> [j] : i - 1 <= j <= i }", 0 },
3648 };
3649 
test_sv(isl_ctx * ctx)3650 int test_sv(isl_ctx *ctx)
3651 {
3652 	isl_union_map *umap;
3653 	int i;
3654 	int sv;
3655 
3656 	for (i = 0; i < ARRAY_SIZE(sv_tests); ++i) {
3657 		umap = isl_union_map_read_from_str(ctx, sv_tests[i].map);
3658 		sv = isl_union_map_is_single_valued(umap);
3659 		isl_union_map_free(umap);
3660 		if (sv < 0)
3661 			return -1;
3662 		if (sv_tests[i].sv && !sv)
3663 			isl_die(ctx, isl_error_internal,
3664 				"map not detected as single valued", return -1);
3665 		if (!sv_tests[i].sv && sv)
3666 			isl_die(ctx, isl_error_internal,
3667 				"map detected as single valued", return -1);
3668 	}
3669 
3670 	return 0;
3671 }
3672 
3673 struct {
3674 	const char *str;
3675 	int bijective;
3676 } bijective_tests[] = {
3677 	{ "[N,M]->{[i,j] -> [i]}", 0 },
3678 	{ "[N,M]->{[i,j] -> [i] : j=i}", 1 },
3679 	{ "[N,M]->{[i,j] -> [i] : j=0}", 1 },
3680 	{ "[N,M]->{[i,j] -> [i] : j=N}", 1 },
3681 	{ "[N,M]->{[i,j] -> [j,i]}", 1 },
3682 	{ "[N,M]->{[i,j] -> [i+j]}", 0 },
3683 	{ "[N,M]->{[i,j] -> []}", 0 },
3684 	{ "[N,M]->{[i,j] -> [i,j,N]}", 1 },
3685 	{ "[N,M]->{[i,j] -> [2i]}", 0 },
3686 	{ "[N,M]->{[i,j] -> [i,i]}", 0 },
3687 	{ "[N,M]->{[i,j] -> [2i,i]}", 0 },
3688 	{ "[N,M]->{[i,j] -> [2i,j]}", 1 },
3689 	{ "[N,M]->{[i,j] -> [x,y] : 2x=i & y =j}", 1 },
3690 };
3691 
test_bijective(struct isl_ctx * ctx)3692 static int test_bijective(struct isl_ctx *ctx)
3693 {
3694 	isl_map *map;
3695 	int i;
3696 	int bijective;
3697 
3698 	for (i = 0; i < ARRAY_SIZE(bijective_tests); ++i) {
3699 		map = isl_map_read_from_str(ctx, bijective_tests[i].str);
3700 		bijective = isl_map_is_bijective(map);
3701 		isl_map_free(map);
3702 		if (bijective < 0)
3703 			return -1;
3704 		if (bijective_tests[i].bijective && !bijective)
3705 			isl_die(ctx, isl_error_internal,
3706 				"map not detected as bijective", return -1);
3707 		if (!bijective_tests[i].bijective && bijective)
3708 			isl_die(ctx, isl_error_internal,
3709 				"map detected as bijective", return -1);
3710 	}
3711 
3712 	return 0;
3713 }
3714 
3715 /* Inputs for isl_pw_qpolynomial_gist tests.
3716  * "pwqp" is the input, "set" is the context and "gist" is the expected result.
3717  */
3718 struct {
3719 	const char *pwqp;
3720 	const char *set;
3721 	const char *gist;
3722 } pwqp_gist_tests[] = {
3723 	{ "{ [i] -> i }", "{ [k] : exists a : k = 2a }", "{ [i] -> i }" },
3724 	{ "{ [i] -> i + [ (i + [i/3])/2 ] }", "{ [10] }", "{ [i] -> 16 }" },
3725 	{ "{ [i] -> ([(i)/2]) }", "{ [k] : exists a : k = 2a+1 }",
3726 	  "{ [i] -> -1/2 + 1/2 * i }" },
3727 	{ "{ [i] -> i^2 : i != 0 }", "{ [i] : i != 0 }", "{ [i] -> i^2 }" },
3728 };
3729 
3730 /* Perform some basic isl_pw_qpolynomial_gist tests.
3731  */
test_pwqp_gist(isl_ctx * ctx)3732 static isl_stat test_pwqp_gist(isl_ctx *ctx)
3733 {
3734 	int i;
3735 	const char *str;
3736 	isl_set *set;
3737 	isl_pw_qpolynomial *pwqp1, *pwqp2;
3738 	isl_bool equal;
3739 
3740 	for (i = 0; i < ARRAY_SIZE(pwqp_gist_tests); ++i) {
3741 		str = pwqp_gist_tests[i].pwqp;
3742 		pwqp1 = isl_pw_qpolynomial_read_from_str(ctx, str);
3743 		str = pwqp_gist_tests[i].set;
3744 		set = isl_set_read_from_str(ctx, str);
3745 		pwqp1 = isl_pw_qpolynomial_gist(pwqp1, set);
3746 		str = pwqp_gist_tests[i].gist;
3747 		pwqp2 = isl_pw_qpolynomial_read_from_str(ctx, str);
3748 		pwqp1 = isl_pw_qpolynomial_sub(pwqp1, pwqp2);
3749 		equal = isl_pw_qpolynomial_is_zero(pwqp1);
3750 		isl_pw_qpolynomial_free(pwqp1);
3751 
3752 		if (equal < 0)
3753 			return isl_stat_error;
3754 		if (!equal)
3755 			isl_die(ctx, isl_error_unknown,
3756 				"unexpected result", return isl_stat_error);
3757 	}
3758 
3759 	return isl_stat_ok;
3760 }
3761 
3762 /* Perform a basic isl_pw_qpolynomial_max test.
3763  */
test_pwqp_max(isl_ctx * ctx)3764 static isl_stat test_pwqp_max(isl_ctx *ctx)
3765 {
3766 	const char *str;
3767 	isl_pw_qpolynomial *pwqp;
3768 	isl_val *v;
3769 	int ok;
3770 
3771 	str = "{ [x=2:9, y] -> floor((x + 1)/4)^3 - floor((2x)/3)^2 }";
3772 	pwqp = isl_pw_qpolynomial_read_from_str(ctx, str);
3773 	v = isl_pw_qpolynomial_max(pwqp);
3774 	ok = isl_val_cmp_si(v, -1) == 0;
3775 	isl_val_free(v);
3776 
3777 	if (!v)
3778 		return isl_stat_error;
3779 	if (!ok)
3780 		isl_die(ctx, isl_error_unknown, "unexpected maximum",
3781 			return isl_stat_error);
3782 
3783 	return isl_stat_ok;
3784 }
3785 
test_pwqp(struct isl_ctx * ctx)3786 static int test_pwqp(struct isl_ctx *ctx)
3787 {
3788 	const char *str;
3789 	isl_set *set;
3790 	isl_pw_qpolynomial *pwqp1, *pwqp2;
3791 	int equal;
3792 
3793 	str = "{ [i,j,k] -> 1 + 9 * [i/5] + 7 * [j/11] + 4 * [k/13] }";
3794 	pwqp1 = isl_pw_qpolynomial_read_from_str(ctx, str);
3795 
3796 	pwqp1 = isl_pw_qpolynomial_move_dims(pwqp1, isl_dim_param, 0,
3797 						isl_dim_in, 1, 1);
3798 
3799 	str = "[j] -> { [i,k] -> 1 + 9 * [i/5] + 7 * [j/11] + 4 * [k/13] }";
3800 	pwqp2 = isl_pw_qpolynomial_read_from_str(ctx, str);
3801 
3802 	pwqp1 = isl_pw_qpolynomial_sub(pwqp1, pwqp2);
3803 
3804 	assert(isl_pw_qpolynomial_is_zero(pwqp1));
3805 
3806 	isl_pw_qpolynomial_free(pwqp1);
3807 
3808 	if (test_pwqp_gist(ctx) < 0)
3809 		return -1;
3810 
3811 	str = "{ [i] -> ([([i/2] + [i/2])/5]) }";
3812 	pwqp1 = isl_pw_qpolynomial_read_from_str(ctx, str);
3813 	str = "{ [i] -> ([(2 * [i/2])/5]) }";
3814 	pwqp2 = isl_pw_qpolynomial_read_from_str(ctx, str);
3815 
3816 	pwqp1 = isl_pw_qpolynomial_sub(pwqp1, pwqp2);
3817 
3818 	assert(isl_pw_qpolynomial_is_zero(pwqp1));
3819 
3820 	isl_pw_qpolynomial_free(pwqp1);
3821 
3822 	str = "{ [x] -> ([x/2] + [(x+1)/2]) }";
3823 	pwqp1 = isl_pw_qpolynomial_read_from_str(ctx, str);
3824 	str = "{ [x] -> x }";
3825 	pwqp2 = isl_pw_qpolynomial_read_from_str(ctx, str);
3826 
3827 	pwqp1 = isl_pw_qpolynomial_sub(pwqp1, pwqp2);
3828 
3829 	assert(isl_pw_qpolynomial_is_zero(pwqp1));
3830 
3831 	isl_pw_qpolynomial_free(pwqp1);
3832 
3833 	str = "{ [i] -> ([i/2]) : i >= 0; [i] -> ([i/3]) : i < 0 }";
3834 	pwqp1 = isl_pw_qpolynomial_read_from_str(ctx, str);
3835 	pwqp2 = isl_pw_qpolynomial_read_from_str(ctx, str);
3836 	pwqp1 = isl_pw_qpolynomial_coalesce(pwqp1);
3837 	pwqp1 = isl_pw_qpolynomial_sub(pwqp1, pwqp2);
3838 	assert(isl_pw_qpolynomial_is_zero(pwqp1));
3839 	isl_pw_qpolynomial_free(pwqp1);
3840 
3841 	str = "{ [a,b,a] -> (([(2*[a/3]+b)/5]) * ([(2*[a/3]+b)/5])) }";
3842 	pwqp2 = isl_pw_qpolynomial_read_from_str(ctx, str);
3843 	str = "{ [a,b,c] -> (([(2*[a/3]+b)/5]) * ([(2*[c/3]+b)/5])) }";
3844 	pwqp1 = isl_pw_qpolynomial_read_from_str(ctx, str);
3845 	set = isl_set_read_from_str(ctx, "{ [a,b,a] }");
3846 	pwqp1 = isl_pw_qpolynomial_intersect_domain(pwqp1, set);
3847 	equal = isl_pw_qpolynomial_plain_is_equal(pwqp1, pwqp2);
3848 	isl_pw_qpolynomial_free(pwqp1);
3849 	isl_pw_qpolynomial_free(pwqp2);
3850 	if (equal < 0)
3851 		return -1;
3852 	if (!equal)
3853 		isl_die(ctx, isl_error_unknown, "unexpected result", return -1);
3854 
3855 	str = "{ [a,b,c] -> (([(2*[a/3]+1)/5]) * ([(2*[c/3]+1)/5])) : b = 1 }";
3856 	pwqp2 = isl_pw_qpolynomial_read_from_str(ctx, str);
3857 	str = "{ [a,b,c] -> (([(2*[a/3]+b)/5]) * ([(2*[c/3]+b)/5])) }";
3858 	pwqp1 = isl_pw_qpolynomial_read_from_str(ctx, str);
3859 	pwqp1 = isl_pw_qpolynomial_fix_val(pwqp1, isl_dim_set, 1,
3860 						isl_val_one(ctx));
3861 	equal = isl_pw_qpolynomial_plain_is_equal(pwqp1, pwqp2);
3862 	isl_pw_qpolynomial_free(pwqp1);
3863 	isl_pw_qpolynomial_free(pwqp2);
3864 	if (equal < 0)
3865 		return -1;
3866 	if (!equal)
3867 		isl_die(ctx, isl_error_unknown, "unexpected result", return -1);
3868 
3869 	if (test_pwqp_max(ctx) < 0)
3870 		return -1;
3871 
3872 	return 0;
3873 }
3874 
test_split_periods(isl_ctx * ctx)3875 static int test_split_periods(isl_ctx *ctx)
3876 {
3877 	const char *str;
3878 	isl_pw_qpolynomial *pwqp;
3879 
3880 	str = "{ [U,V] -> 1/3 * U + 2/3 * V - [(U + 2V)/3] + [U/2] : "
3881 		"U + 2V + 3 >= 0 and - U -2V  >= 0 and - U + 10 >= 0 and "
3882 		"U  >= 0; [U,V] -> U^2 : U >= 100 }";
3883 	pwqp = isl_pw_qpolynomial_read_from_str(ctx, str);
3884 
3885 	pwqp = isl_pw_qpolynomial_split_periods(pwqp, 2);
3886 
3887 	isl_pw_qpolynomial_free(pwqp);
3888 
3889 	if (!pwqp)
3890 		return -1;
3891 
3892 	return 0;
3893 }
3894 
test_union(isl_ctx * ctx)3895 static int test_union(isl_ctx *ctx)
3896 {
3897 	const char *str;
3898 	isl_union_set *uset1, *uset2;
3899 	isl_union_map *umap1, *umap2;
3900 	int equal;
3901 
3902 	str = "{ [i] : 0 <= i <= 1 }";
3903 	uset1 = isl_union_set_read_from_str(ctx, str);
3904 	str = "{ [1] -> [0] }";
3905 	umap1 = isl_union_map_read_from_str(ctx, str);
3906 
3907 	umap2 = isl_union_set_lex_gt_union_set(isl_union_set_copy(uset1), uset1);
3908 	equal = isl_union_map_is_equal(umap1, umap2);
3909 
3910 	isl_union_map_free(umap1);
3911 	isl_union_map_free(umap2);
3912 
3913 	if (equal < 0)
3914 		return -1;
3915 	if (!equal)
3916 		isl_die(ctx, isl_error_unknown, "union maps not equal",
3917 			return -1);
3918 
3919 	str = "{ A[i] -> B[i]; B[i] -> C[i]; A[0] -> C[1] }";
3920 	umap1 = isl_union_map_read_from_str(ctx, str);
3921 	str = "{ A[i]; B[i] }";
3922 	uset1 = isl_union_set_read_from_str(ctx, str);
3923 
3924 	uset2 = isl_union_map_domain(umap1);
3925 
3926 	equal = isl_union_set_is_equal(uset1, uset2);
3927 
3928 	isl_union_set_free(uset1);
3929 	isl_union_set_free(uset2);
3930 
3931 	if (equal < 0)
3932 		return -1;
3933 	if (!equal)
3934 		isl_die(ctx, isl_error_unknown, "union sets not equal",
3935 			return -1);
3936 
3937 	return 0;
3938 }
3939 
3940 /* Inputs for basic isl_pw_qpolynomial_bound tests.
3941  * "type" is the type of bound that should be computed.
3942  * "poly" is a string representation of the input.
3943  * "bound" is a string representation of the expected result.
3944  * "tight" is set if the result is expected to be tight.
3945  */
3946 static struct {
3947 	int tight;
3948 	enum isl_fold type;
3949 	const char *poly;
3950 	const char *bound;
3951 } bound_tests[] = {
3952 	/* Check that computing a bound of a non-zero polynomial
3953 	 * over an unbounded domain does not produce a rational value.
3954 	 * In particular, check that the upper bound is infinity.
3955 	 */
3956 	{ 0, isl_fold_max, "{ [m, n] -> -m * n }", "{ max(infty) }" },
3957 	{ 1, isl_fold_max, "{ [[a, b, c, d] -> [e]] -> 0 }",
3958 	  "{ [a, b, c, d] -> max(0) }" },
3959 	{ 1, isl_fold_max, "{ [[x] -> [x]] -> 1 : exists a : x = 2 a }",
3960 	  "{ [x] -> max(1) : x mod 2 = 0 }" },
3961 	{ 1, isl_fold_min, "{ [x=5:10] -> (x + 2)^2 }", "{ min(49) }" },
3962 	{ 1, isl_fold_max, "{ [0:10] -> 1 }", "{ max(1) }" },
3963 	{ 1, isl_fold_max, "{ [[m] -> [0:m]] -> m^2 }",
3964 	  "{ [m] -> max(m^2) : m >= 0 }" },
3965 };
3966 
3967 /* Check that the bound computation can handle differences
3968  * in domain dimension names of the input polynomial and its domain.
3969  */
test_bound_space(isl_ctx * ctx)3970 static isl_stat test_bound_space(isl_ctx *ctx)
3971 {
3972 	const char *str;
3973 	isl_set *set;
3974 	isl_pw_qpolynomial *pwqp;
3975 	isl_pw_qpolynomial_fold *pwf;
3976 
3977 	str = "{ [[c] -> [c]] }";
3978 	set = isl_set_read_from_str(ctx, str);
3979 	str = "{ [[a] -> [b]] -> 1 }";
3980 	pwqp = isl_pw_qpolynomial_read_from_str(ctx, str);
3981 	pwqp = isl_pw_qpolynomial_intersect_domain(pwqp, set);
3982 	pwf = isl_pw_qpolynomial_bound(pwqp, isl_fold_max, NULL);
3983 	isl_pw_qpolynomial_fold_free(pwf);
3984 
3985 	return isl_stat_non_null(pwf);
3986 }
3987 
3988 /* Perform basic isl_pw_qpolynomial_bound tests.
3989  */
test_bound(isl_ctx * ctx)3990 static int test_bound(isl_ctx *ctx)
3991 {
3992 	int i;
3993 
3994 	if (test_bound_space(ctx) < 0)
3995 		return -1;
3996 
3997 	for (i = 0; i < ARRAY_SIZE(bound_tests); ++i) {
3998 		const char *str;
3999 		enum isl_fold type;
4000 		isl_bool equal, tight;
4001 		isl_pw_qpolynomial *pwqp;
4002 		isl_pw_qpolynomial_fold *pwf1, *pwf2;
4003 
4004 		str = bound_tests[i].poly;
4005 		pwqp = isl_pw_qpolynomial_read_from_str(ctx, str);
4006 		type = bound_tests[i].type;
4007 		pwf1 = isl_pw_qpolynomial_bound(pwqp, type, &tight);
4008 		str = bound_tests[i].bound;
4009 		pwf2 = isl_pw_qpolynomial_fold_read_from_str(ctx, str);
4010 		equal = isl_pw_qpolynomial_fold_plain_is_equal(pwf1, pwf2);
4011 		isl_pw_qpolynomial_fold_free(pwf2);
4012 		isl_pw_qpolynomial_fold_free(pwf1);
4013 		if (equal < 0)
4014 			return -1;
4015 		if (!equal)
4016 			isl_die(ctx, isl_error_unknown,
4017 				"incorrect bound result", return -1);
4018 		if (bound_tests[i].tight && !tight)
4019 			isl_die(ctx, isl_error_unknown,
4020 				"bound unexpectedly not tight", return -1);
4021 	}
4022 
4023 	return 0;
4024 }
4025 
4026 /* isl_set is defined to isl_map internally, so the corresponding elements
4027  * are isl_basic_map objects.
4028  */
4029 #undef EL_BASE
4030 #undef SET_BASE
4031 #define EL_BASE		basic_map
4032 #define SET_BASE	set
4033 #include "isl_test_list_templ.c"
4034 
4035 #undef EL_BASE
4036 #undef SET_BASE
4037 #define EL_BASE		basic_set
4038 #define SET_BASE	union_set
4039 #include "isl_test_list_templ.c"
4040 
4041 #undef EL_BASE
4042 #undef SET_BASE
4043 #define EL_BASE		set
4044 #define SET_BASE	union_set
4045 #include "isl_test_list_templ.c"
4046 
4047 #undef EL_BASE
4048 #undef SET_BASE
4049 #define EL_BASE		basic_map
4050 #define SET_BASE	map
4051 #include "isl_test_list_templ.c"
4052 
4053 #undef EL_BASE
4054 #undef SET_BASE
4055 #define EL_BASE		map
4056 #define SET_BASE	union_map
4057 #include "isl_test_list_templ.c"
4058 
4059 /* Check that the conversion from isl objects to lists works as expected.
4060  */
test_get_list(isl_ctx * ctx)4061 static int test_get_list(isl_ctx *ctx)
4062 {
4063 	if (test_get_list_basic_map_from_set(ctx, "{ [0]; [2]; [3] }"))
4064 		return -1;
4065 	if (test_get_list_basic_set_from_union_set(ctx, "{ A[0]; B[2]; B[3] }"))
4066 		return -1;
4067 	if (test_get_list_set_from_union_set(ctx, "{ A[0]; A[2]; B[3] }"))
4068 		return -1;
4069 	if (test_get_list_basic_map_from_map(ctx,
4070 				"{ [0] -> [0]; [2] -> [0]; [3] -> [0] }"))
4071 		return -1;
4072 	if (test_get_list_map_from_union_map(ctx,
4073 				"{ A[0] -> [0]; A[2] -> [0]; B[3] -> [0] }"))
4074 		return -1;
4075 
4076 	return 0;
4077 }
4078 
test_lift(isl_ctx * ctx)4079 static int test_lift(isl_ctx *ctx)
4080 {
4081 	const char *str;
4082 	isl_basic_map *bmap;
4083 	isl_basic_set *bset;
4084 
4085 	str = "{ [i0] : exists e0 : i0 = 4e0 }";
4086 	bset = isl_basic_set_read_from_str(ctx, str);
4087 	bset = isl_basic_set_lift(bset);
4088 	bmap = isl_basic_map_from_range(bset);
4089 	bset = isl_basic_map_domain(bmap);
4090 	isl_basic_set_free(bset);
4091 
4092 	return 0;
4093 }
4094 
4095 /* Check that isl_set_is_subset is not confused by identical
4096  * integer divisions.
4097  * The call to isl_set_normalize ensures that the equality constraints
4098  * a = b = 0 are discovered, turning e0 and e1 into identical
4099  * integer divisions.  Any further simplification would remove
4100  * the duplicate integer divisions.
4101  */
test_subset_duplicate_integer_divisions(isl_ctx * ctx)4102 static isl_stat test_subset_duplicate_integer_divisions(isl_ctx *ctx)
4103 {
4104 	const char *str;
4105 	isl_bool is_subset;
4106 	isl_set *set1, *set2;
4107 
4108 	str = "{ [a, b, c, d] : "
4109 	    "exists (e0 = floor((a + d)/4), e1 = floor((d)/4), "
4110 		    "e2 = floor((-a - d + 4 *floor((a + d)/4))/10), "
4111 		    "e3 = floor((-d + 4*floor((d)/4))/10): "
4112 		"10e2 = -a - 2c - d + 4e0 and 10e3 = -2c - d + 4e1 and "
4113 		"b >= 0 and a <= 0 and b <= a) }";
4114 	set1 = isl_set_read_from_str(ctx, str);
4115 	set2 = isl_set_read_from_str(ctx, str);
4116 	set2 = isl_set_normalize(set2);
4117 
4118 	is_subset = isl_set_is_subset(set1, set2);
4119 
4120 	isl_set_free(set1);
4121 	isl_set_free(set2);
4122 
4123 	if (is_subset < 0)
4124 		return isl_stat_error;
4125 	if (!is_subset)
4126 		isl_die(ctx, isl_error_unknown,
4127 			"set is not considered to be a subset of itself",
4128 			return isl_stat_error);
4129 
4130 	return isl_stat_ok;
4131 }
4132 
4133 struct {
4134 	const char *set1;
4135 	const char *set2;
4136 	int subset;
4137 } subset_tests[] = {
4138 	{ "{ [112, 0] }",
4139 	  "{ [i0, i1] : exists (e0 = [(i0 - i1)/16], e1: "
4140 		"16e0 <= i0 - i1 and 16e0 >= -15 + i0 - i1 and "
4141 		"16e1 <= i1 and 16e0 >= -i1 and 16e1 >= -i0 + i1) }", 1 },
4142 	{ "{ [65] }",
4143 	  "{ [i] : exists (e0 = [(255i)/256], e1 = [(127i + 65e0)/191], "
4144 		"e2 = [(3i + 61e1)/65], e3 = [(52i + 12e2)/61], "
4145 		"e4 = [(2i + e3)/3], e5 = [(4i + e3)/4], e6 = [(8i + e3)/12]: "
4146 		    "3e4 = 2i + e3 and 4e5 = 4i + e3 and 12e6 = 8i + e3 and "
4147 		    "i <= 255 and 64e3 >= -45 + 67i and i >= 0 and "
4148 		    "256e0 <= 255i and 256e0 >= -255 + 255i and "
4149 		    "191e1 <= 127i + 65e0 and 191e1 >= -190 + 127i + 65e0 and "
4150 		    "65e2 <= 3i + 61e1 and 65e2 >= -64 + 3i + 61e1 and "
4151 		    "61e3 <= 52i + 12e2 and 61e3 >= -60 + 52i + 12e2) }", 1 },
4152 	{ "{ [i] : 0 <= i <= 10 }", "{ rat: [i] : 0 <= i <= 10 }", 1 },
4153 	{ "{ rat: [i] : 0 <= i <= 10 }", "{ [i] : 0 <= i <= 10 }", 0 },
4154 	{ "{ rat: [0] }", "{ [i] : 0 <= i <= 10 }", 1 },
4155 	{ "{ rat: [(1)/2] }", "{ [i] : 0 <= i <= 10 }", 0 },
4156 	{ "{ [t, i] : (exists (e0 = [(2 + t)/4]: 4e0 <= 2 + t and "
4157 			"4e0 >= -1 + t and i >= 57 and i <= 62 and "
4158 			"4e0 <= 62 + t - i and 4e0 >= -61 + t + i and "
4159 			"t >= 0 and t <= 511 and 4e0 <= -57 + t + i and "
4160 			"4e0 >= 58 + t - i and i >= 58 + t and i >= 62 - t)) }",
4161 	  "{ [i0, i1] : (exists (e0 = [(4 + i0)/4]: 4e0 <= 62 + i0 - i1 and "
4162 			"4e0 >= 1 + i0 and i0 >= 0 and i0 <= 511 and "
4163 			"4e0 <= -57 + i0 + i1)) or "
4164 		"(exists (e0 = [(2 + i0)/4]: 4e0 <= i0 and "
4165 			"4e0 >= 58 + i0 - i1 and i0 >= 2 and i0 <= 511 and "
4166 			"4e0 >= -61 + i0 + i1)) or "
4167 		"(i1 <= 66 - i0 and i0 >= 2 and i1 >= 59 + i0) }", 1 },
4168 	{ "[a, b] -> { : a = 0 and b = -1 }", "[b, a] -> { : b >= -10 }", 1 },
4169 };
4170 
test_subset(isl_ctx * ctx)4171 static int test_subset(isl_ctx *ctx)
4172 {
4173 	int i;
4174 	isl_set *set1, *set2;
4175 	int subset;
4176 
4177 	if (test_subset_duplicate_integer_divisions(ctx) < 0)
4178 		return -1;
4179 
4180 	for (i = 0; i < ARRAY_SIZE(subset_tests); ++i) {
4181 		set1 = isl_set_read_from_str(ctx, subset_tests[i].set1);
4182 		set2 = isl_set_read_from_str(ctx, subset_tests[i].set2);
4183 		subset = isl_set_is_subset(set1, set2);
4184 		isl_set_free(set1);
4185 		isl_set_free(set2);
4186 		if (subset < 0)
4187 			return -1;
4188 		if (subset != subset_tests[i].subset)
4189 			isl_die(ctx, isl_error_unknown,
4190 				"incorrect subset result", return -1);
4191 	}
4192 
4193 	return 0;
4194 }
4195 
4196 /* Perform a set subtraction with a set that has a non-obviously empty disjunct.
4197  * Older versions of isl would fail on such cases.
4198  */
test_subtract_empty(isl_ctx * ctx)4199 static isl_stat test_subtract_empty(isl_ctx *ctx)
4200 {
4201 	const char *str;
4202 	isl_set *s1, *s2;
4203 
4204 	s1 = isl_set_read_from_str(ctx, "{ [0] }");
4205 	str = "{ [a] : (exists (e0, e1, e2: 1056e1 <= 32 + a - 33e0 and "
4206 			"1089e1 >= a - 33e0 and 1089e1 <= 1 + a - 33e0 and "
4207 			"33e2 >= -a + 33e0 + 1056e1 and "
4208 			"33e2 < -2a + 66e0 + 2112e1)) or a = 0 }";
4209 	s2 = isl_set_read_from_str(ctx, str);
4210 	s1 = isl_set_subtract(s1, s2);
4211 	isl_set_free(s1);
4212 
4213 	return isl_stat_non_null(s1);
4214 }
4215 
4216 struct {
4217 	const char *minuend;
4218 	const char *subtrahend;
4219 	const char *difference;
4220 } subtract_domain_tests[] = {
4221 	{ "{ A[i] -> B[i] }", "{ A[i] }", "{ }" },
4222 	{ "{ A[i] -> B[i] }", "{ B[i] }", "{ A[i] -> B[i] }" },
4223 	{ "{ A[i] -> B[i] }", "{ A[i] : i > 0 }", "{ A[i] -> B[i] : i <= 0 }" },
4224 };
4225 
test_subtract(isl_ctx * ctx)4226 static int test_subtract(isl_ctx *ctx)
4227 {
4228 	int i;
4229 	isl_union_map *umap1, *umap2;
4230 	isl_union_pw_multi_aff *upma1, *upma2;
4231 	isl_union_set *uset;
4232 	int equal;
4233 
4234 	if (test_subtract_empty(ctx) < 0)
4235 		return -1;
4236 
4237 	for (i = 0; i < ARRAY_SIZE(subtract_domain_tests); ++i) {
4238 		umap1 = isl_union_map_read_from_str(ctx,
4239 				subtract_domain_tests[i].minuend);
4240 		uset = isl_union_set_read_from_str(ctx,
4241 				subtract_domain_tests[i].subtrahend);
4242 		umap2 = isl_union_map_read_from_str(ctx,
4243 				subtract_domain_tests[i].difference);
4244 		umap1 = isl_union_map_subtract_domain(umap1, uset);
4245 		equal = isl_union_map_is_equal(umap1, umap2);
4246 		isl_union_map_free(umap1);
4247 		isl_union_map_free(umap2);
4248 		if (equal < 0)
4249 			return -1;
4250 		if (!equal)
4251 			isl_die(ctx, isl_error_unknown,
4252 				"incorrect subtract domain result", return -1);
4253 	}
4254 
4255 	for (i = 0; i < ARRAY_SIZE(subtract_domain_tests); ++i) {
4256 		upma1 = isl_union_pw_multi_aff_read_from_str(ctx,
4257 				subtract_domain_tests[i].minuend);
4258 		uset = isl_union_set_read_from_str(ctx,
4259 				subtract_domain_tests[i].subtrahend);
4260 		upma2 = isl_union_pw_multi_aff_read_from_str(ctx,
4261 				subtract_domain_tests[i].difference);
4262 		upma1 = isl_union_pw_multi_aff_subtract_domain(upma1, uset);
4263 		equal = isl_union_pw_multi_aff_plain_is_equal(upma1, upma2);
4264 		isl_union_pw_multi_aff_free(upma1);
4265 		isl_union_pw_multi_aff_free(upma2);
4266 		if (equal < 0)
4267 			return -1;
4268 		if (!equal)
4269 			isl_die(ctx, isl_error_unknown,
4270 				"incorrect subtract domain result", return -1);
4271 	}
4272 
4273 	return 0;
4274 }
4275 
4276 /* Check that intersecting the empty basic set with another basic set
4277  * does not increase the number of constraints.  In particular,
4278  * the empty basic set should maintain its canonical representation.
4279  */
test_intersect_1(isl_ctx * ctx)4280 static int test_intersect_1(isl_ctx *ctx)
4281 {
4282 	isl_size n1, n2;
4283 	isl_basic_set *bset1, *bset2;
4284 
4285 	bset1 = isl_basic_set_read_from_str(ctx, "{ [a,b,c] : 1 = 0 }");
4286 	bset2 = isl_basic_set_read_from_str(ctx, "{ [1,2,3] }");
4287 	n1 = isl_basic_set_n_constraint(bset1);
4288 	bset1 = isl_basic_set_intersect(bset1, bset2);
4289 	n2 = isl_basic_set_n_constraint(bset1);
4290 	isl_basic_set_free(bset1);
4291 	if (n1 < 0 || n2 < 0)
4292 		return -1;
4293 	if (n1 != n2)
4294 		isl_die(ctx, isl_error_unknown,
4295 			"number of constraints of empty set changed",
4296 			return -1);
4297 
4298 	return 0;
4299 }
4300 
4301 /* Check that intersecting a set with itself does not cause
4302  * an explosion in the number of disjuncts.
4303  */
test_intersect_2(isl_ctx * ctx)4304 static isl_stat test_intersect_2(isl_ctx *ctx)
4305 {
4306 	int i;
4307 	isl_set *set;
4308 
4309 	set = isl_set_read_from_str(ctx, "{ [x,y] : x >= 0 or y >= 0 }");
4310 	for (i = 0; i < 100; ++i)
4311 		set = isl_set_intersect(set, isl_set_copy(set));
4312 	isl_set_free(set);
4313 	if (!set)
4314 		return isl_stat_error;
4315 	return isl_stat_ok;
4316 }
4317 
4318 /* Perform some intersection tests.
4319  */
test_intersect(isl_ctx * ctx)4320 static int test_intersect(isl_ctx *ctx)
4321 {
4322 	if (test_intersect_1(ctx) < 0)
4323 		return -1;
4324 	if (test_intersect_2(ctx) < 0)
4325 		return -1;
4326 
4327 	return 0;
4328 }
4329 
test_factorize(isl_ctx * ctx)4330 int test_factorize(isl_ctx *ctx)
4331 {
4332 	const char *str;
4333 	isl_basic_set *bset;
4334 	isl_factorizer *f;
4335 
4336 	str = "{ [i0, i1, i2, i3, i4, i5, i6, i7] : 3i5 <= 2 - 2i0 and "
4337 	    "i0 >= -2 and i6 >= 1 + i3 and i7 >= 0 and 3i5 >= -2i0 and "
4338 	    "2i4 <= i2 and i6 >= 1 + 2i0 + 3i1 and i4 <= -1 and "
4339 	    "i6 >= 1 + 2i0 + 3i5 and i6 <= 2 + 2i0 + 3i5 and "
4340 	    "3i5 <= 2 - 2i0 - i2 + 3i4 and i6 <= 2 + 2i0 + 3i1 and "
4341 	    "i0 <= -1 and i7 <= i2 + i3 - 3i4 - i6 and "
4342 	    "3i5 >= -2i0 - i2 + 3i4 }";
4343 	bset = isl_basic_set_read_from_str(ctx, str);
4344 	f = isl_basic_set_factorizer(bset);
4345 	isl_basic_set_free(bset);
4346 	isl_factorizer_free(f);
4347 	if (!f)
4348 		isl_die(ctx, isl_error_unknown,
4349 			"failed to construct factorizer", return -1);
4350 
4351 	str = "{ [i0, i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11, i12] : "
4352 	    "i12 <= 2 + i0 - i11 and 2i8 >= -i4 and i11 >= i1 and "
4353 	    "3i5 <= -i2 and 2i11 >= -i4 - 2i7 and i11 <= 3 + i0 + 3i9 and "
4354 	    "i11 <= -i4 - 2i7 and i12 >= -i10 and i2 >= -2 and "
4355 	    "i11 >= i1 + 3i10 and i11 >= 1 + i0 + 3i9 and "
4356 	    "i11 <= 1 - i4 - 2i8 and 6i6 <= 6 - i2 and 3i6 >= 1 - i2 and "
4357 	    "i11 <= 2 + i1 and i12 <= i4 + i11 and i12 >= i0 - i11 and "
4358 	    "3i5 >= -2 - i2 and i12 >= -1 + i4 + i11 and 3i3 <= 3 - i2 and "
4359 	    "9i6 <= 11 - i2 + 6i5 and 3i3 >= 1 - i2 and "
4360 	    "9i6 <= 5 - i2 + 6i3 and i12 <= -1 and i2 <= 0 }";
4361 	bset = isl_basic_set_read_from_str(ctx, str);
4362 	f = isl_basic_set_factorizer(bset);
4363 	isl_basic_set_free(bset);
4364 	isl_factorizer_free(f);
4365 	if (!f)
4366 		isl_die(ctx, isl_error_unknown,
4367 			"failed to construct factorizer", return -1);
4368 
4369 	return 0;
4370 }
4371 
check_injective(__isl_take isl_map * map,void * user)4372 static isl_stat check_injective(__isl_take isl_map *map, void *user)
4373 {
4374 	int *injective = user;
4375 
4376 	*injective = isl_map_is_injective(map);
4377 	isl_map_free(map);
4378 
4379 	if (*injective < 0 || !*injective)
4380 		return isl_stat_error;
4381 
4382 	return isl_stat_ok;
4383 }
4384 
test_one_schedule(isl_ctx * ctx,const char * d,const char * w,const char * r,const char * s,int tilable,int parallel)4385 int test_one_schedule(isl_ctx *ctx, const char *d, const char *w,
4386 	const char *r, const char *s, int tilable, int parallel)
4387 {
4388 	int i;
4389 	isl_union_set *D;
4390 	isl_union_map *W, *R, *S;
4391 	isl_union_map *empty;
4392 	isl_union_map *dep_raw, *dep_war, *dep_waw, *dep;
4393 	isl_union_map *validity, *proximity, *coincidence;
4394 	isl_union_map *schedule;
4395 	isl_union_map *test;
4396 	isl_union_set *delta;
4397 	isl_union_set *domain;
4398 	isl_set *delta_set;
4399 	isl_set *slice;
4400 	isl_set *origin;
4401 	isl_schedule_constraints *sc;
4402 	isl_schedule *sched;
4403 	int is_nonneg, is_parallel, is_tilable, is_injection, is_complete;
4404 	isl_size n;
4405 
4406 	D = isl_union_set_read_from_str(ctx, d);
4407 	W = isl_union_map_read_from_str(ctx, w);
4408 	R = isl_union_map_read_from_str(ctx, r);
4409 	S = isl_union_map_read_from_str(ctx, s);
4410 
4411 	W = isl_union_map_intersect_domain(W, isl_union_set_copy(D));
4412 	R = isl_union_map_intersect_domain(R, isl_union_set_copy(D));
4413 
4414 	empty = isl_union_map_empty(isl_union_map_get_space(S));
4415         isl_union_map_compute_flow(isl_union_map_copy(R),
4416 				   isl_union_map_copy(W), empty,
4417 				   isl_union_map_copy(S),
4418 				   &dep_raw, NULL, NULL, NULL);
4419         isl_union_map_compute_flow(isl_union_map_copy(W),
4420 				   isl_union_map_copy(W),
4421 				   isl_union_map_copy(R),
4422 				   isl_union_map_copy(S),
4423 				   &dep_waw, &dep_war, NULL, NULL);
4424 
4425 	dep = isl_union_map_union(dep_waw, dep_war);
4426 	dep = isl_union_map_union(dep, dep_raw);
4427 	validity = isl_union_map_copy(dep);
4428 	coincidence = isl_union_map_copy(dep);
4429 	proximity = isl_union_map_copy(dep);
4430 
4431 	sc = isl_schedule_constraints_on_domain(isl_union_set_copy(D));
4432 	sc = isl_schedule_constraints_set_validity(sc, validity);
4433 	sc = isl_schedule_constraints_set_coincidence(sc, coincidence);
4434 	sc = isl_schedule_constraints_set_proximity(sc, proximity);
4435 	sched = isl_schedule_constraints_compute_schedule(sc);
4436 	schedule = isl_schedule_get_map(sched);
4437 	isl_schedule_free(sched);
4438 	isl_union_map_free(W);
4439 	isl_union_map_free(R);
4440 	isl_union_map_free(S);
4441 
4442 	is_injection = 1;
4443 	isl_union_map_foreach_map(schedule, &check_injective, &is_injection);
4444 
4445 	domain = isl_union_map_domain(isl_union_map_copy(schedule));
4446 	is_complete = isl_union_set_is_subset(D, domain);
4447 	isl_union_set_free(D);
4448 	isl_union_set_free(domain);
4449 
4450 	test = isl_union_map_reverse(isl_union_map_copy(schedule));
4451 	test = isl_union_map_apply_range(test, dep);
4452 	test = isl_union_map_apply_range(test, schedule);
4453 
4454 	delta = isl_union_map_deltas(test);
4455 	n = isl_union_set_n_set(delta);
4456 	if (n < 0) {
4457 		isl_union_set_free(delta);
4458 		return -1;
4459 	}
4460 	if (n == 0) {
4461 		is_tilable = 1;
4462 		is_parallel = 1;
4463 		is_nonneg = 1;
4464 		isl_union_set_free(delta);
4465 	} else {
4466 		isl_size dim;
4467 
4468 		delta_set = isl_set_from_union_set(delta);
4469 
4470 		slice = isl_set_universe(isl_set_get_space(delta_set));
4471 		for (i = 0; i < tilable; ++i)
4472 			slice = isl_set_lower_bound_si(slice, isl_dim_set, i, 0);
4473 		is_tilable = isl_set_is_subset(delta_set, slice);
4474 		isl_set_free(slice);
4475 
4476 		slice = isl_set_universe(isl_set_get_space(delta_set));
4477 		for (i = 0; i < parallel; ++i)
4478 			slice = isl_set_fix_si(slice, isl_dim_set, i, 0);
4479 		is_parallel = isl_set_is_subset(delta_set, slice);
4480 		isl_set_free(slice);
4481 
4482 		origin = isl_set_universe(isl_set_get_space(delta_set));
4483 		dim = isl_set_dim(origin, isl_dim_set);
4484 		if (dim < 0)
4485 			origin = isl_set_free(origin);
4486 		for (i = 0; i < dim; ++i)
4487 			origin = isl_set_fix_si(origin, isl_dim_set, i, 0);
4488 
4489 		delta_set = isl_set_union(delta_set, isl_set_copy(origin));
4490 		delta_set = isl_set_lexmin(delta_set);
4491 
4492 		is_nonneg = isl_set_is_equal(delta_set, origin);
4493 
4494 		isl_set_free(origin);
4495 		isl_set_free(delta_set);
4496 	}
4497 
4498 	if (is_nonneg < 0 || is_parallel < 0 || is_tilable < 0 ||
4499 	    is_injection < 0 || is_complete < 0)
4500 		return -1;
4501 	if (!is_complete)
4502 		isl_die(ctx, isl_error_unknown,
4503 			"generated schedule incomplete", return -1);
4504 	if (!is_injection)
4505 		isl_die(ctx, isl_error_unknown,
4506 			"generated schedule not injective on each statement",
4507 			return -1);
4508 	if (!is_nonneg)
4509 		isl_die(ctx, isl_error_unknown,
4510 			"negative dependences in generated schedule",
4511 			return -1);
4512 	if (!is_tilable)
4513 		isl_die(ctx, isl_error_unknown,
4514 			"generated schedule not as tilable as expected",
4515 			return -1);
4516 	if (!is_parallel)
4517 		isl_die(ctx, isl_error_unknown,
4518 			"generated schedule not as parallel as expected",
4519 			return -1);
4520 
4521 	return 0;
4522 }
4523 
4524 /* Compute a schedule for the given instance set, validity constraints,
4525  * proximity constraints and context and return a corresponding union map
4526  * representation.
4527  */
compute_schedule_with_context(isl_ctx * ctx,const char * domain,const char * validity,const char * proximity,const char * context)4528 static __isl_give isl_union_map *compute_schedule_with_context(isl_ctx *ctx,
4529 	const char *domain, const char *validity, const char *proximity,
4530 	const char *context)
4531 {
4532 	isl_set *con;
4533 	isl_union_set *dom;
4534 	isl_union_map *dep;
4535 	isl_union_map *prox;
4536 	isl_schedule_constraints *sc;
4537 	isl_schedule *schedule;
4538 	isl_union_map *sched;
4539 
4540 	con = isl_set_read_from_str(ctx, context);
4541 	dom = isl_union_set_read_from_str(ctx, domain);
4542 	dep = isl_union_map_read_from_str(ctx, validity);
4543 	prox = isl_union_map_read_from_str(ctx, proximity);
4544 	sc = isl_schedule_constraints_on_domain(dom);
4545 	sc = isl_schedule_constraints_set_context(sc, con);
4546 	sc = isl_schedule_constraints_set_validity(sc, dep);
4547 	sc = isl_schedule_constraints_set_proximity(sc, prox);
4548 	schedule = isl_schedule_constraints_compute_schedule(sc);
4549 	sched = isl_schedule_get_map(schedule);
4550 	isl_schedule_free(schedule);
4551 
4552 	return sched;
4553 }
4554 
4555 /* Compute a schedule for the given instance set, validity constraints and
4556  * proximity constraints and return a corresponding union map representation.
4557  */
compute_schedule(isl_ctx * ctx,const char * domain,const char * validity,const char * proximity)4558 static __isl_give isl_union_map *compute_schedule(isl_ctx *ctx,
4559 	const char *domain, const char *validity, const char *proximity)
4560 {
4561 	return compute_schedule_with_context(ctx, domain, validity, proximity,
4562 						"{ : }");
4563 }
4564 
4565 /* Check that a schedule can be constructed on the given domain
4566  * with the given validity and proximity constraints.
4567  */
test_has_schedule(isl_ctx * ctx,const char * domain,const char * validity,const char * proximity)4568 static int test_has_schedule(isl_ctx *ctx, const char *domain,
4569 	const char *validity, const char *proximity)
4570 {
4571 	isl_union_map *sched;
4572 
4573 	sched = compute_schedule(ctx, domain, validity, proximity);
4574 	if (!sched)
4575 		return -1;
4576 
4577 	isl_union_map_free(sched);
4578 	return 0;
4579 }
4580 
test_special_schedule(isl_ctx * ctx,const char * domain,const char * validity,const char * proximity,const char * expected_sched)4581 int test_special_schedule(isl_ctx *ctx, const char *domain,
4582 	const char *validity, const char *proximity, const char *expected_sched)
4583 {
4584 	isl_union_map *sched1, *sched2;
4585 	int equal;
4586 
4587 	sched1 = compute_schedule(ctx, domain, validity, proximity);
4588 	sched2 = isl_union_map_read_from_str(ctx, expected_sched);
4589 
4590 	equal = isl_union_map_is_equal(sched1, sched2);
4591 	isl_union_map_free(sched1);
4592 	isl_union_map_free(sched2);
4593 
4594 	if (equal < 0)
4595 		return -1;
4596 	if (!equal)
4597 		isl_die(ctx, isl_error_unknown, "unexpected schedule",
4598 			return -1);
4599 
4600 	return 0;
4601 }
4602 
4603 /* Check that the schedule map is properly padded, i.e., that the range
4604  * lives in a single space.
4605  */
test_padded_schedule(isl_ctx * ctx)4606 static int test_padded_schedule(isl_ctx *ctx)
4607 {
4608 	const char *str;
4609 	isl_union_set *D;
4610 	isl_union_map *validity, *proximity;
4611 	isl_schedule_constraints *sc;
4612 	isl_schedule *sched;
4613 	isl_union_map *umap;
4614 	isl_union_set *range;
4615 	isl_set *set;
4616 
4617 	str = "[N] -> { S0[i] : 0 <= i <= N; S1[i, j] : 0 <= i, j <= N }";
4618 	D = isl_union_set_read_from_str(ctx, str);
4619 	validity = isl_union_map_empty(isl_union_set_get_space(D));
4620 	proximity = isl_union_map_copy(validity);
4621 	sc = isl_schedule_constraints_on_domain(D);
4622 	sc = isl_schedule_constraints_set_validity(sc, validity);
4623 	sc = isl_schedule_constraints_set_proximity(sc, proximity);
4624 	sched = isl_schedule_constraints_compute_schedule(sc);
4625 	umap = isl_schedule_get_map(sched);
4626 	isl_schedule_free(sched);
4627 	range = isl_union_map_range(umap);
4628 	set = isl_set_from_union_set(range);
4629 	isl_set_free(set);
4630 
4631 	if (!set)
4632 		return -1;
4633 
4634 	return 0;
4635 }
4636 
4637 /* Check that conditional validity constraints are also taken into
4638  * account across bands.
4639  * In particular, try to make sure that live ranges D[1,0]->C[2,1] and
4640  * D[2,0]->C[3,0] are not local in the outer band of the generated schedule
4641  * and then check that the adjacent order constraint C[2,1]->D[2,0]
4642  * is enforced by the rest of the schedule.
4643  */
test_special_conditional_schedule_constraints(isl_ctx * ctx)4644 static int test_special_conditional_schedule_constraints(isl_ctx *ctx)
4645 {
4646 	const char *str;
4647 	isl_union_set *domain;
4648 	isl_union_map *validity, *proximity, *condition;
4649 	isl_union_map *sink, *source, *dep;
4650 	isl_schedule_constraints *sc;
4651 	isl_schedule *schedule;
4652 	isl_union_access_info *access;
4653 	isl_union_flow *flow;
4654 	int empty;
4655 
4656 	str = "[n] -> { C[k, i] : k <= -1 + n and i >= 0 and i <= -1 + k; "
4657 	    "A[k] : k >= 1 and k <= -1 + n; "
4658 	    "B[k, i] : k <= -1 + n and i >= 0 and i <= -1 + k; "
4659 	    "D[k, i] : k <= -1 + n and i >= 0 and i <= -1 + k }";
4660 	domain = isl_union_set_read_from_str(ctx, str);
4661 	sc = isl_schedule_constraints_on_domain(domain);
4662 	str = "[n] -> { D[k, i] -> C[1 + k, k - i] : "
4663 		"k <= -2 + n and i >= 1 and i <= -1 + k; "
4664 		"D[k, i] -> C[1 + k, i] : "
4665 		"k <= -2 + n and i >= 1 and i <= -1 + k; "
4666 		"D[k, 0] -> C[1 + k, k] : k >= 1 and k <= -2 + n; "
4667 		"D[k, 0] -> C[1 + k, 0] : k >= 1 and k <= -2 + n }";
4668 	validity = isl_union_map_read_from_str(ctx, str);
4669 	sc = isl_schedule_constraints_set_validity(sc, validity);
4670 	str = "[n] -> { C[k, i] -> D[k, i] : "
4671 		"0 <= i <= -1 + k and k <= -1 + n }";
4672 	proximity = isl_union_map_read_from_str(ctx, str);
4673 	sc = isl_schedule_constraints_set_proximity(sc, proximity);
4674 	str = "[n] -> { [D[k, i] -> a[]] -> [C[1 + k, k - i] -> b[]] : "
4675 		"i <= -1 + k and i >= 1 and k <= -2 + n; "
4676 		"[B[k, i] -> c[]] -> [B[k, 1 + i] -> c[]] : "
4677 		"k <= -1 + n and i >= 0 and i <= -2 + k }";
4678 	condition = isl_union_map_read_from_str(ctx, str);
4679 	str = "[n] -> { [B[k, i] -> e[]] -> [D[k, i] -> a[]] : "
4680 		"i >= 0 and i <= -1 + k and k <= -1 + n; "
4681 		"[C[k, i] -> b[]] -> [D[k', -1 + k - i] -> a[]] : "
4682 		"i >= 0 and i <= -1 + k and k <= -1 + n and "
4683 		"k' <= -1 + n and k' >= k - i and k' >= 1 + k; "
4684 		"[C[k, i] -> b[]] -> [D[k, -1 + k - i] -> a[]] : "
4685 		"i >= 0 and i <= -1 + k and k <= -1 + n; "
4686 		"[B[k, i] -> c[]] -> [A[k'] -> d[]] : "
4687 		"k <= -1 + n and i >= 0 and i <= -1 + k and "
4688 		"k' >= 1 and k' <= -1 + n and k' >= 1 + k }";
4689 	validity = isl_union_map_read_from_str(ctx, str);
4690 	sc = isl_schedule_constraints_set_conditional_validity(sc, condition,
4691 								validity);
4692 	schedule = isl_schedule_constraints_compute_schedule(sc);
4693 	str = "{ D[2,0] -> [] }";
4694 	sink = isl_union_map_read_from_str(ctx, str);
4695 	access = isl_union_access_info_from_sink(sink);
4696 	str = "{ C[2,1] -> [] }";
4697 	source = isl_union_map_read_from_str(ctx, str);
4698 	access = isl_union_access_info_set_must_source(access, source);
4699 	access = isl_union_access_info_set_schedule(access, schedule);
4700 	flow = isl_union_access_info_compute_flow(access);
4701 	dep = isl_union_flow_get_must_dependence(flow);
4702 	isl_union_flow_free(flow);
4703 	empty = isl_union_map_is_empty(dep);
4704 	isl_union_map_free(dep);
4705 
4706 	if (empty < 0)
4707 		return -1;
4708 	if (empty)
4709 		isl_die(ctx, isl_error_unknown,
4710 			"conditional validity not respected", return -1);
4711 
4712 	return 0;
4713 }
4714 
4715 /* Check that the test for violated conditional validity constraints
4716  * is not confused by domain compression.
4717  * In particular, earlier versions of isl would apply
4718  * a schedule on the compressed domains to the original domains,
4719  * resulting in a failure to detect that the default schedule
4720  * violates the conditional validity constraints.
4721  */
test_special_conditional_schedule_constraints_2(isl_ctx * ctx)4722 static int test_special_conditional_schedule_constraints_2(isl_ctx *ctx)
4723 {
4724 	const char *str;
4725 	isl_bool empty;
4726 	isl_union_set *domain;
4727 	isl_union_map *validity, *condition;
4728 	isl_schedule_constraints *sc;
4729 	isl_schedule *schedule;
4730 	isl_union_map *umap;
4731 	isl_map *map, *ge;
4732 
4733 	str = "{ A[0, i] : 0 <= i <= 10; B[1, i] : 0 <= i <= 10 }";
4734 	domain = isl_union_set_read_from_str(ctx, str);
4735 	sc = isl_schedule_constraints_on_domain(domain);
4736 	str = "{ B[1, i] -> A[0, i + 1] }";
4737 	condition = isl_union_map_read_from_str(ctx, str);
4738 	str = "{ A[0, i] -> B[1, i - 1] }";
4739 	validity = isl_union_map_read_from_str(ctx, str);
4740 	sc = isl_schedule_constraints_set_conditional_validity(sc, condition,
4741 						isl_union_map_copy(validity));
4742 	schedule = isl_schedule_constraints_compute_schedule(sc);
4743 	umap = isl_schedule_get_map(schedule);
4744 	isl_schedule_free(schedule);
4745 	validity = isl_union_map_apply_domain(validity,
4746 						isl_union_map_copy(umap));
4747 	validity = isl_union_map_apply_range(validity, umap);
4748 	map = isl_map_from_union_map(validity);
4749 	ge = isl_map_lex_ge(isl_space_domain(isl_map_get_space(map)));
4750 	map = isl_map_intersect(map, ge);
4751 	empty = isl_map_is_empty(map);
4752 	isl_map_free(map);
4753 
4754 	if (empty < 0)
4755 		return -1;
4756 	if (!empty)
4757 		isl_die(ctx, isl_error_unknown,
4758 			"conditional validity constraints not satisfied",
4759 			return -1);
4760 
4761 	return 0;
4762 }
4763 
4764 /* Input for testing of schedule construction based on
4765  * conditional constraints.
4766  *
4767  * domain is the iteration domain
4768  * flow are the flow dependences, which determine the validity and
4769  * 	proximity constraints
4770  * condition are the conditions on the conditional validity constraints
4771  * conditional_validity are the conditional validity constraints
4772  * outer_band_n is the expected number of members in the outer band
4773  */
4774 struct {
4775 	const char *domain;
4776 	const char *flow;
4777 	const char *condition;
4778 	const char *conditional_validity;
4779 	int outer_band_n;
4780 } live_range_tests[] = {
4781 	/* Contrived example that illustrates that we need to keep
4782 	 * track of tagged condition dependences and
4783 	 * tagged conditional validity dependences
4784 	 * in isl_sched_edge separately.
4785 	 * In particular, the conditional validity constraints on A
4786 	 * cannot be satisfied,
4787 	 * but they can be ignored because there are no corresponding
4788 	 * condition constraints.  However, we do have an additional
4789 	 * conditional validity constraint that maps to the same
4790 	 * dependence relation
4791 	 * as the condition constraint on B.  If we did not make a distinction
4792 	 * between tagged condition and tagged conditional validity
4793 	 * dependences, then we
4794 	 * could end up treating this shared dependence as an condition
4795 	 * constraint on A, forcing a localization of the conditions,
4796 	 * which is impossible.
4797 	 */
4798 	{ "{ S[i] : 0 <= 1 < 100; T[i] : 0 <= 1 < 100 }",
4799 	  "{ S[i] -> S[i+1] : 0 <= i < 99 }",
4800 	  "{ [S[i] -> B[]] -> [S[i+1] -> B[]] : 0 <= i < 99 }",
4801 	  "{ [S[i] -> A[]] -> [T[i'] -> A[]] : 0 <= i', i < 100 and i != i';"
4802 	    "[T[i] -> A[]] -> [S[i'] -> A[]] : 0 <= i', i < 100 and i != i';"
4803 	    "[S[i] -> A[]] -> [S[i+1] -> A[]] : 0 <= i < 99 }",
4804 	  1
4805 	},
4806 	/* TACO 2013 Fig. 7 */
4807 	{ "[n] -> { S1[i,j] : 0 <= i,j < n; S2[i,j] : 0 <= i,j < n }",
4808 	  "[n] -> { S1[i,j] -> S2[i,j] : 0 <= i,j < n;"
4809 		   "S2[i,j] -> S2[i,j+1] : 0 <= i < n and 0 <= j < n - 1 }",
4810 	  "[n] -> { [S1[i,j] -> t[]] -> [S2[i,j] -> t[]] : 0 <= i,j < n;"
4811 		   "[S2[i,j] -> x1[]] -> [S2[i,j+1] -> x1[]] : "
4812 				"0 <= i < n and 0 <= j < n - 1 }",
4813 	  "[n] -> { [S2[i,j] -> t[]] -> [S1[i,j'] -> t[]] : "
4814 				"0 <= i < n and 0 <= j < j' < n;"
4815 		   "[S2[i,j] -> t[]] -> [S1[i',j'] -> t[]] : "
4816 				"0 <= i < i' < n and 0 <= j,j' < n;"
4817 		   "[S2[i,j] -> x1[]] -> [S2[i,j'] -> x1[]] : "
4818 				"0 <= i,j,j' < n and j < j' }",
4819 	    2
4820 	},
4821 	/* TACO 2013 Fig. 7, without tags */
4822 	{ "[n] -> { S1[i,j] : 0 <= i,j < n; S2[i,j] : 0 <= i,j < n }",
4823 	  "[n] -> { S1[i,j] -> S2[i,j] : 0 <= i,j < n;"
4824 		   "S2[i,j] -> S2[i,j+1] : 0 <= i < n and 0 <= j < n - 1 }",
4825 	  "[n] -> { S1[i,j] -> S2[i,j] : 0 <= i,j < n;"
4826 		   "S2[i,j] -> S2[i,j+1] : 0 <= i < n and 0 <= j < n - 1 }",
4827 	  "[n] -> { S2[i,j] -> S1[i,j'] : 0 <= i < n and 0 <= j < j' < n;"
4828 		   "S2[i,j] -> S1[i',j'] : 0 <= i < i' < n and 0 <= j,j' < n;"
4829 		   "S2[i,j] -> S2[i,j'] : 0 <= i,j,j' < n and j < j' }",
4830 	   1
4831 	},
4832 	/* TACO 2013 Fig. 12 */
4833 	{ "{ S1[i,0] : 0 <= i <= 1; S2[i,j] : 0 <= i <= 1 and 1 <= j <= 2;"
4834 	    "S3[i,3] : 0 <= i <= 1 }",
4835 	  "{ S1[i,0] -> S2[i,1] : 0 <= i <= 1;"
4836 	    "S2[i,1] -> S2[i,2] : 0 <= i <= 1;"
4837 	    "S2[i,2] -> S3[i,3] : 0 <= i <= 1 }",
4838 	  "{ [S1[i,0]->t[]] -> [S2[i,1]->t[]] : 0 <= i <= 1;"
4839 	    "[S2[i,1]->t[]] -> [S2[i,2]->t[]] : 0 <= i <= 1;"
4840 	    "[S2[i,2]->t[]] -> [S3[i,3]->t[]] : 0 <= i <= 1 }",
4841 	  "{ [S2[i,1]->t[]] -> [S2[i,2]->t[]] : 0 <= i <= 1;"
4842 	    "[S2[0,j]->t[]] -> [S2[1,j']->t[]] : 1 <= j,j' <= 2;"
4843 	    "[S2[0,j]->t[]] -> [S1[1,0]->t[]] : 1 <= j <= 2;"
4844 	    "[S3[0,3]->t[]] -> [S2[1,j]->t[]] : 1 <= j <= 2;"
4845 	    "[S3[0,3]->t[]] -> [S1[1,0]->t[]] }",
4846 	   1
4847 	}
4848 };
4849 
4850 /* Test schedule construction based on conditional constraints.
4851  * In particular, check the number of members in the outer band node
4852  * as an indication of whether tiling is possible or not.
4853  */
test_conditional_schedule_constraints(isl_ctx * ctx)4854 static int test_conditional_schedule_constraints(isl_ctx *ctx)
4855 {
4856 	int i;
4857 	isl_union_set *domain;
4858 	isl_union_map *condition;
4859 	isl_union_map *flow;
4860 	isl_union_map *validity;
4861 	isl_schedule_constraints *sc;
4862 	isl_schedule *schedule;
4863 	isl_schedule_node *node;
4864 	isl_size n_member;
4865 
4866 	if (test_special_conditional_schedule_constraints(ctx) < 0)
4867 		return -1;
4868 	if (test_special_conditional_schedule_constraints_2(ctx) < 0)
4869 		return -1;
4870 
4871 	for (i = 0; i < ARRAY_SIZE(live_range_tests); ++i) {
4872 		domain = isl_union_set_read_from_str(ctx,
4873 				live_range_tests[i].domain);
4874 		flow = isl_union_map_read_from_str(ctx,
4875 				live_range_tests[i].flow);
4876 		condition = isl_union_map_read_from_str(ctx,
4877 				live_range_tests[i].condition);
4878 		validity = isl_union_map_read_from_str(ctx,
4879 				live_range_tests[i].conditional_validity);
4880 		sc = isl_schedule_constraints_on_domain(domain);
4881 		sc = isl_schedule_constraints_set_validity(sc,
4882 				isl_union_map_copy(flow));
4883 		sc = isl_schedule_constraints_set_proximity(sc, flow);
4884 		sc = isl_schedule_constraints_set_conditional_validity(sc,
4885 				condition, validity);
4886 		schedule = isl_schedule_constraints_compute_schedule(sc);
4887 		node = isl_schedule_get_root(schedule);
4888 		while (node &&
4889 		    isl_schedule_node_get_type(node) != isl_schedule_node_band)
4890 			node = isl_schedule_node_first_child(node);
4891 		n_member = isl_schedule_node_band_n_member(node);
4892 		isl_schedule_node_free(node);
4893 		isl_schedule_free(schedule);
4894 
4895 		if (!schedule || n_member < 0)
4896 			return -1;
4897 		if (n_member != live_range_tests[i].outer_band_n)
4898 			isl_die(ctx, isl_error_unknown,
4899 				"unexpected number of members in outer band",
4900 				return -1);
4901 	}
4902 	return 0;
4903 }
4904 
4905 /* Check that the schedule computed for the given instance set and
4906  * dependence relation strongly satisfies the dependences.
4907  * In particular, check that no instance is scheduled before
4908  * or together with an instance on which it depends.
4909  * Earlier versions of isl would produce a schedule that
4910  * only weakly satisfies the dependences.
4911  */
test_strongly_satisfying_schedule(isl_ctx * ctx)4912 static int test_strongly_satisfying_schedule(isl_ctx *ctx)
4913 {
4914 	const char *domain, *dep;
4915 	isl_union_map *D, *schedule;
4916 	isl_map *map, *ge;
4917 	int empty;
4918 
4919 	domain = "{ B[i0, i1] : 0 <= i0 <= 1 and 0 <= i1 <= 11; "
4920 		    "A[i0] : 0 <= i0 <= 1 }";
4921 	dep = "{ B[i0, i1] -> B[i0, 1 + i1] : 0 <= i0 <= 1 and 0 <= i1 <= 10; "
4922 		"B[0, 11] -> A[1]; A[i0] -> B[i0, 0] : 0 <= i0 <= 1 }";
4923 	schedule = compute_schedule(ctx, domain, dep, dep);
4924 	D = isl_union_map_read_from_str(ctx, dep);
4925 	D = isl_union_map_apply_domain(D, isl_union_map_copy(schedule));
4926 	D = isl_union_map_apply_range(D, schedule);
4927 	map = isl_map_from_union_map(D);
4928 	ge = isl_map_lex_ge(isl_space_domain(isl_map_get_space(map)));
4929 	map = isl_map_intersect(map, ge);
4930 	empty = isl_map_is_empty(map);
4931 	isl_map_free(map);
4932 
4933 	if (empty < 0)
4934 		return -1;
4935 	if (!empty)
4936 		isl_die(ctx, isl_error_unknown,
4937 			"dependences not strongly satisfied", return -1);
4938 
4939 	return 0;
4940 }
4941 
4942 /* Compute a schedule for input where the instance set constraints
4943  * conflict with the context constraints.
4944  * Earlier versions of isl did not properly handle this situation.
4945  */
test_conflicting_context_schedule(isl_ctx * ctx)4946 static int test_conflicting_context_schedule(isl_ctx *ctx)
4947 {
4948 	isl_union_map *schedule;
4949 	const char *domain, *context;
4950 
4951 	domain = "[n] -> { A[] : n >= 0 }";
4952 	context = "[n] -> { : n < 0 }";
4953 	schedule = compute_schedule_with_context(ctx,
4954 						domain, "{}", "{}", context);
4955 	isl_union_map_free(schedule);
4956 
4957 	if (!schedule)
4958 		return -1;
4959 
4960 	return 0;
4961 }
4962 
4963 /* Check that a set of schedule constraints that only allow for
4964  * a coalescing schedule still produces a schedule even if the user
4965  * request a non-coalescing schedule.  Earlier versions of isl
4966  * would not handle this case correctly.
4967  */
test_coalescing_schedule(isl_ctx * ctx)4968 static int test_coalescing_schedule(isl_ctx *ctx)
4969 {
4970 	const char *domain, *dep;
4971 	isl_union_set *I;
4972 	isl_union_map *D;
4973 	isl_schedule_constraints *sc;
4974 	isl_schedule *schedule;
4975 	int treat_coalescing;
4976 
4977 	domain = "{ S[a, b] : 0 <= a <= 1 and 0 <= b <= 1 }";
4978 	dep = "{ S[a, b] -> S[a + b, 1 - b] }";
4979 	I = isl_union_set_read_from_str(ctx, domain);
4980 	D = isl_union_map_read_from_str(ctx, dep);
4981 	sc = isl_schedule_constraints_on_domain(I);
4982 	sc = isl_schedule_constraints_set_validity(sc, D);
4983 	treat_coalescing = isl_options_get_schedule_treat_coalescing(ctx);
4984 	isl_options_set_schedule_treat_coalescing(ctx, 1);
4985 	schedule = isl_schedule_constraints_compute_schedule(sc);
4986 	isl_options_set_schedule_treat_coalescing(ctx, treat_coalescing);
4987 	isl_schedule_free(schedule);
4988 	if (!schedule)
4989 		return -1;
4990 	return 0;
4991 }
4992 
4993 /* Check that the scheduler does not perform any needless
4994  * compound skewing.  Earlier versions of isl would compute
4995  * schedules in terms of transformed schedule coefficients and
4996  * would not accurately keep track of the sum of the original
4997  * schedule coefficients.  It could then produce the schedule
4998  * S[t,i,j,k] -> [t, 2t + i, 2t + i + j, 2t + i + j + k]
4999  * for the input below instead of the schedule below.
5000  */
test_skewing_schedule(isl_ctx * ctx)5001 static int test_skewing_schedule(isl_ctx *ctx)
5002 {
5003 	const char *D, *V, *P, *S;
5004 
5005 	D = "[n] -> { S[t,i,j,k] : 0 <= t,i,j,k < n }";
5006 	V = "[n] -> { S[t,i,j,k] -> S[t+1,a,b,c] : 0 <= t,i,j,k,a,b,c < n and "
5007 		"-2 <= a-i <= 2 and -1 <= a-i + b-j <= 1 and "
5008 		"-1 <= a-i + b-j + c-k <= 1 }";
5009 	P = "{ }";
5010 	S = "{ S[t,i,j,k] -> [t, 2t + i, t + i + j, 2t + k] }";
5011 
5012 	return test_special_schedule(ctx, D, V, P, S);
5013 }
5014 
test_schedule(isl_ctx * ctx)5015 int test_schedule(isl_ctx *ctx)
5016 {
5017 	const char *D, *W, *R, *V, *P, *S;
5018 	int max_coincidence;
5019 	int treat_coalescing;
5020 
5021 	/* Handle resulting schedule with zero bands. */
5022 	if (test_one_schedule(ctx, "{[]}", "{}", "{}", "{[] -> []}", 0, 0) < 0)
5023 		return -1;
5024 
5025 	/* Jacobi */
5026 	D = "[T,N] -> { S1[t,i] : 1 <= t <= T and 2 <= i <= N - 1 }";
5027 	W = "{ S1[t,i] -> a[t,i] }";
5028 	R = "{ S1[t,i] -> a[t-1,i]; S1[t,i] -> a[t-1,i-1]; "
5029 	    	"S1[t,i] -> a[t-1,i+1] }";
5030 	S = "{ S1[t,i] -> [t,i] }";
5031 	if (test_one_schedule(ctx, D, W, R, S, 2, 0) < 0)
5032 		return -1;
5033 
5034 	/* Fig. 5 of CC2008 */
5035 	D = "[N] -> { S_0[i, j] : i >= 0 and i <= -1 + N and j >= 2 and "
5036 				"j <= -1 + N }";
5037 	W = "[N] -> { S_0[i, j] -> a[i, j] : i >= 0 and i <= -1 + N and "
5038 				"j >= 2 and j <= -1 + N }";
5039 	R = "[N] -> { S_0[i, j] -> a[j, i] : i >= 0 and i <= -1 + N and "
5040 				"j >= 2 and j <= -1 + N; "
5041 		    "S_0[i, j] -> a[i, -1 + j] : i >= 0 and i <= -1 + N and "
5042 				"j >= 2 and j <= -1 + N }";
5043 	S = "[N] -> { S_0[i, j] -> [0, i, 0, j, 0] }";
5044 	if (test_one_schedule(ctx, D, W, R, S, 2, 0) < 0)
5045 		return -1;
5046 
5047 	D = "{ S1[i] : 0 <= i <= 10; S2[i] : 0 <= i <= 9 }";
5048 	W = "{ S1[i] -> a[i] }";
5049 	R = "{ S2[i] -> a[i+1] }";
5050 	S = "{ S1[i] -> [0,i]; S2[i] -> [1,i] }";
5051 	if (test_one_schedule(ctx, D, W, R, S, 1, 1) < 0)
5052 		return -1;
5053 
5054 	D = "{ S1[i] : 0 <= i < 10; S2[i] : 0 <= i < 10 }";
5055 	W = "{ S1[i] -> a[i] }";
5056 	R = "{ S2[i] -> a[9-i] }";
5057 	S = "{ S1[i] -> [0,i]; S2[i] -> [1,i] }";
5058 	if (test_one_schedule(ctx, D, W, R, S, 1, 1) < 0)
5059 		return -1;
5060 
5061 	D = "[N] -> { S1[i] : 0 <= i < N; S2[i] : 0 <= i < N }";
5062 	W = "{ S1[i] -> a[i] }";
5063 	R = "[N] -> { S2[i] -> a[N-1-i] }";
5064 	S = "{ S1[i] -> [0,i]; S2[i] -> [1,i] }";
5065 	if (test_one_schedule(ctx, D, W, R, S, 1, 1) < 0)
5066 		return -1;
5067 
5068 	D = "{ S1[i] : 0 < i < 10; S2[i] : 0 <= i < 10 }";
5069 	W = "{ S1[i] -> a[i]; S2[i] -> b[i] }";
5070 	R = "{ S2[i] -> a[i]; S1[i] -> b[i-1] }";
5071 	S = "{ S1[i] -> [i,0]; S2[i] -> [i,1] }";
5072 	if (test_one_schedule(ctx, D, W, R, S, 0, 0) < 0)
5073 		return -1;
5074 
5075 	D = "[N] -> { S1[i] : 1 <= i <= N; S2[i,j] : 1 <= i,j <= N }";
5076 	W = "{ S1[i] -> a[0,i]; S2[i,j] -> a[i,j] }";
5077 	R = "{ S2[i,j] -> a[i-1,j] }";
5078 	S = "{ S1[i] -> [0,i,0]; S2[i,j] -> [1,i,j] }";
5079 	if (test_one_schedule(ctx, D, W, R, S, 2, 1) < 0)
5080 		return -1;
5081 
5082 	D = "[N] -> { S1[i] : 1 <= i <= N; S2[i,j] : 1 <= i,j <= N }";
5083 	W = "{ S1[i] -> a[i,0]; S2[i,j] -> a[i,j] }";
5084 	R = "{ S2[i,j] -> a[i,j-1] }";
5085 	S = "{ S1[i] -> [0,i,0]; S2[i,j] -> [1,i,j] }";
5086 	if (test_one_schedule(ctx, D, W, R, S, 2, 1) < 0)
5087 		return -1;
5088 
5089 	D = "[N] -> { S_0[]; S_1[i] : i >= 0 and i <= -1 + N; S_2[] }";
5090 	W = "[N] -> { S_0[] -> a[0]; S_2[] -> b[0]; "
5091 		    "S_1[i] -> a[1 + i] : i >= 0 and i <= -1 + N }";
5092 	R = "[N] -> { S_2[] -> a[N]; S_1[i] -> a[i] : i >= 0 and i <= -1 + N }";
5093 	S = "[N] -> { S_1[i] -> [1, i, 0]; S_2[] -> [2, 0, 1]; "
5094 		    "S_0[] -> [0, 0, 0] }";
5095 	if (test_one_schedule(ctx, D, W, R, S, 1, 0) < 0)
5096 		return -1;
5097 	ctx->opt->schedule_parametric = 0;
5098 	if (test_one_schedule(ctx, D, W, R, S, 0, 0) < 0)
5099 		return -1;
5100 	ctx->opt->schedule_parametric = 1;
5101 
5102 	D = "[N] -> { S1[i] : 1 <= i <= N; S2[i] : 1 <= i <= N; "
5103 		    "S3[i,j] : 1 <= i,j <= N; S4[i] : 1 <= i <= N }";
5104 	W = "{ S1[i] -> a[i,0]; S2[i] -> a[0,i]; S3[i,j] -> a[i,j] }";
5105 	R = "[N] -> { S3[i,j] -> a[i-1,j]; S3[i,j] -> a[i,j-1]; "
5106 		    "S4[i] -> a[i,N] }";
5107 	S = "{ S1[i] -> [0,i,0]; S2[i] -> [1,i,0]; S3[i,j] -> [2,i,j]; "
5108 		"S4[i] -> [4,i,0] }";
5109 	max_coincidence = isl_options_get_schedule_maximize_coincidence(ctx);
5110 	isl_options_set_schedule_maximize_coincidence(ctx, 0);
5111 	if (test_one_schedule(ctx, D, W, R, S, 2, 0) < 0)
5112 		return -1;
5113 	isl_options_set_schedule_maximize_coincidence(ctx, max_coincidence);
5114 
5115 	D = "[N] -> { S_0[i, j] : i >= 1 and i <= N and j >= 1 and j <= N }";
5116 	W = "[N] -> { S_0[i, j] -> s[0] : i >= 1 and i <= N and j >= 1 and "
5117 					"j <= N }";
5118 	R = "[N] -> { S_0[i, j] -> s[0] : i >= 1 and i <= N and j >= 1 and "
5119 					"j <= N; "
5120 		    "S_0[i, j] -> a[i, j] : i >= 1 and i <= N and j >= 1 and "
5121 					"j <= N }";
5122 	S = "[N] -> { S_0[i, j] -> [0, i, 0, j, 0] }";
5123 	if (test_one_schedule(ctx, D, W, R, S, 0, 0) < 0)
5124 		return -1;
5125 
5126 	D = "[N] -> { S_0[t] : t >= 0 and t <= -1 + N; "
5127 		    " S_2[t] : t >= 0 and t <= -1 + N; "
5128 		    " S_1[t, i] : t >= 0 and t <= -1 + N and i >= 0 and "
5129 				"i <= -1 + N }";
5130 	W = "[N] -> { S_0[t] -> a[t, 0] : t >= 0 and t <= -1 + N; "
5131 		    " S_2[t] -> b[t] : t >= 0 and t <= -1 + N; "
5132 		    " S_1[t, i] -> a[t, 1 + i] : t >= 0 and t <= -1 + N and "
5133 						"i >= 0 and i <= -1 + N }";
5134 	R = "[N] -> { S_1[t, i] -> a[t, i] : t >= 0 and t <= -1 + N and "
5135 					    "i >= 0 and i <= -1 + N; "
5136 		    " S_2[t] -> a[t, N] : t >= 0 and t <= -1 + N }";
5137 	S = "[N] -> { S_2[t] -> [0, t, 2]; S_1[t, i] -> [0, t, 1, i, 0]; "
5138 		    " S_0[t] -> [0, t, 0] }";
5139 
5140 	if (test_one_schedule(ctx, D, W, R, S, 2, 1) < 0)
5141 		return -1;
5142 	ctx->opt->schedule_parametric = 0;
5143 	if (test_one_schedule(ctx, D, W, R, S, 0, 0) < 0)
5144 		return -1;
5145 	ctx->opt->schedule_parametric = 1;
5146 
5147 	D = "[N] -> { S1[i,j] : 0 <= i,j < N; S2[i,j] : 0 <= i,j < N }";
5148 	S = "{ S1[i,j] -> [0,i,j]; S2[i,j] -> [1,i,j] }";
5149 	if (test_one_schedule(ctx, D, "{}", "{}", S, 2, 2) < 0)
5150 		return -1;
5151 
5152 	D = "[M, N] -> { S_1[i] : i >= 0 and i <= -1 + M; "
5153 	    "S_0[i, j] : i >= 0 and i <= -1 + M and j >= 0 and j <= -1 + N }";
5154 	W = "[M, N] -> { S_0[i, j] -> a[j] : i >= 0 and i <= -1 + M and "
5155 					    "j >= 0 and j <= -1 + N; "
5156 			"S_1[i] -> b[0] : i >= 0 and i <= -1 + M }";
5157 	R = "[M, N] -> { S_0[i, j] -> a[0] : i >= 0 and i <= -1 + M and "
5158 					    "j >= 0 and j <= -1 + N; "
5159 			"S_1[i] -> b[0] : i >= 0 and i <= -1 + M }";
5160 	S = "[M, N] -> { S_1[i] -> [1, i, 0]; S_0[i, j] -> [0, i, 0, j, 0] }";
5161 	if (test_one_schedule(ctx, D, W, R, S, 0, 0) < 0)
5162 		return -1;
5163 
5164 	D = "{ S_0[i] : i >= 0 }";
5165 	W = "{ S_0[i] -> a[i] : i >= 0 }";
5166 	R = "{ S_0[i] -> a[0] : i >= 0 }";
5167 	S = "{ S_0[i] -> [0, i, 0] }";
5168 	if (test_one_schedule(ctx, D, W, R, S, 0, 0) < 0)
5169 		return -1;
5170 
5171 	D = "{ S_0[i] : i >= 0; S_1[i] : i >= 0 }";
5172 	W = "{ S_0[i] -> a[i] : i >= 0; S_1[i] -> b[i] : i >= 0 }";
5173 	R = "{ S_0[i] -> b[0] : i >= 0; S_1[i] -> a[i] : i >= 0 }";
5174 	S = "{ S_1[i] -> [0, i, 1]; S_0[i] -> [0, i, 0] }";
5175 	if (test_one_schedule(ctx, D, W, R, S, 0, 0) < 0)
5176 		return -1;
5177 
5178 	D = "[n] -> { S_0[j, k] : j <= -1 + n and j >= 0 and "
5179 				"k <= -1 + n and k >= 0 }";
5180 	W = "[n] -> { S_0[j, k] -> B[j] : j <= -1 + n and j >= 0 and "							"k <= -1 + n and k >= 0 }";
5181 	R = "[n] -> { S_0[j, k] -> B[j] : j <= -1 + n and j >= 0 and "
5182 					"k <= -1 + n and k >= 0; "
5183 		    "S_0[j, k] -> B[k] : j <= -1 + n and j >= 0 and "
5184 					"k <= -1 + n and k >= 0; "
5185 		    "S_0[j, k] -> A[k] : j <= -1 + n and j >= 0 and "
5186 					"k <= -1 + n and k >= 0 }";
5187 	S = "[n] -> { S_0[j, k] -> [2, j, k] }";
5188 	ctx->opt->schedule_outer_coincidence = 1;
5189 	if (test_one_schedule(ctx, D, W, R, S, 0, 0) < 0)
5190 		return -1;
5191 	ctx->opt->schedule_outer_coincidence = 0;
5192 
5193 	D = "{Stmt_for_body24[i0, i1, i2, i3]:"
5194 		"i0 >= 0 and i0 <= 1 and i1 >= 0 and i1 <= 6 and i2 >= 2 and "
5195 		"i2 <= 6 - i1 and i3 >= 0 and i3 <= -1 + i2;"
5196 	     "Stmt_for_body24[i0, i1, 1, 0]:"
5197 		"i0 >= 0 and i0 <= 1 and i1 >= 0 and i1 <= 5;"
5198 	     "Stmt_for_body7[i0, i1, i2]:"
5199 		"i0 >= 0 and i0 <= 1 and i1 >= 0 and i1 <= 7 and i2 >= 0 and "
5200 		"i2 <= 7 }";
5201 
5202 	V = "{Stmt_for_body24[0, i1, i2, i3] -> "
5203 		"Stmt_for_body24[1, i1, i2, i3]:"
5204 		"i3 >= 0 and i3 <= -1 + i2 and i1 >= 0 and i2 <= 6 - i1 and "
5205 		"i2 >= 1;"
5206 	     "Stmt_for_body24[0, i1, i2, i3] -> "
5207 		"Stmt_for_body7[1, 1 + i1 + i3, 1 + i1 + i2]:"
5208 		"i3 <= -1 + i2 and i2 <= 6 - i1 and i2 >= 1 and i1 >= 0 and "
5209 		"i3 >= 0;"
5210 	      "Stmt_for_body24[0, i1, i2, i3] ->"
5211 		"Stmt_for_body7[1, i1, 1 + i1 + i3]:"
5212 		"i3 >= 0 and i2 <= 6 - i1 and i1 >= 0 and i3 <= -1 + i2;"
5213 	      "Stmt_for_body7[0, i1, i2] -> Stmt_for_body7[1, i1, i2]:"
5214 		"(i2 >= 1 + i1 and i2 <= 6 and i1 >= 0 and i1 <= 4) or "
5215 		"(i2 >= 3 and i2 <= 7 and i1 >= 1 and i2 >= 1 + i1) or "
5216 		"(i2 >= 0 and i2 <= i1 and i2 >= -7 + i1 and i1 <= 7);"
5217 	      "Stmt_for_body7[0, i1, 1 + i1] -> Stmt_for_body7[1, i1, 1 + i1]:"
5218 		"i1 <= 6 and i1 >= 0;"
5219 	      "Stmt_for_body7[0, 0, 7] -> Stmt_for_body7[1, 0, 7];"
5220 	      "Stmt_for_body7[i0, i1, i2] -> "
5221 		"Stmt_for_body24[i0, o1, -1 + i2 - o1, -1 + i1 - o1]:"
5222 		"i0 >= 0 and i0 <= 1 and o1 >= 0 and i2 >= 1 + i1 and "
5223 		"o1 <= -2 + i2 and i2 <= 7 and o1 <= -1 + i1;"
5224 	      "Stmt_for_body7[i0, i1, i2] -> "
5225 		"Stmt_for_body24[i0, i1, o2, -1 - i1 + i2]:"
5226 		"i0 >= 0 and i0 <= 1 and i1 >= 0 and o2 >= -i1 + i2 and "
5227 		"o2 >= 1 and o2 <= 6 - i1 and i2 >= 1 + i1 }";
5228 	P = V;
5229 
5230 	treat_coalescing = isl_options_get_schedule_treat_coalescing(ctx);
5231 	isl_options_set_schedule_treat_coalescing(ctx, 0);
5232 	if (test_has_schedule(ctx, D, V, P) < 0)
5233 		return -1;
5234 	isl_options_set_schedule_treat_coalescing(ctx, treat_coalescing);
5235 
5236 	D = "{ S_0[i, j] : i >= 1 and i <= 10 and j >= 1 and j <= 8 }";
5237 	V = "{ S_0[i, j] -> S_0[i, 1 + j] : i >= 1 and i <= 10 and "
5238 					   "j >= 1 and j <= 7;"
5239 		"S_0[i, j] -> S_0[1 + i, j] : i >= 1 and i <= 9 and "
5240 					     "j >= 1 and j <= 8 }";
5241 	P = "{ }";
5242 	S = "{ S_0[i, j] -> [i + j, i] }";
5243 	ctx->opt->schedule_algorithm = ISL_SCHEDULE_ALGORITHM_FEAUTRIER;
5244 	if (test_special_schedule(ctx, D, V, P, S) < 0)
5245 		return -1;
5246 	ctx->opt->schedule_algorithm = ISL_SCHEDULE_ALGORITHM_ISL;
5247 
5248 	/* Fig. 1 from Feautrier's "Some Efficient Solutions..." pt. 2, 1992 */
5249 	D = "[N] -> { S_0[i, j] : i >= 0 and i <= -1 + N and "
5250 				 "j >= 0 and j <= -1 + i }";
5251 	V = "[N] -> { S_0[i, j] -> S_0[i, 1 + j] : j <= -2 + i and "
5252 					"i <= -1 + N and j >= 0;"
5253 		     "S_0[i, -1 + i] -> S_0[1 + i, 0] : i >= 1 and "
5254 					"i <= -2 + N }";
5255 	P = "{ }";
5256 	S = "{ S_0[i, j] -> [i, j] }";
5257 	ctx->opt->schedule_algorithm = ISL_SCHEDULE_ALGORITHM_FEAUTRIER;
5258 	if (test_special_schedule(ctx, D, V, P, S) < 0)
5259 		return -1;
5260 	ctx->opt->schedule_algorithm = ISL_SCHEDULE_ALGORITHM_ISL;
5261 
5262 	/* Test both algorithms on a case with only proximity dependences. */
5263 	D = "{ S[i,j] : 0 <= i <= 10 }";
5264 	V = "{ }";
5265 	P = "{ S[i,j] -> S[i+1,j] : 0 <= i,j <= 10 }";
5266 	S = "{ S[i, j] -> [j, i] }";
5267 	ctx->opt->schedule_algorithm = ISL_SCHEDULE_ALGORITHM_FEAUTRIER;
5268 	if (test_special_schedule(ctx, D, V, P, S) < 0)
5269 		return -1;
5270 	ctx->opt->schedule_algorithm = ISL_SCHEDULE_ALGORITHM_ISL;
5271 	if (test_special_schedule(ctx, D, V, P, S) < 0)
5272 		return -1;
5273 
5274 	D = "{ A[a]; B[] }";
5275 	V = "{}";
5276 	P = "{ A[a] -> B[] }";
5277 	if (test_has_schedule(ctx, D, V, P) < 0)
5278 		return -1;
5279 
5280 	if (test_padded_schedule(ctx) < 0)
5281 		return -1;
5282 
5283 	/* Check that check for progress is not confused by rational
5284 	 * solution.
5285 	 */
5286 	D = "[N] -> { S0[i, j] : i >= 0 and i <= N and j >= 0 and j <= N }";
5287 	V = "[N] -> { S0[i0, -1 + N] -> S0[2 + i0, 0] : i0 >= 0 and "
5288 							"i0 <= -2 + N; "
5289 			"S0[i0, i1] -> S0[i0, 1 + i1] : i0 >= 0 and "
5290 				"i0 <= N and i1 >= 0 and i1 <= -1 + N }";
5291 	P = "{}";
5292 	ctx->opt->schedule_algorithm = ISL_SCHEDULE_ALGORITHM_FEAUTRIER;
5293 	if (test_has_schedule(ctx, D, V, P) < 0)
5294 		return -1;
5295 	ctx->opt->schedule_algorithm = ISL_SCHEDULE_ALGORITHM_ISL;
5296 
5297 	/* Check that we allow schedule rows that are only non-trivial
5298 	 * on some full-dimensional domains.
5299 	 */
5300 	D = "{ S1[j] : 0 <= j <= 1; S0[]; S2[k] : 0 <= k <= 1 }";
5301 	V = "{ S0[] -> S1[j] : 0 <= j <= 1; S2[0] -> S0[];"
5302 		"S1[j] -> S2[1] : 0 <= j <= 1 }";
5303 	P = "{}";
5304 	ctx->opt->schedule_algorithm = ISL_SCHEDULE_ALGORITHM_FEAUTRIER;
5305 	if (test_has_schedule(ctx, D, V, P) < 0)
5306 		return -1;
5307 	ctx->opt->schedule_algorithm = ISL_SCHEDULE_ALGORITHM_ISL;
5308 
5309 	if (test_conditional_schedule_constraints(ctx) < 0)
5310 		return -1;
5311 
5312 	if (test_strongly_satisfying_schedule(ctx) < 0)
5313 		return -1;
5314 
5315 	if (test_conflicting_context_schedule(ctx) < 0)
5316 		return -1;
5317 
5318 	if (test_coalescing_schedule(ctx) < 0)
5319 		return -1;
5320 	if (test_skewing_schedule(ctx) < 0)
5321 		return -1;
5322 
5323 	return 0;
5324 }
5325 
5326 /* Perform scheduling tests using the whole component scheduler.
5327  */
test_schedule_whole(isl_ctx * ctx)5328 static int test_schedule_whole(isl_ctx *ctx)
5329 {
5330 	int whole;
5331 	int r;
5332 
5333 	whole = isl_options_get_schedule_whole_component(ctx);
5334 	isl_options_set_schedule_whole_component(ctx, 1);
5335 	r = test_schedule(ctx);
5336 	isl_options_set_schedule_whole_component(ctx, whole);
5337 
5338 	return r;
5339 }
5340 
5341 /* Perform scheduling tests using the incremental scheduler.
5342  */
test_schedule_incremental(isl_ctx * ctx)5343 static int test_schedule_incremental(isl_ctx *ctx)
5344 {
5345 	int whole;
5346 	int r;
5347 
5348 	whole = isl_options_get_schedule_whole_component(ctx);
5349 	isl_options_set_schedule_whole_component(ctx, 0);
5350 	r = test_schedule(ctx);
5351 	isl_options_set_schedule_whole_component(ctx, whole);
5352 
5353 	return r;
5354 }
5355 
test_plain_injective(isl_ctx * ctx,const char * str,int injective)5356 int test_plain_injective(isl_ctx *ctx, const char *str, int injective)
5357 {
5358 	isl_union_map *umap;
5359 	int test;
5360 
5361 	umap = isl_union_map_read_from_str(ctx, str);
5362 	test = isl_union_map_plain_is_injective(umap);
5363 	isl_union_map_free(umap);
5364 	if (test < 0)
5365 		return -1;
5366 	if (test == injective)
5367 		return 0;
5368 	if (injective)
5369 		isl_die(ctx, isl_error_unknown,
5370 			"map not detected as injective", return -1);
5371 	else
5372 		isl_die(ctx, isl_error_unknown,
5373 			"map detected as injective", return -1);
5374 }
5375 
test_injective(isl_ctx * ctx)5376 int test_injective(isl_ctx *ctx)
5377 {
5378 	const char *str;
5379 
5380 	if (test_plain_injective(ctx, "{S[i,j] -> A[0]; T[i,j] -> B[1]}", 0))
5381 		return -1;
5382 	if (test_plain_injective(ctx, "{S[] -> A[0]; T[] -> B[0]}", 1))
5383 		return -1;
5384 	if (test_plain_injective(ctx, "{S[] -> A[0]; T[] -> A[1]}", 1))
5385 		return -1;
5386 	if (test_plain_injective(ctx, "{S[] -> A[0]; T[] -> A[0]}", 0))
5387 		return -1;
5388 	if (test_plain_injective(ctx, "{S[i] -> A[i,0]; T[i] -> A[i,1]}", 1))
5389 		return -1;
5390 	if (test_plain_injective(ctx, "{S[i] -> A[i]; T[i] -> A[i]}", 0))
5391 		return -1;
5392 	if (test_plain_injective(ctx, "{S[] -> A[0,0]; T[] -> A[0,1]}", 1))
5393 		return -1;
5394 	if (test_plain_injective(ctx, "{S[] -> A[0,0]; T[] -> A[1,0]}", 1))
5395 		return -1;
5396 
5397 	str = "{S[] -> A[0,0]; T[] -> A[0,1]; U[] -> A[1,0]}";
5398 	if (test_plain_injective(ctx, str, 1))
5399 		return -1;
5400 	str = "{S[] -> A[0,0]; T[] -> A[0,1]; U[] -> A[0,0]}";
5401 	if (test_plain_injective(ctx, str, 0))
5402 		return -1;
5403 
5404 	return 0;
5405 }
5406 
5407 #undef BASE
5408 #define BASE	aff
5409 #include "isl_test_plain_equal_templ.c"
5410 
5411 #undef BASE
5412 #define BASE	pw_multi_aff
5413 #include "isl_test_plain_equal_templ.c"
5414 
5415 #undef BASE
5416 #define BASE	union_pw_aff
5417 #include "isl_test_plain_equal_templ.c"
5418 
5419 /* Basic tests on isl_union_pw_aff.
5420  *
5421  * In particular, check that isl_union_pw_aff_aff_on_domain
5422  * aligns the parameters of the input objects and
5423  * that isl_union_pw_aff_param_on_domain_id properly
5424  * introduces the parameter.
5425  */
test_upa(isl_ctx * ctx)5426 static int test_upa(isl_ctx *ctx)
5427 {
5428 	const char *str;
5429 	isl_id *id;
5430 	isl_aff *aff;
5431 	isl_union_set *domain;
5432 	isl_union_pw_aff *upa;
5433 	isl_stat ok;
5434 
5435 	aff = isl_aff_read_from_str(ctx, "[N] -> { [N] }");
5436 	str = "[M] -> { A[i] : 0 <= i < M; B[] }";
5437 	domain = isl_union_set_read_from_str(ctx, str);
5438 	upa = isl_union_pw_aff_aff_on_domain(domain, aff);
5439 	str = "[N, M] -> { A[i] -> [N] : 0 <= i < M; B[] -> [N] }";
5440 	ok = union_pw_aff_check_plain_equal(upa, str);
5441 	isl_union_pw_aff_free(upa);
5442 	if (ok < 0)
5443 		return -1;
5444 
5445 	id = isl_id_alloc(ctx, "N", NULL);
5446 	str = "[M] -> { A[i] : 0 <= i < M; B[] }";
5447 	domain = isl_union_set_read_from_str(ctx, str);
5448 	upa = isl_union_pw_aff_param_on_domain_id(domain, id);
5449 	str = "[N, M] -> { A[i] -> [N] : 0 <= i < M; B[] -> [N] }";
5450 	ok = union_pw_aff_check_plain_equal(upa, str);
5451 	isl_union_pw_aff_free(upa);
5452 	if (ok < 0)
5453 		return -1;
5454 
5455 	return 0;
5456 }
5457 
5458 struct {
5459 	__isl_give isl_aff *(*fn)(__isl_take isl_aff *aff1,
5460 				__isl_take isl_aff *aff2);
5461 } aff_bin_op[] = {
5462 	['+'] = { &isl_aff_add },
5463 	['-'] = { &isl_aff_sub },
5464 	['*'] = { &isl_aff_mul },
5465 	['/'] = { &isl_aff_div },
5466 };
5467 
5468 struct {
5469 	const char *arg1;
5470 	unsigned char op;
5471 	const char *arg2;
5472 	const char *res;
5473 } aff_bin_tests[] = {
5474 	{ "{ [i] -> [i] }", '+', "{ [i] -> [i] }",
5475 	  "{ [i] -> [2i] }" },
5476 	{ "{ [i] -> [i] }", '-', "{ [i] -> [i] }",
5477 	  "{ [i] -> [0] }" },
5478 	{ "{ [i] -> [i] }", '*', "{ [i] -> [2] }",
5479 	  "{ [i] -> [2i] }" },
5480 	{ "{ [i] -> [2] }", '*', "{ [i] -> [i] }",
5481 	  "{ [i] -> [2i] }" },
5482 	{ "{ [i] -> [i] }", '/', "{ [i] -> [2] }",
5483 	  "{ [i] -> [i/2] }" },
5484 	{ "{ [i] -> [2i] }", '/', "{ [i] -> [2] }",
5485 	  "{ [i] -> [i] }" },
5486 	{ "{ [i] -> [i] }", '+', "{ [i] -> [NaN] }",
5487 	  "{ [i] -> [NaN] }" },
5488 	{ "{ [i] -> [i] }", '-', "{ [i] -> [NaN] }",
5489 	  "{ [i] -> [NaN] }" },
5490 	{ "{ [i] -> [i] }", '*', "{ [i] -> [NaN] }",
5491 	  "{ [i] -> [NaN] }" },
5492 	{ "{ [i] -> [2] }", '*', "{ [i] -> [NaN] }",
5493 	  "{ [i] -> [NaN] }" },
5494 	{ "{ [i] -> [i] }", '/', "{ [i] -> [NaN] }",
5495 	  "{ [i] -> [NaN] }" },
5496 	{ "{ [i] -> [2] }", '/', "{ [i] -> [NaN] }",
5497 	  "{ [i] -> [NaN] }" },
5498 	{ "{ [i] -> [NaN] }", '+', "{ [i] -> [i] }",
5499 	  "{ [i] -> [NaN] }" },
5500 	{ "{ [i] -> [NaN] }", '-', "{ [i] -> [i] }",
5501 	  "{ [i] -> [NaN] }" },
5502 	{ "{ [i] -> [NaN] }", '*', "{ [i] -> [2] }",
5503 	  "{ [i] -> [NaN] }" },
5504 	{ "{ [i] -> [NaN] }", '*', "{ [i] -> [i] }",
5505 	  "{ [i] -> [NaN] }" },
5506 	{ "{ [i] -> [NaN] }", '/', "{ [i] -> [2] }",
5507 	  "{ [i] -> [NaN] }" },
5508 	{ "{ [i] -> [NaN] }", '/', "{ [i] -> [i] }",
5509 	  "{ [i] -> [NaN] }" },
5510 	{ "{ [i] -> [i] }", '/', "{ [i] -> [0] }",
5511 	  "{ [i] -> [NaN] }" },
5512 };
5513 
5514 /* Perform some basic tests of binary operations on isl_aff objects.
5515  */
test_bin_aff(isl_ctx * ctx)5516 static int test_bin_aff(isl_ctx *ctx)
5517 {
5518 	int i;
5519 	isl_aff *aff1, *aff2, *res;
5520 	__isl_give isl_aff *(*fn)(__isl_take isl_aff *aff1,
5521 				__isl_take isl_aff *aff2);
5522 	int ok;
5523 
5524 	for (i = 0; i < ARRAY_SIZE(aff_bin_tests); ++i) {
5525 		aff1 = isl_aff_read_from_str(ctx, aff_bin_tests[i].arg1);
5526 		aff2 = isl_aff_read_from_str(ctx, aff_bin_tests[i].arg2);
5527 		res = isl_aff_read_from_str(ctx, aff_bin_tests[i].res);
5528 		fn = aff_bin_op[aff_bin_tests[i].op].fn;
5529 		aff1 = fn(aff1, aff2);
5530 		if (isl_aff_is_nan(res))
5531 			ok = isl_aff_is_nan(aff1);
5532 		else
5533 			ok = isl_aff_plain_is_equal(aff1, res);
5534 		isl_aff_free(aff1);
5535 		isl_aff_free(res);
5536 		if (ok < 0)
5537 			return -1;
5538 		if (!ok)
5539 			isl_die(ctx, isl_error_unknown,
5540 				"unexpected result", return -1);
5541 	}
5542 
5543 	return 0;
5544 }
5545 
5546 struct {
5547 	__isl_give isl_pw_aff *(*fn)(__isl_take isl_pw_aff *pa1,
5548 				     __isl_take isl_pw_aff *pa2);
5549 } pw_aff_bin_op[] = {
5550 	['m'] = { &isl_pw_aff_min },
5551 	['M'] = { &isl_pw_aff_max },
5552 };
5553 
5554 /* Inputs for binary isl_pw_aff operation tests.
5555  * "arg1" and "arg2" are the two arguments, "op" identifies the operation
5556  * defined by pw_aff_bin_op, and "res" is the expected result.
5557  */
5558 struct {
5559 	const char *arg1;
5560 	unsigned char op;
5561 	const char *arg2;
5562 	const char *res;
5563 } pw_aff_bin_tests[] = {
5564 	{ "{ [i] -> [i] }", 'm', "{ [i] -> [i] }",
5565 	  "{ [i] -> [i] }" },
5566 	{ "{ [i] -> [i] }", 'M', "{ [i] -> [i] }",
5567 	  "{ [i] -> [i] }" },
5568 	{ "{ [i] -> [i] }", 'm', "{ [i] -> [0] }",
5569 	  "{ [i] -> [i] : i <= 0; [i] -> [0] : i > 0 }" },
5570 	{ "{ [i] -> [i] }", 'M', "{ [i] -> [0] }",
5571 	  "{ [i] -> [i] : i >= 0; [i] -> [0] : i < 0 }" },
5572 	{ "{ [i] -> [i] }", 'm', "{ [i] -> [NaN] }",
5573 	  "{ [i] -> [NaN] }" },
5574 	{ "{ [i] -> [NaN] }", 'm', "{ [i] -> [i] }",
5575 	  "{ [i] -> [NaN] }" },
5576 };
5577 
5578 /* Perform some basic tests of binary operations on isl_pw_aff objects.
5579  */
test_bin_pw_aff(isl_ctx * ctx)5580 static int test_bin_pw_aff(isl_ctx *ctx)
5581 {
5582 	int i;
5583 	isl_bool ok;
5584 	isl_pw_aff *pa1, *pa2, *res;
5585 
5586 	for (i = 0; i < ARRAY_SIZE(pw_aff_bin_tests); ++i) {
5587 		pa1 = isl_pw_aff_read_from_str(ctx, pw_aff_bin_tests[i].arg1);
5588 		pa2 = isl_pw_aff_read_from_str(ctx, pw_aff_bin_tests[i].arg2);
5589 		res = isl_pw_aff_read_from_str(ctx, pw_aff_bin_tests[i].res);
5590 		pa1 = pw_aff_bin_op[pw_aff_bin_tests[i].op].fn(pa1, pa2);
5591 		if (isl_pw_aff_involves_nan(res))
5592 			ok = isl_pw_aff_involves_nan(pa1);
5593 		else
5594 			ok = isl_pw_aff_plain_is_equal(pa1, res);
5595 		isl_pw_aff_free(pa1);
5596 		isl_pw_aff_free(res);
5597 		if (ok < 0)
5598 			return -1;
5599 		if (!ok)
5600 			isl_die(ctx, isl_error_unknown,
5601 				"unexpected result", return -1);
5602 	}
5603 
5604 	return 0;
5605 }
5606 
5607 /* Inputs for basic tests of test operations on
5608  * isl_union_pw_multi_aff objects.
5609  * "fn" is the function that is being tested.
5610  * "arg" is a string description of the input.
5611  * "res" is the expected result.
5612  */
5613 static struct {
5614 	isl_bool (*fn)(__isl_keep isl_union_pw_multi_aff *upma1);
5615 	const char *arg;
5616 	isl_bool res;
5617 } upma_test_tests[] = {
5618 	{ &isl_union_pw_multi_aff_involves_nan, "{ A[] -> [0]; B[0] -> [1] }",
5619 	  isl_bool_false },
5620 	{ &isl_union_pw_multi_aff_involves_nan, "{ A[] -> [NaN]; B[0] -> [1] }",
5621 	  isl_bool_true },
5622 	{ &isl_union_pw_multi_aff_involves_nan, "{ A[] -> [0]; B[0] -> [NaN] }",
5623 	  isl_bool_true },
5624 	{ &isl_union_pw_multi_aff_involves_nan,
5625 	  "{ A[] -> [0]; B[0] -> [1, NaN, 5] }",
5626 	  isl_bool_true },
5627 	{ &isl_union_pw_multi_aff_involves_locals,
5628 	  "{ A[] -> [0]; B[0] -> [1] }",
5629 	  isl_bool_false },
5630 	{ &isl_union_pw_multi_aff_involves_locals,
5631 	  "{ A[] -> [0]; B[x] -> [1] : x mod 2 = 0 }",
5632 	  isl_bool_true },
5633 	{ &isl_union_pw_multi_aff_involves_locals,
5634 	  "{ A[] -> [0]; B[x] -> [x // 2] }",
5635 	  isl_bool_true },
5636 	{ &isl_union_pw_multi_aff_involves_locals,
5637 	  "{ A[i] -> [i // 2]; B[0] -> [1] }",
5638 	  isl_bool_true },
5639 };
5640 
5641 /* Perform some basic tests of test operations on
5642  * isl_union_pw_multi_aff objects.
5643  */
test_upma_test(isl_ctx * ctx)5644 static isl_stat test_upma_test(isl_ctx *ctx)
5645 {
5646 	int i;
5647 	isl_union_pw_multi_aff *upma;
5648 	isl_bool res;
5649 
5650 	for (i = 0; i < ARRAY_SIZE(upma_test_tests); ++i) {
5651 		const char *str;
5652 
5653 		str = upma_test_tests[i].arg;
5654 		upma = isl_union_pw_multi_aff_read_from_str(ctx, str);
5655 		res = upma_test_tests[i].fn(upma);
5656 		isl_union_pw_multi_aff_free(upma);
5657 		if (res < 0)
5658 			return isl_stat_error;
5659 		if (res != upma_test_tests[i].res)
5660 			isl_die(ctx, isl_error_unknown,
5661 				"unexpected result", return isl_stat_error);
5662 	}
5663 
5664 	return isl_stat_ok;
5665 }
5666 
5667 struct {
5668 	__isl_give isl_union_pw_multi_aff *(*fn)(
5669 		__isl_take isl_union_pw_multi_aff *upma1,
5670 		__isl_take isl_union_pw_multi_aff *upma2);
5671 	const char *arg1;
5672 	const char *arg2;
5673 	const char *res;
5674 } upma_bin_tests[] = {
5675 	{ &isl_union_pw_multi_aff_add, "{ A[] -> [0]; B[0] -> [1] }",
5676 	  "{ B[x] -> [2] : x >= 0 }", "{ B[0] -> [3] }" },
5677 	{ &isl_union_pw_multi_aff_union_add, "{ A[] -> [0]; B[0] -> [1] }",
5678 	  "{ B[x] -> [2] : x >= 0 }",
5679 	  "{ A[] -> [0]; B[0] -> [3]; B[x] -> [2] : x >= 1 }" },
5680 	{ &isl_union_pw_multi_aff_pullback_union_pw_multi_aff,
5681 	  "{ A[] -> B[0]; C[x] -> B[1] : x < 10; C[y] -> B[2] : y >= 10 }",
5682 	  "{ D[i] -> A[] : i < 0; D[i] -> C[i + 5] : i >= 0 }",
5683 	  "{ D[i] -> B[0] : i < 0; D[i] -> B[1] : 0 <= i < 5; "
5684 	    "D[i] -> B[2] : i >= 5 }" },
5685 	{ &isl_union_pw_multi_aff_union_add, "{ B[x] -> A[1] : x <= 0 }",
5686 	  "{ B[x] -> C[2] : x > 0 }",
5687 	  "{ B[x] -> A[1] : x <= 0; B[x] -> C[2] : x > 0 }" },
5688 	{ &isl_union_pw_multi_aff_union_add, "{ B[x] -> A[1] : x <= 0 }",
5689 	  "{ B[x] -> A[2] : x >= 0 }",
5690 	  "{ B[x] -> A[1] : x < 0; B[x] -> A[2] : x > 0; B[0] -> A[3] }" },
5691 	{
5692   &isl_union_pw_multi_aff_preimage_domain_wrapped_domain_union_pw_multi_aff,
5693 	  "{ B[x] -> C[x + 2] }",
5694 	  "{ D[y] -> B[2y] }",
5695 	  "{ }" },
5696 	{
5697   &isl_union_pw_multi_aff_preimage_domain_wrapped_domain_union_pw_multi_aff,
5698 	  "{ [A[x] -> B[x + 1]] -> C[x + 2] }",
5699 	  "{ D[y] -> B[2y] }",
5700 	  "{ }" },
5701 	{
5702   &isl_union_pw_multi_aff_preimage_domain_wrapped_domain_union_pw_multi_aff,
5703 	  "{ [A[x] -> B[x + 1]] -> C[x + 2]; B[x] -> C[x + 2] }",
5704 	  "{ D[y] -> A[2y] }",
5705 	  "{ [D[y] -> B[2y + 1]] -> C[2y + 2] }" },
5706 	{
5707   &isl_union_pw_multi_aff_preimage_domain_wrapped_domain_union_pw_multi_aff,
5708 	  "{ T[A[x] -> B[x + 1]] -> C[x + 2]; B[x] -> C[x + 2] }",
5709 	  "{ D[y] -> A[2y] }",
5710 	  "{ T[D[y] -> B[2y + 1]] -> C[2y + 2] }" },
5711 };
5712 
5713 /* Perform some basic tests of binary operations on
5714  * isl_union_pw_multi_aff objects.
5715  */
test_bin_upma(isl_ctx * ctx)5716 static int test_bin_upma(isl_ctx *ctx)
5717 {
5718 	int i;
5719 	isl_union_pw_multi_aff *upma1, *upma2, *res;
5720 	int ok;
5721 
5722 	for (i = 0; i < ARRAY_SIZE(upma_bin_tests); ++i) {
5723 		upma1 = isl_union_pw_multi_aff_read_from_str(ctx,
5724 							upma_bin_tests[i].arg1);
5725 		upma2 = isl_union_pw_multi_aff_read_from_str(ctx,
5726 							upma_bin_tests[i].arg2);
5727 		res = isl_union_pw_multi_aff_read_from_str(ctx,
5728 							upma_bin_tests[i].res);
5729 		upma1 = upma_bin_tests[i].fn(upma1, upma2);
5730 		ok = isl_union_pw_multi_aff_plain_is_equal(upma1, res);
5731 		isl_union_pw_multi_aff_free(upma1);
5732 		isl_union_pw_multi_aff_free(res);
5733 		if (ok < 0)
5734 			return -1;
5735 		if (!ok)
5736 			isl_die(ctx, isl_error_unknown,
5737 				"unexpected result", return -1);
5738 	}
5739 
5740 	return 0;
5741 }
5742 
5743 struct {
5744 	__isl_give isl_union_pw_multi_aff *(*fn)(
5745 		__isl_take isl_union_pw_multi_aff *upma1,
5746 		__isl_take isl_union_pw_multi_aff *upma2);
5747 	const char *arg1;
5748 	const char *arg2;
5749 } upma_bin_fail_tests[] = {
5750 	{ &isl_union_pw_multi_aff_union_add, "{ B[x] -> A[1] : x <= 0 }",
5751 	  "{ B[x] -> C[2] : x >= 0 }" },
5752 };
5753 
5754 /* Perform some basic tests of binary operations on
5755  * isl_union_pw_multi_aff objects that are expected to fail.
5756  */
test_bin_upma_fail(isl_ctx * ctx)5757 static int test_bin_upma_fail(isl_ctx *ctx)
5758 {
5759 	int i, n;
5760 	isl_union_pw_multi_aff *upma1, *upma2;
5761 	int on_error;
5762 
5763 	on_error = isl_options_get_on_error(ctx);
5764 	isl_options_set_on_error(ctx, ISL_ON_ERROR_CONTINUE);
5765 	n = ARRAY_SIZE(upma_bin_fail_tests);
5766 	for (i = 0; i < n; ++i) {
5767 		upma1 = isl_union_pw_multi_aff_read_from_str(ctx,
5768 						upma_bin_fail_tests[i].arg1);
5769 		upma2 = isl_union_pw_multi_aff_read_from_str(ctx,
5770 						upma_bin_fail_tests[i].arg2);
5771 		upma1 = upma_bin_fail_tests[i].fn(upma1, upma2);
5772 		isl_union_pw_multi_aff_free(upma1);
5773 		if (upma1)
5774 			break;
5775 	}
5776 	isl_options_set_on_error(ctx, on_error);
5777 	if (i < n)
5778 		isl_die(ctx, isl_error_unknown,
5779 			"operation not expected to succeed", return -1);
5780 
5781 	return 0;
5782 }
5783 
5784 /* Inputs for basic tests of binary operations on
5785  * pairs of isl_union_pw_multi_aff and isl_union_set objects.
5786  * "fn" is the function that is being tested.
5787  * "arg1" and "arg2" are string descriptions of the inputs.
5788  * "res" is a string description of the expected result.
5789  */
5790 struct {
5791 	__isl_give isl_union_pw_multi_aff *(*fn)(
5792 		__isl_take isl_union_pw_multi_aff *upma,
5793 		__isl_take isl_union_set *uset);
5794 	const char *arg1;
5795 	const char *arg2;
5796 	const char *res;
5797 } upma_uset_tests[] = {
5798 	{ &isl_union_pw_multi_aff_intersect_domain_wrapped_range,
5799 	  "{ A[i] -> B[i] }", "{ B[0] }",
5800 	  "{ }" },
5801 	{ &isl_union_pw_multi_aff_intersect_domain_wrapped_domain,
5802 	  "{ [A[i] -> B[i]] -> C[i + 1] }", "{ A[1]; B[0] }",
5803 	  "{ [A[1] -> B[1]] -> C[2] }" },
5804 	{ &isl_union_pw_multi_aff_intersect_domain_wrapped_range,
5805 	  "{ [A[i] -> B[i]] -> C[i + 1] }", "{ A[1]; B[0] }",
5806 	  "{ [A[0] -> B[0]] -> C[1] }" },
5807 	{ &isl_union_pw_multi_aff_intersect_domain_wrapped_range,
5808 	  "{ [A[i] -> B[i]] -> C[i + 1] }", "[N] -> { B[N] }",
5809 	  "[N] -> { [A[N] -> B[N]] -> C[N + 1] }" },
5810 	{ &isl_union_pw_multi_aff_intersect_domain_wrapped_range,
5811 	  "[M] -> { [A[M] -> B[M]] -> C[M + 1] }", "[N] -> { B[N] }",
5812 	  "[N, M] -> { [A[N] -> B[N]] -> C[N + 1] : N = M }" },
5813 	{ &isl_union_pw_multi_aff_intersect_domain_wrapped_range,
5814 	  "{ [A[] -> B[]] -> C[]; N[A[] -> B[]] -> D[]; [B[] -> A[]] -> E[] }",
5815 	  "{ B[] }",
5816 	  "{ [A[] -> B[]] -> C[]; N[A[] -> B[]] -> D[] }" },
5817 };
5818 
5819 /* Perform some basic tests of binary operations on
5820  * pairs of isl_union_pw_multi_aff and isl_union_set objects.
5821  */
test_upma_uset(isl_ctx * ctx)5822 static isl_stat test_upma_uset(isl_ctx *ctx)
5823 {
5824 	int i;
5825 	isl_bool ok;
5826 	isl_union_pw_multi_aff *upma, *res;
5827 	isl_union_set *uset;
5828 
5829 	for (i = 0; i < ARRAY_SIZE(upma_uset_tests); ++i) {
5830 		upma = isl_union_pw_multi_aff_read_from_str(ctx,
5831 						    upma_uset_tests[i].arg1);
5832 		uset = isl_union_set_read_from_str(ctx,
5833 						    upma_uset_tests[i].arg2);
5834 		res = isl_union_pw_multi_aff_read_from_str(ctx,
5835 						    upma_uset_tests[i].res);
5836 		upma = upma_uset_tests[i].fn(upma, uset);
5837 		ok = isl_union_pw_multi_aff_plain_is_equal(upma, res);
5838 		isl_union_pw_multi_aff_free(upma);
5839 		isl_union_pw_multi_aff_free(res);
5840 		if (ok < 0)
5841 			return isl_stat_error;
5842 		if (!ok)
5843 			isl_die(ctx, isl_error_unknown,
5844 				"unexpected result", return isl_stat_error);
5845 	}
5846 
5847 	return isl_stat_ok;
5848 }
5849 
5850 /* Inputs for basic tests of unary operations on isl_multi_pw_aff objects.
5851  * "fn" is the function that is tested.
5852  * "arg" is a string description of the input.
5853  * "res" is a string description of the expected result.
5854  */
5855 struct {
5856 	__isl_give isl_multi_pw_aff *(*fn)(__isl_take isl_multi_pw_aff *mpa);
5857 	const char *arg;
5858 	const char *res;
5859 } mpa_un_tests[] = {
5860 	{ &isl_multi_pw_aff_range_factor_domain,
5861 	  "{ A[x] -> [B[(1 : x >= 5)] -> C[(2 : x <= 10)]] }",
5862 	  "{ A[x] -> B[(1 : x >= 5)] }" },
5863 	{ &isl_multi_pw_aff_range_factor_range,
5864 	  "{ A[x] -> [B[(1 : x >= 5)] -> C[(2 : x <= 10)]] }",
5865 	  "{ A[y] -> C[(2 : y <= 10)] }" },
5866 	{ &isl_multi_pw_aff_range_factor_domain,
5867 	  "{ A[x] -> [B[(1 : x >= 5)] -> C[]] }",
5868 	  "{ A[x] -> B[(1 : x >= 5)] }" },
5869 	{ &isl_multi_pw_aff_range_factor_range,
5870 	  "{ A[x] -> [B[(1 : x >= 5)] -> C[]] }",
5871 	  "{ A[y] -> C[] }" },
5872 	{ &isl_multi_pw_aff_range_factor_domain,
5873 	  "{ A[x] -> [B[] -> C[(2 : x <= 10)]] }",
5874 	  "{ A[x] -> B[] }" },
5875 	{ &isl_multi_pw_aff_range_factor_range,
5876 	  "{ A[x] -> [B[] -> C[(2 : x <= 10)]] }",
5877 	  "{ A[y] -> C[(2 : y <= 10)] }" },
5878 	{ &isl_multi_pw_aff_range_factor_domain,
5879 	  "{ A[x] -> [B[] -> C[]] }",
5880 	  "{ A[x] -> B[] }" },
5881 	{ &isl_multi_pw_aff_range_factor_range,
5882 	  "{ A[x] -> [B[] -> C[]] }",
5883 	  "{ A[y] -> C[] }" },
5884 	{ &isl_multi_pw_aff_factor_range,
5885 	  "{ [B[] -> C[]] }",
5886 	  "{ C[] }" },
5887 	{ &isl_multi_pw_aff_range_factor_domain,
5888 	  "{ A[x] -> [B[] -> C[]] : x >= 0 }",
5889 	  "{ A[x] -> B[] : x >= 0 }" },
5890 	{ &isl_multi_pw_aff_range_factor_range,
5891 	  "{ A[x] -> [B[] -> C[]] : x >= 0 }",
5892 	  "{ A[y] -> C[] : y >= 0 }" },
5893 	{ &isl_multi_pw_aff_factor_range,
5894 	  "[N] -> { [B[] -> C[]] : N >= 0 }",
5895 	  "[N] -> { C[] : N >= 0 }" },
5896 };
5897 
5898 /* Perform some basic tests of unary operations on isl_multi_pw_aff objects.
5899  */
test_un_mpa(isl_ctx * ctx)5900 static int test_un_mpa(isl_ctx *ctx)
5901 {
5902 	int i;
5903 	isl_bool ok;
5904 	isl_multi_pw_aff *mpa, *res;
5905 
5906 	for (i = 0; i < ARRAY_SIZE(mpa_un_tests); ++i) {
5907 		mpa = isl_multi_pw_aff_read_from_str(ctx, mpa_un_tests[i].arg);
5908 		res = isl_multi_pw_aff_read_from_str(ctx, mpa_un_tests[i].res);
5909 		mpa = mpa_un_tests[i].fn(mpa);
5910 		ok = isl_multi_pw_aff_plain_is_equal(mpa, res);
5911 		isl_multi_pw_aff_free(mpa);
5912 		isl_multi_pw_aff_free(res);
5913 		if (ok < 0)
5914 			return -1;
5915 		if (!ok)
5916 			isl_die(ctx, isl_error_unknown,
5917 				"unexpected result", return -1);
5918 	}
5919 
5920 	return 0;
5921 }
5922 
5923 /* Inputs for basic tests of binary operations on isl_multi_pw_aff objects.
5924  * "fn" is the function that is tested.
5925  * "arg1" and "arg2" are string descriptions of the inputs.
5926  * "res" is a string description of the expected result.
5927  */
5928 struct {
5929 	__isl_give isl_multi_pw_aff *(*fn)(
5930 		__isl_take isl_multi_pw_aff *mpa1,
5931 		__isl_take isl_multi_pw_aff *mpa2);
5932 	const char *arg1;
5933 	const char *arg2;
5934 	const char *res;
5935 } mpa_bin_tests[] = {
5936 	{ &isl_multi_pw_aff_add, "{ A[] -> [1] }", "{ A[] -> [2] }",
5937 	  "{ A[] -> [3] }" },
5938 	{ &isl_multi_pw_aff_add, "{ A[x] -> [(1 : x >= 5)] }",
5939 	  "{ A[x] -> [(x : x <= 10)] }",
5940 	  "{ A[x] -> [(1 + x : 5 <= x <= 10)] }" },
5941 	{ &isl_multi_pw_aff_add, "{ A[x] -> [] : x >= 5 }",
5942 	  "{ A[x] -> [] : x <= 10 }",
5943 	  "{ A[x] -> [] : 5 <= x <= 10 }" },
5944 	{ &isl_multi_pw_aff_add, "{ A[x] -> [] : x >= 5 }",
5945 	  "[N] -> { A[x] -> [] : x <= N }",
5946 	  "[N] -> { A[x] -> [] : 5 <= x <= N }" },
5947 	{ &isl_multi_pw_aff_add,
5948 	  "[N] -> { A[x] -> [] : x <= N }",
5949 	  "{ A[x] -> [] : x >= 5 }",
5950 	  "[N] -> { A[x] -> [] : 5 <= x <= N }" },
5951 	{ &isl_multi_pw_aff_range_product, "{ A[x] -> B[(1 : x >= 5)] }",
5952 	  "{ A[y] -> C[(2 : y <= 10)] }",
5953 	  "{ A[x] -> [B[(1 : x >= 5)] -> C[(2 : x <= 10)]] }" },
5954 	{ &isl_multi_pw_aff_range_product, "{ A[x] -> B[1] : x >= 5 }",
5955 	  "{ A[y] -> C[2] : y <= 10 }",
5956 	  "{ A[x] -> [B[(1 : x >= 5)] -> C[(2 : x <= 10)]] }" },
5957 	{ &isl_multi_pw_aff_range_product, "{ A[x] -> B[1] : x >= 5 }",
5958 	  "[N] -> { A[y] -> C[2] : y <= N }",
5959 	  "[N] -> { A[x] -> [B[(1 : x >= 5)] -> C[(2 : x <= N)]] }" },
5960 	{ &isl_multi_pw_aff_range_product, "[N] -> { A[x] -> B[1] : x >= N }",
5961 	  "{ A[y] -> C[2] : y <= 10 }",
5962 	  "[N] -> { A[x] -> [B[(1 : x >= N)] -> C[(2 : x <= 10)]] }" },
5963 	{ &isl_multi_pw_aff_range_product, "{ A[] -> B[1] }", "{ A[] -> C[2] }",
5964 	  "{ A[] -> [B[1] -> C[2]] }" },
5965 	{ &isl_multi_pw_aff_range_product, "{ A[] -> B[] }", "{ A[] -> C[] }",
5966 	  "{ A[] -> [B[] -> C[]] }" },
5967 	{ &isl_multi_pw_aff_range_product, "{ A[x] -> B[(1 : x >= 5)] }",
5968 	  "{ A[y] -> C[] : y <= 10 }",
5969 	  "{ A[x] -> [B[(1 : x >= 5)] -> C[]] : x <= 10 }" },
5970 	{ &isl_multi_pw_aff_range_product, "{ A[y] -> C[] : y <= 10 }",
5971 	  "{ A[x] -> B[(1 : x >= 5)] }",
5972 	  "{ A[x] -> [C[] -> B[(1 : x >= 5)]] : x <= 10 }" },
5973 	{ &isl_multi_pw_aff_product, "{ A[x] -> B[(1 : x >= 5)] }",
5974 	  "{ A[y] -> C[(2 : y <= 10)] }",
5975 	  "{ [A[x] -> A[y]] -> [B[(1 : x >= 5)] -> C[(2 : y <= 10)]] }" },
5976 	{ &isl_multi_pw_aff_product, "{ A[x] -> B[(1 : x >= 5)] }",
5977 	  "{ A[y] -> C[] : y <= 10 }",
5978 	  "{ [A[x] -> A[y]] -> [B[(1 : x >= 5)] -> C[]] : y <= 10 }" },
5979 	{ &isl_multi_pw_aff_product, "{ A[y] -> C[] : y <= 10 }",
5980 	  "{ A[x] -> B[(1 : x >= 5)] }",
5981 	  "{ [A[y] -> A[x]] -> [C[] -> B[(1 : x >= 5)]] : y <= 10 }" },
5982 	{ &isl_multi_pw_aff_product, "{ A[x] -> B[(1 : x >= 5)] }",
5983 	  "[N] -> { A[y] -> C[] : y <= N }",
5984 	  "[N] -> { [A[x] -> A[y]] -> [B[(1 : x >= 5)] -> C[]] : y <= N }" },
5985 	{ &isl_multi_pw_aff_product, "[N] -> { A[y] -> C[] : y <= N }",
5986 	  "{ A[x] -> B[(1 : x >= 5)] }",
5987 	  "[N] -> { [A[y] -> A[x]] -> [C[] -> B[(1 : x >= 5)]] : y <= N }" },
5988 	{ &isl_multi_pw_aff_product, "{ A[x] -> B[] : x >= 5 }",
5989 	  "{ A[y] -> C[] : y <= 10 }",
5990 	  "{ [A[x] -> A[y]] -> [B[] -> C[]] : x >= 5 and y <= 10 }" },
5991 	{ &isl_multi_pw_aff_product, "{ A[] -> B[1] }", "{ A[] -> C[2] }",
5992 	  "{ [A[] -> A[]] -> [B[1] -> C[2]] }" },
5993 	{ &isl_multi_pw_aff_product, "{ A[] -> B[] }", "{ A[] -> C[] }",
5994 	  "{ [A[] -> A[]] -> [B[] -> C[]] }" },
5995 	{ &isl_multi_pw_aff_pullback_multi_pw_aff,
5996 	  "{ B[i,j] -> C[i + 2j] }", "{ A[a,b] -> B[b,a] }",
5997 	  "{ A[a,b] -> C[b + 2a] }" },
5998 	{ &isl_multi_pw_aff_pullback_multi_pw_aff,
5999 	  "{ B[i,j] -> C[i + 2j] }",
6000 	  "{ A[a,b] -> B[(b : b > a),(a : b > a)] }",
6001 	  "{ A[a,b] -> C[(b + 2a : b > a)] }" },
6002 	{ &isl_multi_pw_aff_pullback_multi_pw_aff,
6003 	  "{ B[i,j] -> C[(i + 2j : j > 4)] }",
6004 	  "{ A[a,b] -> B[(b : b > a),(a : b > a)] }",
6005 	  "{ A[a,b] -> C[(b + 2a : b > a > 4)] }" },
6006 	{ &isl_multi_pw_aff_pullback_multi_pw_aff,
6007 	  "{ B[i,j] -> C[] }",
6008 	  "{ A[a,b] -> B[(b : b > a),(a : b > a)] }",
6009 	  "{ A[a,b] -> C[] }" },
6010 	{ &isl_multi_pw_aff_pullback_multi_pw_aff,
6011 	  "{ B[i,j] -> C[] : i > j }",
6012 	  "{ A[a,b] -> B[b,a] }",
6013 	  "{ A[a,b] -> C[] : b > a }" },
6014 	{ &isl_multi_pw_aff_pullback_multi_pw_aff,
6015 	  "{ B[i,j] -> C[] : j > 5 }",
6016 	  "{ A[a,b] -> B[(b : b > a),(a : b > a)] }",
6017 	  "{ A[a,b] -> C[] : b > a > 5 }" },
6018 	{ &isl_multi_pw_aff_pullback_multi_pw_aff,
6019 	  "[N] -> { B[i,j] -> C[] : j > N }",
6020 	  "{ A[a,b] -> B[(b : b > a),(a : b > a)] }",
6021 	  "[N] -> { A[a,b] -> C[] : b > a > N }" },
6022 	{ &isl_multi_pw_aff_pullback_multi_pw_aff,
6023 	  "[M,N] -> { B[] -> C[] : N > 5 }",
6024 	  "[M,N] -> { A[] -> B[] : M > N }",
6025 	  "[M,N] -> { A[] -> C[] : M > N > 5 }" },
6026 };
6027 
6028 /* Perform some basic tests of binary operations on isl_multi_pw_aff objects.
6029  */
test_bin_mpa(isl_ctx * ctx)6030 static int test_bin_mpa(isl_ctx *ctx)
6031 {
6032 	int i;
6033 	isl_bool ok;
6034 	isl_multi_pw_aff *mpa1, *mpa2, *res;
6035 
6036 	for (i = 0; i < ARRAY_SIZE(mpa_bin_tests); ++i) {
6037 		mpa1 = isl_multi_pw_aff_read_from_str(ctx,
6038 							mpa_bin_tests[i].arg1);
6039 		mpa2 = isl_multi_pw_aff_read_from_str(ctx,
6040 							mpa_bin_tests[i].arg2);
6041 		res = isl_multi_pw_aff_read_from_str(ctx,
6042 							mpa_bin_tests[i].res);
6043 		mpa1 = mpa_bin_tests[i].fn(mpa1, mpa2);
6044 		ok = isl_multi_pw_aff_plain_is_equal(mpa1, res);
6045 		isl_multi_pw_aff_free(mpa1);
6046 		isl_multi_pw_aff_free(res);
6047 		if (ok < 0)
6048 			return -1;
6049 		if (!ok)
6050 			isl_die(ctx, isl_error_unknown,
6051 				"unexpected result", return -1);
6052 	}
6053 
6054 	return 0;
6055 }
6056 
6057 /* Inputs for basic tests of unary operations on
6058  * isl_multi_union_pw_aff objects.
6059  * "fn" is the function that is tested.
6060  * "arg" is a string description of the input.
6061  * "res" is a string description of the expected result.
6062  */
6063 struct {
6064 	__isl_give isl_multi_union_pw_aff *(*fn)(
6065 		__isl_take isl_multi_union_pw_aff *mupa);
6066 	const char *arg;
6067 	const char *res;
6068 } mupa_un_tests[] = {
6069 	{ &isl_multi_union_pw_aff_factor_range,
6070 	  "[B[{ A[] -> [1] }] -> C[{ A[] -> [2] }]]",
6071 	  "C[{ A[] -> [2] }]" },
6072 	{ &isl_multi_union_pw_aff_factor_range,
6073 	  "[B[] -> C[{ A[] -> [2] }]]",
6074 	  "C[{ A[] -> [2] }]" },
6075 	{ &isl_multi_union_pw_aff_factor_range,
6076 	  "[B[{ A[] -> [1] }] -> C[]]",
6077 	  "C[]" },
6078 	{ &isl_multi_union_pw_aff_factor_range,
6079 	  "[B[] -> C[]]",
6080 	  "C[]" },
6081 	{ &isl_multi_union_pw_aff_factor_range,
6082 	  "([B[] -> C[]] : { A[x] : x >= 0 })",
6083 	  "(C[] : { A[x] : x >= 0 })" },
6084 	{ &isl_multi_union_pw_aff_factor_range,
6085 	  "[N] -> ([B[] -> C[]] : { A[x] : x <= N })",
6086 	  "[N] -> (C[] : { A[x] : x <= N })" },
6087 	{ &isl_multi_union_pw_aff_factor_range,
6088 	  "[N] -> ([B[] -> C[]] : { : N >= 0 })",
6089 	  "[N] -> (C[] : { : N >= 0 })" },
6090 };
6091 
6092 /* Perform some basic tests of unary operations on
6093  * isl_multi_union_pw_aff objects.
6094  */
test_un_mupa(isl_ctx * ctx)6095 static int test_un_mupa(isl_ctx *ctx)
6096 {
6097 	int i;
6098 	isl_bool ok;
6099 	isl_multi_union_pw_aff *mupa, *res;
6100 
6101 	for (i = 0; i < ARRAY_SIZE(mupa_un_tests); ++i) {
6102 		mupa = isl_multi_union_pw_aff_read_from_str(ctx,
6103 							mupa_un_tests[i].arg);
6104 		res = isl_multi_union_pw_aff_read_from_str(ctx,
6105 							mupa_un_tests[i].res);
6106 		mupa = mupa_un_tests[i].fn(mupa);
6107 		ok = isl_multi_union_pw_aff_plain_is_equal(mupa, res);
6108 		isl_multi_union_pw_aff_free(mupa);
6109 		isl_multi_union_pw_aff_free(res);
6110 		if (ok < 0)
6111 			return -1;
6112 		if (!ok)
6113 			isl_die(ctx, isl_error_unknown,
6114 				"unexpected result", return -1);
6115 	}
6116 
6117 	return 0;
6118 }
6119 
6120 /* Inputs for basic tests of binary operations on
6121  * isl_multi_union_pw_aff objects.
6122  * "fn" is the function that is tested.
6123  * "arg1" and "arg2" are string descriptions of the inputs.
6124  * "res" is a string description of the expected result.
6125  */
6126 struct {
6127 	__isl_give isl_multi_union_pw_aff *(*fn)(
6128 		__isl_take isl_multi_union_pw_aff *mupa1,
6129 		__isl_take isl_multi_union_pw_aff *mupa2);
6130 	const char *arg1;
6131 	const char *arg2;
6132 	const char *res;
6133 } mupa_bin_tests[] = {
6134 	{ &isl_multi_union_pw_aff_add, "[{ A[] -> [1] }]", "[{ A[] -> [2] }]",
6135 	  "[{ A[] -> [3] }]" },
6136 	{ &isl_multi_union_pw_aff_sub, "[{ A[] -> [1] }]", "[{ A[] -> [2] }]",
6137 	  "[{ A[] -> [-1] }]" },
6138 	{ &isl_multi_union_pw_aff_add,
6139 	  "[{ A[] -> [1]; B[] -> [4] }]",
6140 	  "[{ A[] -> [2]; C[] -> [5] }]",
6141 	  "[{ A[] -> [3] }]" },
6142 	{ &isl_multi_union_pw_aff_union_add,
6143 	  "[{ A[] -> [1]; B[] -> [4] }]",
6144 	  "[{ A[] -> [2]; C[] -> [5] }]",
6145 	  "[{ A[] -> [3]; B[] -> [4]; C[] -> [5] }]" },
6146 	{ &isl_multi_union_pw_aff_add, "[{ A[x] -> [(1)] : x >= 5 }]",
6147 	  "[{ A[x] -> [(x)] : x <= 10 }]",
6148 	  "[{ A[x] -> [(1 + x)] : 5 <= x <= 10 }]" },
6149 	{ &isl_multi_union_pw_aff_add, "([] : { A[x] : x >= 5 })",
6150 	  "([] : { A[x] : x <= 10 })",
6151 	  "([] : { A[x] : 5 <= x <= 10 })" },
6152 	{ &isl_multi_union_pw_aff_add, "([] : { A[x] : x >= 5 })",
6153 	  "[N] -> ([] : { A[x] : x <= N })",
6154 	  "[N] -> ([] : { A[x] : 5 <= x <= N })" },
6155 	{ &isl_multi_union_pw_aff_add, "[N] -> ([] : { A[x] : x >= N })",
6156 	  "([] : { A[x] : x <= 10 })",
6157 	  "[N] -> ([] : { A[x] : N <= x <= 10 })" },
6158 	{ &isl_multi_union_pw_aff_union_add, "[{ A[x] -> [(1)] : x >= 5 }]",
6159 	  "[{ A[x] -> [(x)] : x <= 10 }]",
6160 	  "[{ A[x] -> [(1 + x)] : 5 <= x <= 10; "
6161 	     "A[x] -> [(1)] : x > 10; A[x] -> [(x)] : x < 5 }]" },
6162 	{ &isl_multi_union_pw_aff_union_add, "([] : { A[x] : x >= 5 })",
6163 	  "([] : { A[x] : x <= 10 })",
6164 	  "([] : { A[x] })" },
6165 	{ &isl_multi_union_pw_aff_union_add, "([] : { A[x] : x >= 0 })",
6166 	  "[N] -> ([] : { A[x] : x >= N })",
6167 	  "[N] -> ([] : { A[x] : x >= 0 or x >= N })" },
6168 	{ &isl_multi_union_pw_aff_union_add,
6169 	  "[N] -> ([] : { A[] : N >= 0})",
6170 	  "[N] -> ([] : { A[] : N <= 0})",
6171 	  "[N] -> ([] : { A[] })" },
6172 	{ &isl_multi_union_pw_aff_union_add,
6173 	  "[N] -> ([] : { A[] })",
6174 	  "[N] -> ([] : { : })",
6175 	  "[N] -> ([] : { : })" },
6176 	{ &isl_multi_union_pw_aff_union_add,
6177 	  "[N] -> ([] : { : })",
6178 	  "[N] -> ([] : { A[] })",
6179 	  "[N] -> ([] : { : })" },
6180 	{ &isl_multi_union_pw_aff_union_add,
6181 	  "[N] -> ([] : { : N >= 0})",
6182 	  "[N] -> ([] : { : N <= 0})",
6183 	  "[N] -> ([] : { : })" },
6184 	{ &isl_multi_union_pw_aff_range_product,
6185 	  "B[{ A[] -> [1] }]",
6186 	  "C[{ A[] -> [2] }]",
6187 	  "[B[{ A[] -> [1] }] -> C[{ A[] -> [2] }]]" },
6188 	{ &isl_multi_union_pw_aff_range_product,
6189 	  "(B[] : { A[x] : x >= 5 })",
6190 	  "(C[] : { A[x] : x <= 10 })",
6191 	  "([B[] -> C[]] : { A[x] : 5 <= x <= 10 })" },
6192 	{ &isl_multi_union_pw_aff_range_product,
6193 	  "B[{ A[x] -> [x + 1] : x >= 5 }]",
6194 	  "(C[] : { A[x] : x <= 10 })",
6195 	  "[B[{ A[x] -> [x + 1] : 5 <= x <= 10 }] -> C[]]" },
6196 	{ &isl_multi_union_pw_aff_range_product,
6197 	  "(C[] : { A[x] : x <= 10 })",
6198 	  "B[{ A[x] -> [x + 1] : x >= 5 }]",
6199 	  "[C[] -> B[{ A[x] -> [x + 1] : 5 <= x <= 10 }]]" },
6200 	{ &isl_multi_union_pw_aff_range_product,
6201 	  "B[{ A[x] -> [x + 1] : x >= 5 }]",
6202 	  "[N] -> (C[] : { A[x] : x <= N })",
6203 	  "[N] -> [B[{ A[x] -> [x + 1] : 5 <= x <= N }] -> C[]]" },
6204 	{ &isl_multi_union_pw_aff_range_product,
6205 	  "[N] -> (C[] : { A[x] : x <= N })",
6206 	  "B[{ A[x] -> [x + 1] : x >= 5 }]",
6207 	  "[N] -> [C[] -> B[{ A[x] -> [x + 1] : 5 <= x <= N }]]" },
6208 	{ &isl_multi_union_pw_aff_range_product,
6209 	  "B[{ A[] -> [1]; D[] -> [3] }]",
6210 	  "C[{ A[] -> [2] }]",
6211 	  "[B[{ A[] -> [1]; D[] -> [3] }] -> C[{ A[] -> [2] }]]" },
6212 	{ &isl_multi_union_pw_aff_range_product,
6213 	  "B[] }]",
6214 	  "(C[] : { A[x] })",
6215 	  "([B[] -> C[]] : { A[x] })" },
6216 	{ &isl_multi_union_pw_aff_range_product,
6217 	  "(B[] : { A[x] })",
6218 	  "C[] }]",
6219 	  "([B[] -> C[]] : { A[x] })" },
6220 };
6221 
6222 /* Perform some basic tests of binary operations on
6223  * isl_multi_union_pw_aff objects.
6224  */
test_bin_mupa(isl_ctx * ctx)6225 static int test_bin_mupa(isl_ctx *ctx)
6226 {
6227 	int i;
6228 	isl_bool ok;
6229 	isl_multi_union_pw_aff *mupa1, *mupa2, *res;
6230 
6231 	for (i = 0; i < ARRAY_SIZE(mupa_bin_tests); ++i) {
6232 		mupa1 = isl_multi_union_pw_aff_read_from_str(ctx,
6233 							mupa_bin_tests[i].arg1);
6234 		mupa2 = isl_multi_union_pw_aff_read_from_str(ctx,
6235 							mupa_bin_tests[i].arg2);
6236 		res = isl_multi_union_pw_aff_read_from_str(ctx,
6237 							mupa_bin_tests[i].res);
6238 		mupa1 = mupa_bin_tests[i].fn(mupa1, mupa2);
6239 		ok = isl_multi_union_pw_aff_plain_is_equal(mupa1, res);
6240 		isl_multi_union_pw_aff_free(mupa1);
6241 		isl_multi_union_pw_aff_free(res);
6242 		if (ok < 0)
6243 			return -1;
6244 		if (!ok)
6245 			isl_die(ctx, isl_error_unknown,
6246 				"unexpected result", return -1);
6247 	}
6248 
6249 	return 0;
6250 }
6251 
6252 /* Inputs for basic tests of binary operations on
6253  * pairs of isl_multi_union_pw_aff and isl_set objects.
6254  * "fn" is the function that is tested.
6255  * "arg1" and "arg2" are string descriptions of the inputs.
6256  * "res" is a string description of the expected result.
6257  */
6258 struct {
6259 	__isl_give isl_multi_union_pw_aff *(*fn)(
6260 		__isl_take isl_multi_union_pw_aff *mupa,
6261 		__isl_take isl_set *set);
6262 	const char *arg1;
6263 	const char *arg2;
6264 	const char *res;
6265 } mupa_set_tests[] = {
6266 	{ &isl_multi_union_pw_aff_intersect_range,
6267 	  "C[{ B[i,j] -> [i + 2j] }]", "{ C[1] }",
6268 	  "C[{ B[i,j] -> [i + 2j] : i + 2j = 1 }]" },
6269 	{ &isl_multi_union_pw_aff_intersect_range,
6270 	  "C[{ B[i,j] -> [i + 2j] }]", "[N] -> { C[N] }",
6271 	  "[N] -> C[{ B[i,j] -> [i + 2j] : i + 2j = N }]" },
6272 	{ &isl_multi_union_pw_aff_intersect_range,
6273 	  "[N] -> C[{ B[i,j] -> [i + 2j + N] }]", "{ C[1] }",
6274 	  "[N] -> C[{ B[i,j] -> [i + 2j + N] : i + 2j + N = 1 }]" },
6275 	{ &isl_multi_union_pw_aff_intersect_range,
6276 	  "C[{ B[i,j] -> [i + 2j] }]", "[N] -> { C[x] : N >= 0 }",
6277 	  "[N] -> C[{ B[i,j] -> [i + 2j] : N >= 0 }]" },
6278 	{ &isl_multi_union_pw_aff_intersect_range,
6279 	  "C[]", "{ C[] }", "C[]" },
6280 	{ &isl_multi_union_pw_aff_intersect_range,
6281 	  "[N] -> (C[] : { : N >= 0 })",
6282 	  "{ C[] }",
6283 	  "[N] -> (C[] : { : N >= 0 })" },
6284 	{ &isl_multi_union_pw_aff_intersect_range,
6285 	  "(C[] : { A[a,b] })",
6286 	  "{ C[] }",
6287 	  "(C[] : { A[a,b] })" },
6288 	{ &isl_multi_union_pw_aff_intersect_range,
6289 	  "[N] -> (C[] : { A[a,b] : a,b <= N })",
6290 	  "{ C[] }",
6291 	  "[N] -> (C[] : { A[a,b] : a,b <= N })" },
6292 	{ &isl_multi_union_pw_aff_intersect_range,
6293 	  "C[]",
6294 	  "[N] -> { C[] : N >= 0 }",
6295 	  "[N] -> (C[] : { : N >= 0 })" },
6296 	{ &isl_multi_union_pw_aff_intersect_range,
6297 	  "(C[] : { A[a,b] })",
6298 	  "[N] -> { C[] : N >= 0 }",
6299 	  "[N] -> (C[] : { A[a,b] : N >= 0 })" },
6300 	{ &isl_multi_union_pw_aff_intersect_range,
6301 	  "[N] -> (C[] : { : N >= 0 })",
6302 	  "[N] -> { C[] : N < 1024 }",
6303 	  "[N] -> (C[] : { : 0 <= N < 1024 })" },
6304 	{ &isl_multi_union_pw_aff_intersect_params,
6305 	  "C[{ B[i,j] -> [i + 2j] }]", "[N] -> { : N >= 0 }",
6306 	  "[N] -> C[{ B[i,j] -> [i + 2j] : N >= 0}]" },
6307 	{ &isl_multi_union_pw_aff_intersect_params,
6308 	  "[N] -> C[{ B[i,j] -> [i + 2j] : N <= 256 }]", "[N] -> { : N >= 0 }",
6309 	  "[N] -> C[{ B[i,j] -> [i + 2j] : 0 <= N <= 256 }]" },
6310 	{ &isl_multi_union_pw_aff_intersect_params,
6311 	  "[N] -> C[{ B[i,j] -> [i + 2j] : N <= 256 }]", "{ : }",
6312 	  "[N] -> C[{ B[i,j] -> [i + 2j] : N <= 256 }]" },
6313 	{ &isl_multi_union_pw_aff_intersect_params,
6314 	  "C[]", "[N] -> { : N >= 0 }",
6315 	  "[N] -> (C[] : { : N >= 0 })" },
6316 	{ &isl_multi_union_pw_aff_intersect_params,
6317 	  "(C[] : { A[a,b] })", "[N] -> { : N >= 0 }",
6318 	  "[N] -> (C[] : { A[a,b] : N >= 0 })" },
6319 	{ &isl_multi_union_pw_aff_intersect_params,
6320 	  "[N] -> (C[] : { A[a,N] })", "{ : }",
6321 	  "[N] -> (C[] : { A[a,N] })" },
6322 	{ &isl_multi_union_pw_aff_intersect_params,
6323 	  "[N] -> (C[] : { A[a,b] : N <= 256 })", "[N] -> { : N >= 0 }",
6324 	  "[N] -> (C[] : { A[a,b] : 0 <= N <= 256 })" },
6325 };
6326 
6327 /* Perform some basic tests of binary operations on
6328  * pairs of isl_multi_union_pw_aff and isl_set objects.
6329  */
test_mupa_set(isl_ctx * ctx)6330 static int test_mupa_set(isl_ctx *ctx)
6331 {
6332 	int i;
6333 	isl_bool ok;
6334 	isl_multi_union_pw_aff *mupa, *res;
6335 	isl_set *set;
6336 
6337 	for (i = 0; i < ARRAY_SIZE(mupa_set_tests); ++i) {
6338 		mupa = isl_multi_union_pw_aff_read_from_str(ctx,
6339 						    mupa_set_tests[i].arg1);
6340 		set = isl_set_read_from_str(ctx, mupa_set_tests[i].arg2);
6341 		res = isl_multi_union_pw_aff_read_from_str(ctx,
6342 						    mupa_set_tests[i].res);
6343 		mupa = mupa_set_tests[i].fn(mupa, set);
6344 		ok = isl_multi_union_pw_aff_plain_is_equal(mupa, res);
6345 		isl_multi_union_pw_aff_free(mupa);
6346 		isl_multi_union_pw_aff_free(res);
6347 		if (ok < 0)
6348 			return -1;
6349 		if (!ok)
6350 			isl_die(ctx, isl_error_unknown,
6351 				"unexpected result", return -1);
6352 	}
6353 
6354 	return 0;
6355 }
6356 
6357 /* Inputs for basic tests of binary operations on
6358  * pairs of isl_multi_union_pw_aff and isl_union_set objects.
6359  * "fn" is the function that is tested.
6360  * "arg1" and "arg2" are string descriptions of the inputs.
6361  * "res" is a string description of the expected result.
6362  */
6363 struct {
6364 	__isl_give isl_multi_union_pw_aff *(*fn)(
6365 		__isl_take isl_multi_union_pw_aff *mupa,
6366 		__isl_take isl_union_set *uset);
6367 	const char *arg1;
6368 	const char *arg2;
6369 	const char *res;
6370 } mupa_uset_tests[] = {
6371 	{ &isl_multi_union_pw_aff_intersect_domain,
6372 	  "C[{ B[i,j] -> [i + 2j] }]", "{ B[i,i] }",
6373 	  "C[{ B[i,i] -> [3i] }]" },
6374 	{ &isl_multi_union_pw_aff_intersect_domain,
6375 	  "(C[] : { B[i,j] })", "{ B[i,i] }",
6376 	  "(C[] : { B[i,i] })" },
6377 	{ &isl_multi_union_pw_aff_intersect_domain,
6378 	  "(C[] : { B[i,j] })", "[N] -> { B[N,N] }",
6379 	  "[N] -> (C[] : { B[N,N] })" },
6380 	{ &isl_multi_union_pw_aff_intersect_domain,
6381 	  "C[]", "{ B[i,i] }",
6382 	  "(C[] : { B[i,i] })" },
6383 	{ &isl_multi_union_pw_aff_intersect_domain,
6384 	  "[N] -> (C[] : { : N >= 0 })", "{ B[i,i] }",
6385 	  "[N] -> (C[] : { B[i,i] : N >= 0 })" },
6386 };
6387 
6388 /* Perform some basic tests of binary operations on
6389  * pairs of isl_multi_union_pw_aff and isl_union_set objects.
6390  */
test_mupa_uset(isl_ctx * ctx)6391 static int test_mupa_uset(isl_ctx *ctx)
6392 {
6393 	int i;
6394 	isl_bool ok;
6395 	isl_multi_union_pw_aff *mupa, *res;
6396 	isl_union_set *uset;
6397 
6398 	for (i = 0; i < ARRAY_SIZE(mupa_uset_tests); ++i) {
6399 		mupa = isl_multi_union_pw_aff_read_from_str(ctx,
6400 						    mupa_uset_tests[i].arg1);
6401 		uset = isl_union_set_read_from_str(ctx,
6402 						    mupa_uset_tests[i].arg2);
6403 		res = isl_multi_union_pw_aff_read_from_str(ctx,
6404 						    mupa_uset_tests[i].res);
6405 		mupa = mupa_uset_tests[i].fn(mupa, uset);
6406 		ok = isl_multi_union_pw_aff_plain_is_equal(mupa, res);
6407 		isl_multi_union_pw_aff_free(mupa);
6408 		isl_multi_union_pw_aff_free(res);
6409 		if (ok < 0)
6410 			return -1;
6411 		if (!ok)
6412 			isl_die(ctx, isl_error_unknown,
6413 				"unexpected result", return -1);
6414 	}
6415 
6416 	return 0;
6417 }
6418 
6419 /* Inputs for basic tests of binary operations on
6420  * pairs of isl_multi_union_pw_aff and isl_multi_aff objects.
6421  * "fn" is the function that is tested.
6422  * "arg1" and "arg2" are string descriptions of the inputs.
6423  * "res" is a string description of the expected result.
6424  */
6425 struct {
6426 	__isl_give isl_multi_union_pw_aff *(*fn)(
6427 		__isl_take isl_multi_union_pw_aff *mupa,
6428 		__isl_take isl_multi_aff *ma);
6429 	const char *arg1;
6430 	const char *arg2;
6431 	const char *res;
6432 } mupa_ma_tests[] = {
6433 	{ &isl_multi_union_pw_aff_apply_multi_aff,
6434 	  "C[{ A[i,j] -> [i]; B[i,j] -> [j] }, "
6435 	    "{ A[i,j] -> [j]; B[i,j] -> [i] }]",
6436 	  "{ C[a,b] -> D[b,a] }",
6437 	  "D[{ A[i,j] -> [j]; B[i,j] -> [i] }, "
6438 	    "{ A[i,j] -> [i]; B[i,j] -> [j] }]" },
6439 	{ &isl_multi_union_pw_aff_apply_multi_aff,
6440 	  "C[{ A[i,j] -> [i] : i >= 0; B[i,j] -> [j] }, "
6441 	    "{ A[i,j] -> [j]; B[i,j] -> [i] }]",
6442 	  "{ C[a,b] -> D[b,a] }",
6443 	  "D[{ A[i,j] -> [j] : i >= 0; B[i,j] -> [i] }, "
6444 	    "{ A[i,j] -> [i] : i >= 0; B[i,j] -> [j] }]" },
6445 	{ &isl_multi_union_pw_aff_apply_multi_aff,
6446 	  "C[{ A[i,j] -> [i]; B[i,j] -> [j] }]",
6447 	  "[N] -> { C[a] -> D[a + N] }",
6448 	  "[N] -> D[{ A[i,j] -> [i + N]; B[i,j] -> [j + N] }] " },
6449 	{ &isl_multi_union_pw_aff_apply_multi_aff,
6450 	  "C[]",
6451 	  "{ C[] -> D[] }",
6452 	  "D[]" },
6453 	{ &isl_multi_union_pw_aff_apply_multi_aff,
6454 	  "[N] -> (C[] : { : N >= 0 })",
6455 	  "{ C[] -> D[] }",
6456 	  "[N] -> (D[] : { : N >= 0 })" },
6457 	{ &isl_multi_union_pw_aff_apply_multi_aff,
6458 	  "C[]",
6459 	  "[N] -> { C[] -> D[N] }",
6460 	  "[N] -> D[{ [N] }]" },
6461 	{ &isl_multi_union_pw_aff_apply_multi_aff,
6462 	  "(C[] : { A[i,j] : i >= j })",
6463 	  "{ C[] -> D[] }",
6464 	  "(D[] : { A[i,j] : i >= j })" },
6465 	{ &isl_multi_union_pw_aff_apply_multi_aff,
6466 	  "[N] -> (C[] : { A[i,j] : N >= 0 })",
6467 	  "{ C[] -> D[] }",
6468 	  "[N] -> (D[] : { A[i,j] : N >= 0 })" },
6469 	{ &isl_multi_union_pw_aff_apply_multi_aff,
6470 	  "(C[] : { A[i,j] : i >= j })",
6471 	  "[N] -> { C[] -> D[N] }",
6472 	  "[N] -> (D[{ A[i,j] -> [N] : i >= j }])" },
6473 };
6474 
6475 /* Perform some basic tests of binary operations on
6476  * pairs of isl_multi_union_pw_aff and isl_multi_aff objects.
6477  */
test_mupa_ma(isl_ctx * ctx)6478 static int test_mupa_ma(isl_ctx *ctx)
6479 {
6480 	int i;
6481 	isl_bool ok;
6482 	isl_multi_union_pw_aff *mupa, *res;
6483 	isl_multi_aff *ma;
6484 
6485 	for (i = 0; i < ARRAY_SIZE(mupa_ma_tests); ++i) {
6486 		mupa = isl_multi_union_pw_aff_read_from_str(ctx,
6487 						    mupa_ma_tests[i].arg1);
6488 		ma = isl_multi_aff_read_from_str(ctx, mupa_ma_tests[i].arg2);
6489 		res = isl_multi_union_pw_aff_read_from_str(ctx,
6490 						    mupa_ma_tests[i].res);
6491 		mupa = mupa_ma_tests[i].fn(mupa, ma);
6492 		ok = isl_multi_union_pw_aff_plain_is_equal(mupa, res);
6493 		isl_multi_union_pw_aff_free(mupa);
6494 		isl_multi_union_pw_aff_free(res);
6495 		if (ok < 0)
6496 			return -1;
6497 		if (!ok)
6498 			isl_die(ctx, isl_error_unknown,
6499 				"unexpected result", return -1);
6500 	}
6501 
6502 	return 0;
6503 }
6504 
6505 /* Inputs for basic tests of binary operations on
6506  * pairs of isl_multi_union_pw_aff and isl_pw_aff objects.
6507  * "fn" is the function that is tested.
6508  * "arg1" and "arg2" are string descriptions of the inputs.
6509  * "res" is a string description of the expected result.
6510  */
6511 struct {
6512 	__isl_give isl_union_pw_aff *(*fn)(
6513 		__isl_take isl_multi_union_pw_aff *mupa,
6514 		__isl_take isl_pw_aff *pa);
6515 	const char *arg1;
6516 	const char *arg2;
6517 	const char *res;
6518 } mupa_pa_tests[] = {
6519 	{ &isl_multi_union_pw_aff_apply_pw_aff,
6520 	  "C[{ A[i,j] -> [i]; B[i,j] -> [j] }]",
6521 	  "[N] -> { C[a] -> [a + N] }",
6522 	  "[N] -> { A[i,j] -> [i + N]; B[i,j] -> [j + N] }" },
6523 	{ &isl_multi_union_pw_aff_apply_pw_aff,
6524 	  "C[{ A[i,j] -> [i]; B[i,j] -> [j] }]",
6525 	  "{ C[a] -> [a] : a >= 0; C[a] -> [-a] : a < 0 }",
6526 	  "{ A[i,j] -> [i] : i >= 0; A[i,j] -> [-i] : i < 0; "
6527 	    "B[i,j] -> [j] : j >= 0; B[i,j] -> [-j] : j < 0 }" },
6528 	{ &isl_multi_union_pw_aff_apply_pw_aff,
6529 	  "C[]",
6530 	  "[N] -> { C[] -> [N] }",
6531 	  "[N] -> { [N] }" },
6532 	{ &isl_multi_union_pw_aff_apply_pw_aff,
6533 	  "C[]",
6534 	  "[N] -> { C[] -> [N] : N >= 0; C[] -> [-N] : N < 0 }",
6535 	  "[N] -> { [N] : N >= 0; [-N] : N < 0 }" },
6536 	{ &isl_multi_union_pw_aff_apply_pw_aff,
6537 	  "[N] -> (C[] : { : N >= 0 })",
6538 	  "[N] -> { C[] -> [N] }",
6539 	  "[N] -> { [N] : N >= 0 }" },
6540 	{ &isl_multi_union_pw_aff_apply_pw_aff,
6541 	  "[N] -> (C[] : { : N >= 0 })",
6542 	  "[N] -> { C[] -> [N] : N >= 0; C[] -> [-N] : N < 0 }",
6543 	  "[N] -> { [N] : N >= 0 }" },
6544 	{ &isl_multi_union_pw_aff_apply_pw_aff,
6545 	  "[N] -> (C[] : { : N >= 0 })",
6546 	  "{ C[] -> [0] }",
6547 	  "[N] -> { [0] : N >= 0 }" },
6548 	{ &isl_multi_union_pw_aff_apply_pw_aff,
6549 	  "(C[] : { A[i,j] : i >= j })",
6550 	  "[N] -> { C[] -> [N] }",
6551 	  "[N] -> { A[i,j] -> [N] : i >= j }" },
6552 	{ &isl_multi_union_pw_aff_apply_pw_aff,
6553 	  "(C[] : { A[i,j] : i >= j })",
6554 	  "[N] -> { C[] -> [N] : N >= 0 }",
6555 	  "[N] -> { A[i,j] -> [N] : i >= j and N >= 0 }" },
6556 };
6557 
6558 /* Perform some basic tests of binary operations on
6559  * pairs of isl_multi_union_pw_aff and isl_pw_aff objects.
6560  */
test_mupa_pa(isl_ctx * ctx)6561 static int test_mupa_pa(isl_ctx *ctx)
6562 {
6563 	int i;
6564 	isl_bool ok;
6565 	isl_multi_union_pw_aff *mupa;
6566 	isl_union_pw_aff *upa, *res;
6567 	isl_pw_aff *pa;
6568 
6569 	for (i = 0; i < ARRAY_SIZE(mupa_pa_tests); ++i) {
6570 		mupa = isl_multi_union_pw_aff_read_from_str(ctx,
6571 						    mupa_pa_tests[i].arg1);
6572 		pa = isl_pw_aff_read_from_str(ctx, mupa_pa_tests[i].arg2);
6573 		res = isl_union_pw_aff_read_from_str(ctx,
6574 						    mupa_pa_tests[i].res);
6575 		upa = mupa_pa_tests[i].fn(mupa, pa);
6576 		ok = isl_union_pw_aff_plain_is_equal(upa, res);
6577 		isl_union_pw_aff_free(upa);
6578 		isl_union_pw_aff_free(res);
6579 		if (ok < 0)
6580 			return -1;
6581 		if (!ok)
6582 			isl_die(ctx, isl_error_unknown,
6583 				"unexpected result", return -1);
6584 	}
6585 
6586 	return 0;
6587 }
6588 
6589 /* Inputs for basic tests of binary operations on
6590  * pairs of isl_multi_union_pw_aff and isl_pw_multi_aff objects.
6591  * "fn" is the function that is tested.
6592  * "arg1" and "arg2" are string descriptions of the inputs.
6593  * "res" is a string description of the expected result.
6594  */
6595 struct {
6596 	__isl_give isl_multi_union_pw_aff *(*fn)(
6597 		__isl_take isl_multi_union_pw_aff *mupa,
6598 		__isl_take isl_pw_multi_aff *pma);
6599 	const char *arg1;
6600 	const char *arg2;
6601 	const char *res;
6602 } mupa_pma_tests[] = {
6603 	{ &isl_multi_union_pw_aff_apply_pw_multi_aff,
6604 	  "C[{ A[i,j] -> [i]; B[i,j] -> [j] }, "
6605 	    "{ A[i,j] -> [j]; B[i,j] -> [i] }]",
6606 	  "{ C[a,b] -> D[b,a] }",
6607 	  "D[{ A[i,j] -> [j]; B[i,j] -> [i] }, "
6608 	    "{ A[i,j] -> [i]; B[i,j] -> [j] }]" },
6609 	{ &isl_multi_union_pw_aff_apply_pw_multi_aff,
6610 	  "C[{ A[i,j] -> [i] : i >= 0; B[i,j] -> [j] }, "
6611 	    "{ A[i,j] -> [j]; B[i,j] -> [i] }]",
6612 	  "{ C[a,b] -> D[b,a] }",
6613 	  "D[{ A[i,j] -> [j] : i >= 0; B[i,j] -> [i] }, "
6614 	    "{ A[i,j] -> [i] : i >= 0; B[i,j] -> [j] }]" },
6615 	{ &isl_multi_union_pw_aff_apply_pw_multi_aff,
6616 	  "C[{ A[i,j] -> [i]; B[i,j] -> [j] }]",
6617 	  "[N] -> { C[a] -> D[a + N] }",
6618 	  "[N] -> D[{ A[i,j] -> [i + N]; B[i,j] -> [j + N] }]" },
6619 	{ &isl_multi_union_pw_aff_apply_pw_multi_aff,
6620 	  "C[{ A[i,j] -> [i]; B[i,j] -> [j] }]",
6621 	  "{ C[a] -> D[a] : a >= 0; C[a] -> D[-a] : a < 0 }",
6622 	  "D[{ A[i,j] -> [i] : i >= 0; A[i,j] -> [-i] : i < 0; "
6623 	      "B[i,j] -> [j] : j >= 0; B[i,j] -> [-j] : j < 0 }]" },
6624 	{ &isl_multi_union_pw_aff_apply_pw_multi_aff,
6625 	  "C[{ A[i,j] -> [i]; B[i,j] -> [j] }, "
6626 	    "{ A[i,j] -> [j]; B[i,j] -> [i] }]",
6627 	  "{ C[a,b] -> D[a,b] : a >= b; C[a,b] -> D[b,a] : a < b }",
6628 	  "D[{ A[i,j] -> [i] : i >= j; A[i,j] -> [j] : i < j; "
6629 	      "B[i,j] -> [j] : i <= j; B[i,j] -> [i] : i > j }, "
6630 	    "{ A[i,j] -> [j] : i >= j; A[i,j] -> [i] : i < j; "
6631 	      "B[i,j] -> [i] : i <= j; B[i,j] -> [j] : i > j }]" },
6632 	{ &isl_multi_union_pw_aff_apply_pw_multi_aff,
6633 	  "C[]",
6634 	  "{ C[] -> D[] }",
6635 	  "D[]" },
6636 	{ &isl_multi_union_pw_aff_apply_pw_multi_aff,
6637 	  "[N] -> (C[] : { : N >= 0 })",
6638 	  "{ C[] -> D[] }",
6639 	  "[N] -> (D[] : { : N >= 0 })" },
6640 	{ &isl_multi_union_pw_aff_apply_pw_multi_aff,
6641 	  "C[]",
6642 	  "[N] -> { C[] -> D[N] }",
6643 	  "[N] -> D[{ [N] }]" },
6644 	{ &isl_multi_union_pw_aff_apply_pw_multi_aff,
6645 	  "(C[] : { A[i,j] : i >= j })",
6646 	  "{ C[] -> D[] }",
6647 	  "(D[] : { A[i,j] : i >= j })" },
6648 	{ &isl_multi_union_pw_aff_apply_pw_multi_aff,
6649 	  "[N] -> (C[] : { A[i,j] : N >= 0 })",
6650 	  "{ C[] -> D[] }",
6651 	  "[N] -> (D[] : { A[i,j] : N >= 0 })" },
6652 	{ &isl_multi_union_pw_aff_apply_pw_multi_aff,
6653 	  "(C[] : { A[i,j] : i >= j })",
6654 	  "[N] -> { C[] -> D[N] }",
6655 	  "[N] -> (D[{ A[i,j] -> [N] : i >= j }])" },
6656 	{ &isl_multi_union_pw_aff_apply_pw_multi_aff,
6657 	  "C[]",
6658 	  "[N] -> { C[] -> D[N] : N >= 0; C[] -> D[-N] : N < 0 }",
6659 	  "[N] -> D[{ [N] : N >= 0; [-N] : N < 0 }]" },
6660 	{ &isl_multi_union_pw_aff_apply_pw_multi_aff,
6661 	  "[N] -> (C[] : { : N >= 0 })",
6662 	  "[N] -> { C[] -> D[N] }",
6663 	  "[N] -> D[{ [N] : N >= 0 }]" },
6664 	{ &isl_multi_union_pw_aff_apply_pw_multi_aff,
6665 	  "[N] -> (C[] : { : N >= 0 })",
6666 	  "[N] -> { C[] -> D[N] : N >= 0; C[] -> D[-N] : N < 0 }",
6667 	  "[N] -> D[{ [N] : N >= 0 }]" },
6668 	{ &isl_multi_union_pw_aff_apply_pw_multi_aff,
6669 	  "[N] -> (C[] : { : N >= 0 })",
6670 	  "{ C[] -> D[0] }",
6671 	  "[N] -> D[{ [0] : N >= 0 }]" },
6672 	{ &isl_multi_union_pw_aff_apply_pw_multi_aff,
6673 	  "(C[] : { A[i,j] : i >= j })",
6674 	  "[N] -> { C[] -> D[N] : N >= 0 }",
6675 	  "[N] -> D[{ A[i,j] -> [N] : i >= j and N >= 0 }]" },
6676 };
6677 
6678 /* Perform some basic tests of binary operations on
6679  * pairs of isl_multi_union_pw_aff and isl_pw_multi_aff objects.
6680  */
test_mupa_pma(isl_ctx * ctx)6681 static int test_mupa_pma(isl_ctx *ctx)
6682 {
6683 	int i;
6684 	isl_bool ok;
6685 	isl_multi_union_pw_aff *mupa, *res;
6686 	isl_pw_multi_aff *pma;
6687 
6688 	for (i = 0; i < ARRAY_SIZE(mupa_pma_tests); ++i) {
6689 		mupa = isl_multi_union_pw_aff_read_from_str(ctx,
6690 						    mupa_pma_tests[i].arg1);
6691 		pma = isl_pw_multi_aff_read_from_str(ctx,
6692 						    mupa_pma_tests[i].arg2);
6693 		res = isl_multi_union_pw_aff_read_from_str(ctx,
6694 						    mupa_pma_tests[i].res);
6695 		mupa = mupa_pma_tests[i].fn(mupa, pma);
6696 		ok = isl_multi_union_pw_aff_plain_is_equal(mupa, res);
6697 		isl_multi_union_pw_aff_free(mupa);
6698 		isl_multi_union_pw_aff_free(res);
6699 		if (ok < 0)
6700 			return -1;
6701 		if (!ok)
6702 			isl_die(ctx, isl_error_unknown,
6703 				"unexpected result", return -1);
6704 	}
6705 
6706 	return 0;
6707 }
6708 
6709 /* Inputs for basic tests of binary operations on
6710  * pairs of isl_multi_union_pw_aff and isl_union_pw_multi_aff objects.
6711  * "fn" is the function that is tested.
6712  * "arg1" and "arg2" are string descriptions of the inputs.
6713  * "res" is a string description of the expected result.
6714  */
6715 struct {
6716 	__isl_give isl_multi_union_pw_aff *(*fn)(
6717 		__isl_take isl_multi_union_pw_aff *mupa,
6718 		__isl_take isl_union_pw_multi_aff *upma);
6719 	const char *arg1;
6720 	const char *arg2;
6721 	const char *res;
6722 } mupa_upma_tests[] = {
6723 	{ &isl_multi_union_pw_aff_pullback_union_pw_multi_aff,
6724 	  "C[{ B[i,j] -> [i + 2j] }]", "{ A[a,b] -> B[b,a] }",
6725 	  "C[{ A[a,b] -> [b + 2a] }]" },
6726 	{ &isl_multi_union_pw_aff_pullback_union_pw_multi_aff,
6727 	  "C[{ B[i,j] -> [i + 2j] }]",
6728 	  "{ A[a,b] -> B[b,a] : b > a }",
6729 	  "C[{ A[a,b] -> [b + 2a] : b > a }]" },
6730 	{ &isl_multi_union_pw_aff_pullback_union_pw_multi_aff,
6731 	  "C[{ B[i,j] -> [i + 2j] : j > 4 }]",
6732 	  "{ A[a,b] -> B[b,a] : b > a }",
6733 	  "C[{ A[a,b] -> [b + 2a] : b > a > 4 }]" },
6734 	{ &isl_multi_union_pw_aff_pullback_union_pw_multi_aff,
6735 	  "C[{ B[i,j] -> [i + 2j] }]",
6736 	  "{ A[a,b] -> B[b,a] : a > b; A[a,b] -> B[a,b] : a <= b }",
6737 	  "C[{ A[a,b] -> [b + 2a] : a > b; A[a,b] -> [a + 2b] : a <= b }]" },
6738 	{ &isl_multi_union_pw_aff_pullback_union_pw_multi_aff,
6739 	  "(C[] : { B[a,b] })",
6740 	  "{ A[a,b] -> B[b,a] }",
6741 	  "(C[] : { A[a,b] })" },
6742 	{ &isl_multi_union_pw_aff_pullback_union_pw_multi_aff,
6743 	  "(C[] : { B[a,b] })",
6744 	  "{ B[a,b] -> A[b,a] }",
6745 	  "(C[] : { })" },
6746 	{ &isl_multi_union_pw_aff_pullback_union_pw_multi_aff,
6747 	  "(C[] : { B[a,b] })",
6748 	  "{ A[a,b] -> B[b,a] : a > b }",
6749 	  "(C[] : { A[a,b] : a > b })" },
6750 	{ &isl_multi_union_pw_aff_pullback_union_pw_multi_aff,
6751 	  "(C[] : { B[a,b] : a > b })",
6752 	  "{ A[a,b] -> B[b,a] }",
6753 	  "(C[] : { A[a,b] : b > a })" },
6754 	{ &isl_multi_union_pw_aff_pullback_union_pw_multi_aff,
6755 	  "[N] -> (C[] : { B[a,b] : a > N })",
6756 	  "{ A[a,b] -> B[b,a] : a > b }",
6757 	  "[N] -> (C[] : { A[a,b] : a > b > N })" },
6758 	{ &isl_multi_union_pw_aff_pullback_union_pw_multi_aff,
6759 	  "(C[] : { B[a,b] : a > b })",
6760 	  "[N] -> { A[a,b] -> B[b,a] : a > N }",
6761 	  "[N] -> (C[] : { A[a,b] : b > a > N })" },
6762 	{ &isl_multi_union_pw_aff_pullback_union_pw_multi_aff,
6763 	  "C[]",
6764 	  "{ A[a,b] -> B[b,a] }",
6765 	  "C[]" },
6766 	{ &isl_multi_union_pw_aff_pullback_union_pw_multi_aff,
6767 	  "[N] -> (C[] : { : N >= 0 })",
6768 	  "{ A[a,b] -> B[b,a] }",
6769 	  "[N] -> (C[] : { : N >= 0 })" },
6770 	{ &isl_multi_union_pw_aff_pullback_union_pw_multi_aff,
6771 	  "C[]",
6772 	  "[N] -> { A[a,b] -> B[b,a] : N >= 0 }",
6773 	  "[N] -> (C[] : { : N >= 0 })" },
6774 };
6775 
6776 /* Perform some basic tests of binary operations on
6777  * pairs of isl_multi_union_pw_aff and isl_union_pw_multi_aff objects.
6778  */
test_mupa_upma(isl_ctx * ctx)6779 static int test_mupa_upma(isl_ctx *ctx)
6780 {
6781 	int i;
6782 	isl_bool ok;
6783 	isl_multi_union_pw_aff *mupa, *res;
6784 	isl_union_pw_multi_aff *upma;
6785 
6786 	for (i = 0; i < ARRAY_SIZE(mupa_upma_tests); ++i) {
6787 		mupa = isl_multi_union_pw_aff_read_from_str(ctx,
6788 						    mupa_upma_tests[i].arg1);
6789 		upma = isl_union_pw_multi_aff_read_from_str(ctx,
6790 						    mupa_upma_tests[i].arg2);
6791 		res = isl_multi_union_pw_aff_read_from_str(ctx,
6792 						    mupa_upma_tests[i].res);
6793 		mupa = mupa_upma_tests[i].fn(mupa, upma);
6794 		ok = isl_multi_union_pw_aff_plain_is_equal(mupa, res);
6795 		isl_multi_union_pw_aff_free(mupa);
6796 		isl_multi_union_pw_aff_free(res);
6797 		if (ok < 0)
6798 			return -1;
6799 		if (!ok)
6800 			isl_die(ctx, isl_error_unknown,
6801 				"unexpected result", return -1);
6802 	}
6803 
6804 	return 0;
6805 }
6806 
6807 /* Check that the input tuple of an isl_aff can be set properly.
6808  */
test_aff_set_tuple_id(isl_ctx * ctx)6809 static isl_stat test_aff_set_tuple_id(isl_ctx *ctx)
6810 {
6811 	isl_id *id;
6812 	isl_aff *aff;
6813 	isl_stat equal;
6814 
6815 	aff = isl_aff_read_from_str(ctx, "{ [x] -> [x + 1] }");
6816 	id = isl_id_alloc(ctx, "A", NULL);
6817 	aff = isl_aff_set_tuple_id(aff, isl_dim_in, id);
6818 	equal = aff_check_plain_equal(aff, "{ A[x] -> [x + 1] }");
6819 	isl_aff_free(aff);
6820 	if (equal < 0)
6821 		return isl_stat_error;
6822 
6823 	return isl_stat_ok;
6824 }
6825 
6826 /* Check that affine expressions get normalized on addition/subtraction.
6827  * In particular, check that (final) unused integer divisions get removed
6828  * such that an expression derived from expressions with integer divisions
6829  * is found to be obviously equal to one that is created directly.
6830  */
test_aff_normalize(isl_ctx * ctx)6831 static isl_stat test_aff_normalize(isl_ctx *ctx)
6832 {
6833 	isl_aff *aff, *aff2;
6834 	isl_stat ok;
6835 
6836 	aff = isl_aff_read_from_str(ctx, "{ [x] -> [x//2] }");
6837 	aff2 = isl_aff_read_from_str(ctx, "{ [x] -> [1 + x//2] }");
6838 	aff = isl_aff_sub(aff2, aff);
6839 	ok = aff_check_plain_equal(aff, "{ [x] -> [1] }");
6840 	isl_aff_free(aff);
6841 
6842 	return ok;
6843 }
6844 
test_aff(isl_ctx * ctx)6845 int test_aff(isl_ctx *ctx)
6846 {
6847 	const char *str;
6848 	isl_set *set;
6849 	isl_space *space;
6850 	isl_local_space *ls;
6851 	isl_aff *aff;
6852 	int zero;
6853 	isl_stat equal;
6854 
6855 	if (test_upa(ctx) < 0)
6856 		return -1;
6857 	if (test_bin_aff(ctx) < 0)
6858 		return -1;
6859 	if (test_bin_pw_aff(ctx) < 0)
6860 		return -1;
6861 	if (test_upma_test(ctx) < 0)
6862 		return -1;
6863 	if (test_bin_upma(ctx) < 0)
6864 		return -1;
6865 	if (test_bin_upma_fail(ctx) < 0)
6866 		return -1;
6867 	if (test_upma_uset(ctx) < 0)
6868 		return -1;
6869 	if (test_un_mpa(ctx) < 0)
6870 		return -1;
6871 	if (test_bin_mpa(ctx) < 0)
6872 		return -1;
6873 	if (test_un_mupa(ctx) < 0)
6874 		return -1;
6875 	if (test_bin_mupa(ctx) < 0)
6876 		return -1;
6877 	if (test_mupa_set(ctx) < 0)
6878 		return -1;
6879 	if (test_mupa_uset(ctx) < 0)
6880 		return -1;
6881 	if (test_mupa_ma(ctx) < 0)
6882 		return -1;
6883 	if (test_mupa_pa(ctx) < 0)
6884 		return -1;
6885 	if (test_mupa_pma(ctx) < 0)
6886 		return -1;
6887 	if (test_mupa_upma(ctx) < 0)
6888 		return -1;
6889 
6890 	space = isl_space_set_alloc(ctx, 0, 1);
6891 	ls = isl_local_space_from_space(space);
6892 	aff = isl_aff_zero_on_domain(ls);
6893 
6894 	aff = isl_aff_add_coefficient_si(aff, isl_dim_in, 0, 1);
6895 	aff = isl_aff_scale_down_ui(aff, 3);
6896 	aff = isl_aff_floor(aff);
6897 	aff = isl_aff_add_coefficient_si(aff, isl_dim_in, 0, 1);
6898 	aff = isl_aff_scale_down_ui(aff, 2);
6899 	aff = isl_aff_floor(aff);
6900 	aff = isl_aff_add_coefficient_si(aff, isl_dim_in, 0, 1);
6901 
6902 	str = "{ [10] }";
6903 	set = isl_set_read_from_str(ctx, str);
6904 	aff = isl_aff_gist(aff, set);
6905 
6906 	aff = isl_aff_add_constant_si(aff, -16);
6907 	zero = isl_aff_plain_is_zero(aff);
6908 	isl_aff_free(aff);
6909 
6910 	if (zero < 0)
6911 		return -1;
6912 	if (!zero)
6913 		isl_die(ctx, isl_error_unknown, "unexpected result", return -1);
6914 
6915 	aff = isl_aff_read_from_str(ctx, "{ [-1] }");
6916 	aff = isl_aff_scale_down_ui(aff, 64);
6917 	aff = isl_aff_floor(aff);
6918 	equal = aff_check_plain_equal(aff, "{ [-1] }");
6919 	isl_aff_free(aff);
6920 	if (equal < 0)
6921 		return -1;
6922 
6923 	if (test_aff_set_tuple_id(ctx) < 0)
6924 		return -1;
6925 	if (test_aff_normalize(ctx) < 0)
6926 		return -1;
6927 
6928 	return 0;
6929 }
6930 
6931 /* Inputs for isl_set_bind tests.
6932  * "set" is the input set.
6933  * "tuple" is the binding tuple.
6934  * "res" is the expected result.
6935  */
6936 static
6937 struct {
6938 	const char *set;
6939 	const char *tuple;
6940 	const char *res;
6941 } bind_set_tests[] = {
6942 	{ "{ A[M, N] : M mod 2 = 0 and N mod 8 = 3 }",
6943 	  "{ A[M, N] }",
6944 	  "[M, N] -> { : M mod 2 = 0 and N mod 8 = 3 }" },
6945 	{ "{ B[N, M] : M mod 2 = 0 and N mod 8 = 3 }",
6946 	  "{ B[N, M] }",
6947 	  "[M, N] -> { : M mod 2 = 0 and N mod 8 = 3 }" },
6948 	{ "[M] -> { C[N] : M mod 2 = 0 and N mod 8 = 3 }",
6949 	  "{ C[N] }",
6950 	  "[M, N] -> { : M mod 2 = 0 and N mod 8 = 3 }" },
6951 	{ "[M] -> { D[x, N] : x mod 2 = 0 and N mod 8 = 3 and M >= 0 }",
6952 	  "{ D[M, N] }",
6953 	  "[M, N] -> { : M mod 2 = 0 and N mod 8 = 3 and M >= 0 }" },
6954 };
6955 
6956 /* Perform basic isl_set_bind tests.
6957  */
test_bind_set(isl_ctx * ctx)6958 static isl_stat test_bind_set(isl_ctx *ctx)
6959 {
6960 	int i;
6961 
6962 	for (i = 0; i < ARRAY_SIZE(bind_set_tests); ++i) {
6963 		const char *str;
6964 		isl_set *set;
6965 		isl_multi_id *tuple;
6966 		isl_stat r;
6967 
6968 		set = isl_set_read_from_str(ctx, bind_set_tests[i].set);
6969 		str = bind_set_tests[i].tuple;
6970 		tuple = isl_multi_id_read_from_str(ctx, str);
6971 		set = isl_set_bind(set, tuple);
6972 		r = set_check_equal(set, bind_set_tests[i].res);
6973 		isl_set_free(set);
6974 		if (r < 0)
6975 			return isl_stat_error;
6976 	}
6977 
6978 	return isl_stat_ok;
6979 }
6980 
6981 /* Inputs for isl_map_bind_domain tests.
6982  * "map" is the input map.
6983  * "tuple" is the binding tuple.
6984  * "res" is the expected result.
6985  */
6986 struct {
6987 	const char *map;
6988 	const char *tuple;
6989 	const char *res;
6990 } bind_map_domain_tests[] = {
6991 	{ "{ A[M, N] -> [M + floor(N/2)] }",
6992 	  "{ A[M, N] }",
6993 	  "[M, N] -> { [M + floor(N/2)] }" },
6994 	{ "{ B[N, M] -> [M + floor(N/2)] }",
6995 	  "{ B[N, M] }",
6996 	  "[N, M] -> { [M + floor(N/2)] }" },
6997 	{ "[M] -> { C[N] -> [M + floor(N/2)] }",
6998 	  "{ C[N] }",
6999 	  "[M, N] -> { [M + floor(N/2)] }" },
7000 	{ "[M] -> { C[x, N] -> [x + floor(N/2)] }",
7001 	  "{ C[M, N] }",
7002 	  "[M, N] -> { [M + floor(N/2)] }" },
7003 	{ "[M] -> { C[x, N] -> [M + floor(N/2)] }",
7004 	  "{ C[M, N] }",
7005 	  "[M, N] -> { [M + floor(N/2)] }" },
7006 	{ "[A, M] -> { C[N, x] -> [x + floor(N/2)] }",
7007 	  "{ C[N, M] }",
7008 	  "[A, N, M] -> { [M + floor(N/2)] }" },
7009 };
7010 
7011 /* Perform basic isl_map_bind_domain tests.
7012  */
test_bind_map_domain(isl_ctx * ctx)7013 static isl_stat test_bind_map_domain(isl_ctx *ctx)
7014 {
7015 	int i;
7016 
7017 	for (i = 0; i < ARRAY_SIZE(bind_map_domain_tests); ++i) {
7018 		const char *str;
7019 		isl_map *map;
7020 		isl_set *set;
7021 		isl_multi_id *tuple;
7022 		isl_stat r;
7023 
7024 		str = bind_map_domain_tests[i].map;
7025 		map = isl_map_read_from_str(ctx, str);
7026 		str = bind_map_domain_tests[i].tuple;
7027 		tuple = isl_multi_id_read_from_str(ctx, str);
7028 		set = isl_map_bind_domain(map, tuple);
7029 		str = bind_map_domain_tests[i].res;
7030 		r = set_check_equal(set, str);
7031 		isl_set_free(set);
7032 		if (r < 0)
7033 			return isl_stat_error;
7034 	}
7035 
7036 	return isl_stat_ok;
7037 }
7038 
7039 /* Inputs for isl_union_map_bind_range tests.
7040  * "map" is the input union map.
7041  * "tuple" is the binding tuple.
7042  * "res" is the expected result.
7043  */
7044 struct {
7045 	const char *map;
7046 	const char *tuple;
7047 	const char *res;
7048 } bind_umap_range_tests[] = {
7049 	{ "{ B[N, M] -> A[M, N] : M mod 2 = 0 and N mod 8 = 3 }",
7050 	  "{ A[M, N] }",
7051 	  "[M, N] -> { B[N, M] : M mod 2 = 0 and N mod 8 = 3 }" },
7052 	{ "{ B[N, M] -> A[M, N] : M mod 2 = 0 and N mod 8 = 3 }",
7053 	  "{ B[M, N] }",
7054 	  "{ }" },
7055 	{ "{ A[] -> B[]; C[] -> D[]; E[] -> B[] }",
7056 	  "{ B[] }",
7057 	  "{ A[]; E[] }" },
7058 };
7059 
7060 /* Perform basic isl_union_map_bind_range tests.
7061  */
test_bind_umap_range(isl_ctx * ctx)7062 static isl_stat test_bind_umap_range(isl_ctx *ctx)
7063 {
7064 	int i;
7065 
7066 	for (i = 0; i < ARRAY_SIZE(bind_umap_range_tests); ++i) {
7067 		const char *str;
7068 		isl_union_map *umap;
7069 		isl_union_set *uset;
7070 		isl_multi_id *tuple;
7071 		isl_stat r;
7072 
7073 		str = bind_umap_range_tests[i].map;
7074 		umap = isl_union_map_read_from_str(ctx, str);
7075 		str = bind_umap_range_tests[i].tuple;
7076 		tuple = isl_multi_id_read_from_str(ctx, str);
7077 		uset = isl_union_map_bind_range(umap, tuple);
7078 		str = bind_umap_range_tests[i].res;
7079 		r = uset_check_equal(uset, str);
7080 		isl_union_set_free(uset);
7081 		if (r < 0)
7082 			return isl_stat_error;
7083 	}
7084 
7085 	return isl_stat_ok;
7086 }
7087 
7088 /* Inputs for isl_pw_multi_aff_bind_domain tests.
7089  * "pma" is the input expression.
7090  * "tuple" is the binding tuple.
7091  * "res" is the expected result.
7092  */
7093 struct {
7094 	const char *pma;
7095 	const char *tuple;
7096 	const char *res;
7097 } bind_pma_domain_tests[] = {
7098 	{ "{ A[M, N] -> [M + floor(N/2)] }",
7099 	  "{ A[M, N] }",
7100 	  "[M, N] -> { [M + floor(N/2)] }" },
7101 	{ "{ B[N, M] -> [M + floor(N/2)] }",
7102 	  "{ B[N, M] }",
7103 	  "[N, M] -> { [M + floor(N/2)] }" },
7104 	{ "[M] -> { C[N] -> [M + floor(N/2)] }",
7105 	  "{ C[N] }",
7106 	  "[M, N] -> { [M + floor(N/2)] }" },
7107 	{ "[M] -> { C[x, N] -> [x + floor(N/2)] }",
7108 	  "{ C[M, N] }",
7109 	  "[M, N] -> { [M + floor(N/2)] }" },
7110 	{ "[M] -> { C[x, N] -> [M + floor(N/2)] }",
7111 	  "{ C[M, N] }",
7112 	  "[M, N] -> { [M + floor(N/2)] }" },
7113 	{ "[A, M] -> { C[N, x] -> [x + floor(N/2)] }",
7114 	  "{ C[N, M] }",
7115 	  "[A, N, M] -> { [M + floor(N/2)] }" },
7116 };
7117 
7118 /* Perform basic isl_pw_multi_aff_bind_domain tests.
7119  */
test_bind_pma_domain(isl_ctx * ctx)7120 static isl_stat test_bind_pma_domain(isl_ctx *ctx)
7121 {
7122 	int i;
7123 
7124 	for (i = 0; i < ARRAY_SIZE(bind_pma_domain_tests); ++i) {
7125 		const char *str;
7126 		isl_pw_multi_aff *pma;
7127 		isl_multi_id *tuple;
7128 		isl_stat r;
7129 
7130 		str = bind_pma_domain_tests[i].pma;
7131 		pma = isl_pw_multi_aff_read_from_str(ctx, str);
7132 		str = bind_pma_domain_tests[i].tuple;
7133 		tuple = isl_multi_id_read_from_str(ctx, str);
7134 		pma = isl_pw_multi_aff_bind_domain(pma, tuple);
7135 		str = bind_pma_domain_tests[i].res;
7136 		r = pw_multi_aff_check_plain_equal(pma, str);
7137 		isl_pw_multi_aff_free(pma);
7138 		if (r < 0)
7139 			return isl_stat_error;
7140 	}
7141 
7142 	return isl_stat_ok;
7143 }
7144 
7145 /* Inputs for isl_pw_multi_aff_bind_domain_wrapped_domain tests.
7146  * "pma" is the input expression.
7147  * "tuple" is the binding tuple.
7148  * "res" is the expected result.
7149  */
7150 struct {
7151 	const char *pma;
7152 	const char *tuple;
7153 	const char *res;
7154 } bind_pma_domain_wrapped_tests[] = {
7155 	{ "{ [A[M, N] -> B[]] -> [M + floor(N/2)] }",
7156 	  "{ A[M, N] }",
7157 	  "[M, N] -> { B[] -> [M + floor(N/2)] }" },
7158 	{ "{ [B[N, M] -> D[]] -> [M + floor(N/2)] }",
7159 	  "{ B[N, M] }",
7160 	  "[N, M] -> { D[] -> [M + floor(N/2)] }" },
7161 	{ "[M] -> { [C[N] -> B[x]] -> [x + M + floor(N/2)] }",
7162 	  "{ C[N] }",
7163 	  "[M, N] -> { B[x] -> [x + M + floor(N/2)] }" },
7164 	{ "[M] -> { [C[x, N] -> B[]] -> [x + floor(N/2)] }",
7165 	  "{ C[M, N] }",
7166 	  "[M, N] -> { B[] -> [M + floor(N/2)] }" },
7167 	{ "[M] -> { [C[x, N] -> B[]] -> [M + floor(N/2)] }",
7168 	  "{ C[M, N] }",
7169 	  "[M, N] -> { B[] -> [M + floor(N/2)] }" },
7170 	{ "[A, M] -> { [C[N, x] -> B[]] -> [x + floor(N/2)] }",
7171 	  "{ C[N, M] }",
7172 	  "[A, N, M] -> { B[] -> [M + floor(N/2)] }" },
7173 };
7174 
7175 /* Perform basic isl_pw_multi_aff_bind_domain_wrapped_domain tests.
7176  */
test_bind_pma_domain_wrapped(isl_ctx * ctx)7177 static isl_stat test_bind_pma_domain_wrapped(isl_ctx *ctx)
7178 {
7179 	int i;
7180 
7181 	for (i = 0; i < ARRAY_SIZE(bind_pma_domain_wrapped_tests); ++i) {
7182 		const char *str;
7183 		isl_pw_multi_aff *pma;
7184 		isl_multi_id *tuple;
7185 		isl_stat r;
7186 
7187 		str = bind_pma_domain_wrapped_tests[i].pma;
7188 		pma = isl_pw_multi_aff_read_from_str(ctx, str);
7189 		str = bind_pma_domain_wrapped_tests[i].tuple;
7190 		tuple = isl_multi_id_read_from_str(ctx, str);
7191 		pma = isl_pw_multi_aff_bind_domain_wrapped_domain(pma, tuple);
7192 		str = bind_pma_domain_wrapped_tests[i].res;
7193 		r = pw_multi_aff_check_plain_equal(pma, str);
7194 		isl_pw_multi_aff_free(pma);
7195 		if (r < 0)
7196 			return isl_stat_error;
7197 	}
7198 
7199 	return isl_stat_ok;
7200 }
7201 
7202 /* Inputs for isl_aff_bind_id tests.
7203  * "aff" is the input expression.
7204  * "id" is the binding id.
7205  * "res" is the expected result.
7206  */
7207 static
7208 struct {
7209 	const char *aff;
7210 	const char *id;
7211 	const char *res;
7212 } bind_aff_tests[] = {
7213 	{ "{ [4] }", "M", "[M = 4] -> { : }" },
7214 	{ "{ B[x] -> [floor(x/2)] }", "M", "[M] -> { B[x] : M = floor(x/2) }" },
7215 	{ "[M] -> { [4] }", "M", "[M = 4] -> { : }" },
7216 	{ "[M] -> { [floor(M/2)] }", "M", "[M] -> { : floor(M/2) = M }" },
7217 	{ "{ [NaN] }", "M", "{ : false }" },
7218 	{ "{ A[x] -> [NaN] }", "M", "{ A[x] : false }" },
7219 };
7220 
7221 /* Perform basic isl_aff_bind_id tests.
7222  */
test_bind_aff(isl_ctx * ctx)7223 static isl_stat test_bind_aff(isl_ctx *ctx)
7224 {
7225 	int i;
7226 
7227 	for (i = 0; i < ARRAY_SIZE(bind_aff_tests); ++i) {
7228 		isl_aff *aff;
7229 		isl_set *res;
7230 		isl_id *id;
7231 		isl_stat r;
7232 
7233 		aff = isl_aff_read_from_str(ctx, bind_aff_tests[i].aff);
7234 		id = isl_id_read_from_str(ctx, bind_aff_tests[i].id);
7235 		res = isl_set_from_basic_set(isl_aff_bind_id(aff, id));
7236 		r = set_check_equal(res, bind_aff_tests[i].res);
7237 		isl_set_free(res);
7238 		if (r < 0)
7239 			return isl_stat_error;
7240 	}
7241 
7242 	return isl_stat_ok;
7243 }
7244 
7245 /* Inputs for isl_pw_aff_bind_id tests.
7246  * "pa" is the input expression.
7247  * "id" is the binding id.
7248  * "res" is the expected result.
7249  */
7250 static
7251 struct {
7252 	const char *pa;
7253 	const char *id;
7254 	const char *res;
7255 } bind_pa_tests[] = {
7256 	{ "{ [4] }", "M", "[M = 4] -> { : }" },
7257 	{ "{ B[x] -> [floor(x/2)] }", "M", "[M] -> { B[x] : M = floor(x/2) }" },
7258 	{ "[M] -> { [4] }", "M", "[M = 4] -> { : }" },
7259 	{ "[M] -> { [floor(M/2)] }", "M", "[M] -> { : floor(M/2) = M }" },
7260 	{ "[M] -> { [M] : M >= 0; [-M] : M < 0 }", "M", "[M] -> { : M >= 0 }" },
7261 	{ "{ [NaN] }", "M", "{ : false }" },
7262 	{ "{ A[x] -> [NaN] }", "M", "{ A[x] : false }" },
7263 };
7264 
7265 /* Perform basic isl_pw_aff_bind_id tests.
7266  */
test_bind_pa(isl_ctx * ctx)7267 static isl_stat test_bind_pa(isl_ctx *ctx)
7268 {
7269 	int i;
7270 
7271 	for (i = 0; i < ARRAY_SIZE(bind_pa_tests); ++i) {
7272 		isl_pw_aff *pa;
7273 		isl_set *res;
7274 		isl_id *id;
7275 		isl_stat r;
7276 
7277 		pa = isl_pw_aff_read_from_str(ctx, bind_pa_tests[i].pa);
7278 		id = isl_id_read_from_str(ctx, bind_pa_tests[i].id);
7279 		res = isl_pw_aff_bind_id(pa, id);
7280 		r = set_check_equal(res, bind_pa_tests[i].res);
7281 		isl_set_free(res);
7282 		if (r < 0)
7283 			return isl_stat_error;
7284 	}
7285 
7286 	return isl_stat_ok;
7287 }
7288 
7289 /* Inputs for isl_multi_union_pw_aff_bind tests.
7290  * "mupa" is the input expression.
7291  * "tuple" is the binding tuple.
7292  * "res" is the expected result.
7293  */
7294 static
7295 struct {
7296 	const char *mupa;
7297 	const char *tuple;
7298 	const char *res;
7299 } bind_mupa_tests[] = {
7300 	{ "A[{ [4] }, { [5] }]",
7301 	  "{ A[M, N] }",
7302 	  "[M = 4, N = 5] -> { : }" },
7303 	{ "A[{ B[x] -> [floor(x/2)] }, { B[y] -> [y + 5] }]",
7304 	  "{ A[M, N] }",
7305 	  "[M, N] -> { B[x] : M = floor(x/2) and N = x + 5 }" },
7306 	{ "[M] -> A[{ [4] }, { [M + 1] }]",
7307 	  "{ A[M, N] }",
7308 	  "[M = 4, N = 5] -> { : }" },
7309 };
7310 
7311 /* Perform basic isl_multi_union_pw_aff_bind tests.
7312  */
test_bind_mupa(isl_ctx * ctx)7313 static isl_stat test_bind_mupa(isl_ctx *ctx)
7314 {
7315 	int i;
7316 
7317 	for (i = 0; i < ARRAY_SIZE(bind_mupa_tests); ++i) {
7318 		const char *str;
7319 		isl_multi_union_pw_aff *mupa;
7320 		isl_union_set *res;
7321 		isl_multi_id *tuple;
7322 		isl_stat r;
7323 
7324 		str = bind_mupa_tests[i].mupa;
7325 		mupa = isl_multi_union_pw_aff_read_from_str(ctx, str);
7326 		str = bind_mupa_tests[i].tuple;
7327 		tuple = isl_multi_id_read_from_str(ctx, str);
7328 		res = isl_multi_union_pw_aff_bind(mupa, tuple);
7329 		r = uset_check_equal(res, bind_mupa_tests[i].res);
7330 		isl_union_set_free(res);
7331 		if (r < 0)
7332 			return isl_stat_error;
7333 	}
7334 
7335 	return isl_stat_ok;
7336 }
7337 
7338 /* Perform tests that reinterpret dimensions as parameters.
7339  */
test_bind(isl_ctx * ctx)7340 static int test_bind(isl_ctx *ctx)
7341 {
7342 	if (test_bind_set(ctx) < 0)
7343 		return -1;
7344 	if (test_bind_map_domain(ctx) < 0)
7345 		return -1;
7346 	if (test_bind_umap_range(ctx) < 0)
7347 		return -1;
7348 	if (test_bind_pma_domain(ctx) < 0)
7349 		return -1;
7350 	if (test_bind_pma_domain_wrapped(ctx) < 0)
7351 		return -1;
7352 	if (test_bind_aff(ctx) < 0)
7353 		return -1;
7354 	if (test_bind_pa(ctx) < 0)
7355 		return -1;
7356 	if (test_bind_mupa(ctx) < 0)
7357 		return -1;
7358 
7359 	return 0;
7360 }
7361 
7362 /* Inputs for isl_set_unbind_params tests.
7363  * "set" is the input parameter domain.
7364  * "tuple" is the tuple of the constructed set.
7365  * "res" is the expected result.
7366  */
7367 struct {
7368 	const char *set;
7369 	const char *tuple;
7370 	const char *res;
7371 } unbind_set_tests[] = {
7372 	{ "[M, N] -> { : M mod 2 = 0 and N mod 8 = 3 }",
7373 	  "{ A[M, N] }",
7374 	  "{ A[M, N] : M mod 2 = 0 and N mod 8 = 3 }" },
7375 	{ "[M, N] -> { : M mod 2 = 0 and N mod 8 = 3 }",
7376 	  "{ B[N, M] }",
7377 	  "{ B[N, M] : M mod 2 = 0 and N mod 8 = 3 }" },
7378 	{ "[M, N] -> { : M mod 2 = 0 and N mod 8 = 3 }",
7379 	  "{ C[N] }",
7380 	  "[M] -> { C[N] : M mod 2 = 0 and N mod 8 = 3 }" },
7381 	{ "[M, N] -> { : M mod 2 = 0 and N mod 8 = 3 }",
7382 	  "{ D[T, N] }",
7383 	  "[M] -> { D[x, N] : M mod 2 = 0 and N mod 8 = 3 }" },
7384 };
7385 
7386 /* Perform basic isl_set_unbind_params tests.
7387  */
test_unbind_set(isl_ctx * ctx)7388 static isl_stat test_unbind_set(isl_ctx *ctx)
7389 {
7390 	int i;
7391 
7392 	for (i = 0; i < ARRAY_SIZE(unbind_set_tests); ++i) {
7393 		const char *str;
7394 		isl_set *set;
7395 		isl_multi_id *tuple;
7396 		isl_stat r;
7397 
7398 		set = isl_set_read_from_str(ctx, unbind_set_tests[i].set);
7399 		str = unbind_set_tests[i].tuple;
7400 		tuple = isl_multi_id_read_from_str(ctx, str);
7401 		set = isl_set_unbind_params(set, tuple);
7402 		r = set_check_equal(set, unbind_set_tests[i].res);
7403 		isl_set_free(set);
7404 		if (r < 0)
7405 			return isl_stat_error;
7406 	}
7407 
7408 	return isl_stat_ok;
7409 }
7410 
7411 /* Inputs for isl_aff_unbind_params_insert_domain tests.
7412  * "aff" is the input affine expression defined over a parameter domain.
7413  * "tuple" is the tuple of the domain that gets introduced.
7414  * "res" is the expected result.
7415  */
7416 struct {
7417 	const char *aff;
7418 	const char *tuple;
7419 	const char *res;
7420 } unbind_aff_tests[] = {
7421 	{ "[M, N] -> { [M + floor(N/2)] }",
7422 	  "{ A[M, N] }",
7423 	  "{ A[M, N] -> [M + floor(N/2)] }" },
7424 	{ "[M, N] -> { [M + floor(N/2)] }",
7425 	  "{ B[N, M] }",
7426 	  "{ B[N, M] -> [M + floor(N/2)] }" },
7427 	{ "[M, N] -> { [M + floor(N/2)] }",
7428 	  "{ C[N] }",
7429 	  "[M] -> { C[N] -> [M + floor(N/2)] }" },
7430 	{ "[M, N] -> { [M + floor(N/2)] }",
7431 	  "{ D[A, B, C, N, Z] }",
7432 	  "[M] -> { D[A, B, C, N, Z] -> [M + floor(N/2)] }" },
7433 };
7434 
7435 /* Perform basic isl_aff_unbind_params_insert_domain tests.
7436  */
test_unbind_aff(isl_ctx * ctx)7437 static isl_stat test_unbind_aff(isl_ctx *ctx)
7438 {
7439 	int i;
7440 
7441 	for (i = 0; i < ARRAY_SIZE(unbind_aff_tests); ++i) {
7442 		const char *str;
7443 		isl_aff *aff;
7444 		isl_multi_id *tuple;
7445 		isl_stat r;
7446 
7447 		aff = isl_aff_read_from_str(ctx, unbind_aff_tests[i].aff);
7448 		str = unbind_aff_tests[i].tuple;
7449 		tuple = isl_multi_id_read_from_str(ctx, str);
7450 		aff = isl_aff_unbind_params_insert_domain(aff, tuple);
7451 		r = aff_check_plain_equal(aff, unbind_aff_tests[i].res);
7452 		isl_aff_free(aff);
7453 		if (r < 0)
7454 			return isl_stat_error;
7455 	}
7456 
7457 	return isl_stat_ok;
7458 }
7459 
7460 /* Inputs for isl_multi_aff_unbind_params_insert_domain tests.
7461  * "ma" is the input multi affine expression defined over a parameter domain.
7462  * "tuple" is the tuple of the domain that gets introduced.
7463  * "res" is the expected result.
7464  */
7465 static struct {
7466 	const char *ma;
7467 	const char *tuple;
7468 	const char *res;
7469 } unbind_multi_aff_tests[] = {
7470 	{ "[M, N] -> { T[M + floor(N/2)] }",
7471 	  "{ A[M, N] }",
7472 	  "{ A[M, N] -> T[M + floor(N/2)] }" },
7473 	{ "[M, N] -> { [M + floor(N/2)] }",
7474 	  "{ B[N, M] }",
7475 	  "{ B[N, M] -> [M + floor(N/2)] }" },
7476 	{ "[M, N] -> { [M + floor(N/2)] }",
7477 	  "{ C[N] }",
7478 	  "[M] -> { C[N] -> [M + floor(N/2)] }" },
7479 	{ "[M, N] -> { [M + floor(N/2)] }",
7480 	  "{ D[A, B, C, N, Z] }",
7481 	  "[M] -> { D[A, B, C, N, Z] -> [M + floor(N/2)] }" },
7482 	{ "[M, N] -> { T[M + floor(N/2), N + floor(M/3)] }",
7483 	  "{ A[M, N] }",
7484 	  "{ A[M, N] -> T[M + floor(N/2), N + floor(M/3)] }" },
7485 };
7486 
7487 /* Perform basic isl_multi_aff_unbind_params_insert_domain tests.
7488  */
test_unbind_multi_aff(isl_ctx * ctx)7489 static isl_stat test_unbind_multi_aff(isl_ctx *ctx)
7490 {
7491 	int i;
7492 
7493 	for (i = 0; i < ARRAY_SIZE(unbind_multi_aff_tests); ++i) {
7494 		const char *str;
7495 		isl_multi_aff *ma;
7496 		isl_multi_id *tuple;
7497 		isl_stat r;
7498 
7499 		str = unbind_multi_aff_tests[i].ma;
7500 		ma = isl_multi_aff_read_from_str(ctx, str);
7501 		str = unbind_multi_aff_tests[i].tuple;
7502 		tuple = isl_multi_id_read_from_str(ctx, str);
7503 		ma = isl_multi_aff_unbind_params_insert_domain(ma, tuple);
7504 		str = unbind_multi_aff_tests[i].res;
7505 		r = multi_aff_check_plain_equal(ma, str);
7506 		isl_multi_aff_free(ma);
7507 		if (r < 0)
7508 			return isl_stat_error;
7509 	}
7510 
7511 	return isl_stat_ok;
7512 }
7513 
7514 /* Perform tests that reinterpret parameters.
7515  */
test_unbind(isl_ctx * ctx)7516 static int test_unbind(isl_ctx *ctx)
7517 {
7518 	if (test_unbind_set(ctx) < 0)
7519 		return -1;
7520 	if (test_unbind_aff(ctx) < 0)
7521 		return -1;
7522 	if (test_unbind_multi_aff(ctx) < 0)
7523 		return -1;
7524 
7525 	return 0;
7526 }
7527 
7528 /* Check that "pa" consists of a single expression.
7529  */
check_single_piece(isl_ctx * ctx,__isl_take isl_pw_aff * pa)7530 static int check_single_piece(isl_ctx *ctx, __isl_take isl_pw_aff *pa)
7531 {
7532 	isl_size n;
7533 
7534 	n = isl_pw_aff_n_piece(pa);
7535 	isl_pw_aff_free(pa);
7536 
7537 	if (n < 0)
7538 		return -1;
7539 	if (n != 1)
7540 		isl_die(ctx, isl_error_unknown, "expecting single expression",
7541 			return -1);
7542 
7543 	return 0;
7544 }
7545 
7546 /* Check that the computation below results in a single expression.
7547  * One or two expressions may result depending on which constraint
7548  * ends up being considered as redundant with respect to the other
7549  * constraints after the projection that is performed internally
7550  * by isl_set_dim_min.
7551  */
test_dim_max_1(isl_ctx * ctx)7552 static int test_dim_max_1(isl_ctx *ctx)
7553 {
7554 	const char *str;
7555 	isl_set *set;
7556 	isl_pw_aff *pa;
7557 
7558 	str = "[n] -> { [a, b] : n >= 0 and 4a >= -4 + n and b >= 0 and "
7559 				"-4a <= b <= 3 and b < n - 4a }";
7560 	set = isl_set_read_from_str(ctx, str);
7561 	pa = isl_set_dim_min(set, 0);
7562 	return check_single_piece(ctx, pa);
7563 }
7564 
7565 /* Check that the computation below results in a single expression.
7566  * The PIP problem corresponding to these constraints has a row
7567  * that causes a split of the solution domain.  The solver should
7568  * first pick rows that split off empty parts such that the actual
7569  * solution domain does not get split.
7570  * Note that the description contains some redundant constraints.
7571  * If these constraints get removed first, then the row mentioned
7572  * above does not appear in the PIP problem.
7573  */
test_dim_max_2(isl_ctx * ctx)7574 static int test_dim_max_2(isl_ctx *ctx)
7575 {
7576 	const char *str;
7577 	isl_set *set;
7578 	isl_pw_aff *pa;
7579 
7580 	str = "[P, N] -> { [a] : a < N and a >= 0 and N > P and a <= P and "
7581 				"N > 0 and P >= 0 }";
7582 	set = isl_set_read_from_str(ctx, str);
7583 	pa = isl_set_dim_max(set, 0);
7584 	return check_single_piece(ctx, pa);
7585 }
7586 
test_dim_max(isl_ctx * ctx)7587 int test_dim_max(isl_ctx *ctx)
7588 {
7589 	int equal;
7590 	const char *str;
7591 	isl_set *set1, *set2;
7592 	isl_set *set;
7593 	isl_map *map;
7594 	isl_pw_aff *pwaff;
7595 
7596 	if (test_dim_max_1(ctx) < 0)
7597 		return -1;
7598 	if (test_dim_max_2(ctx) < 0)
7599 		return -1;
7600 
7601 	str = "[N] -> { [i] : 0 <= i <= min(N,10) }";
7602 	set = isl_set_read_from_str(ctx, str);
7603 	pwaff = isl_set_dim_max(set, 0);
7604 	set1 = isl_set_from_pw_aff(pwaff);
7605 	str = "[N] -> { [10] : N >= 10; [N] : N <= 9 and N >= 0 }";
7606 	set2 = isl_set_read_from_str(ctx, str);
7607 	equal = isl_set_is_equal(set1, set2);
7608 	isl_set_free(set1);
7609 	isl_set_free(set2);
7610 	if (equal < 0)
7611 		return -1;
7612 	if (!equal)
7613 		isl_die(ctx, isl_error_unknown, "unexpected result", return -1);
7614 
7615 	str = "[N] -> { [i] : 0 <= i <= max(2N,N+6) }";
7616 	set = isl_set_read_from_str(ctx, str);
7617 	pwaff = isl_set_dim_max(set, 0);
7618 	set1 = isl_set_from_pw_aff(pwaff);
7619 	str = "[N] -> { [6 + N] : -6 <= N <= 5; [2N] : N >= 6 }";
7620 	set2 = isl_set_read_from_str(ctx, str);
7621 	equal = isl_set_is_equal(set1, set2);
7622 	isl_set_free(set1);
7623 	isl_set_free(set2);
7624 	if (equal < 0)
7625 		return -1;
7626 	if (!equal)
7627 		isl_die(ctx, isl_error_unknown, "unexpected result", return -1);
7628 
7629 	str = "[N] -> { [i] : 0 <= i <= 2N or 0 <= i <= N+6 }";
7630 	set = isl_set_read_from_str(ctx, str);
7631 	pwaff = isl_set_dim_max(set, 0);
7632 	set1 = isl_set_from_pw_aff(pwaff);
7633 	str = "[N] -> { [6 + N] : -6 <= N <= 5; [2N] : N >= 6 }";
7634 	set2 = isl_set_read_from_str(ctx, str);
7635 	equal = isl_set_is_equal(set1, set2);
7636 	isl_set_free(set1);
7637 	isl_set_free(set2);
7638 	if (equal < 0)
7639 		return -1;
7640 	if (!equal)
7641 		isl_die(ctx, isl_error_unknown, "unexpected result", return -1);
7642 
7643 	str = "[N,M] -> { [i,j] -> [([i/16]), i%16, ([j/16]), j%16] : "
7644 			"0 <= i < N and 0 <= j < M }";
7645 	map = isl_map_read_from_str(ctx, str);
7646 	set = isl_map_range(map);
7647 
7648 	pwaff = isl_set_dim_max(isl_set_copy(set), 0);
7649 	set1 = isl_set_from_pw_aff(pwaff);
7650 	str = "[N,M] -> { [([(N-1)/16])] : M,N > 0 }";
7651 	set2 = isl_set_read_from_str(ctx, str);
7652 	equal = isl_set_is_equal(set1, set2);
7653 	isl_set_free(set1);
7654 	isl_set_free(set2);
7655 
7656 	pwaff = isl_set_dim_max(isl_set_copy(set), 3);
7657 	set1 = isl_set_from_pw_aff(pwaff);
7658 	str = "[N,M] -> { [t] : t = min(M-1,15) and M,N > 0 }";
7659 	set2 = isl_set_read_from_str(ctx, str);
7660 	if (equal >= 0 && equal)
7661 		equal = isl_set_is_equal(set1, set2);
7662 	isl_set_free(set1);
7663 	isl_set_free(set2);
7664 
7665 	isl_set_free(set);
7666 
7667 	if (equal < 0)
7668 		return -1;
7669 	if (!equal)
7670 		isl_die(ctx, isl_error_unknown, "unexpected result", return -1);
7671 
7672 	/* Check that solutions are properly merged. */
7673 	str = "[n] -> { [a, b, c] : c >= -4a - 2b and "
7674 				"c <= -1 + n - 4a - 2b and c >= -2b and "
7675 				"4a >= -4 + n and c >= 0 }";
7676 	set = isl_set_read_from_str(ctx, str);
7677 	pwaff = isl_set_dim_min(set, 2);
7678 	set1 = isl_set_from_pw_aff(pwaff);
7679 	str = "[n] -> { [(0)] : n >= 1 }";
7680 	set2 = isl_set_read_from_str(ctx, str);
7681 	equal = isl_set_is_equal(set1, set2);
7682 	isl_set_free(set1);
7683 	isl_set_free(set2);
7684 
7685 	if (equal < 0)
7686 		return -1;
7687 	if (!equal)
7688 		isl_die(ctx, isl_error_unknown, "unexpected result", return -1);
7689 
7690 	/* Check that empty solution lie in the right space. */
7691 	str = "[n] -> { [t,a] : 1 = 0 }";
7692 	set = isl_set_read_from_str(ctx, str);
7693 	pwaff = isl_set_dim_max(set, 0);
7694 	set1 = isl_set_from_pw_aff(pwaff);
7695 	str = "[n] -> { [t] : 1 = 0 }";
7696 	set2 = isl_set_read_from_str(ctx, str);
7697 	equal = isl_set_is_equal(set1, set2);
7698 	isl_set_free(set1);
7699 	isl_set_free(set2);
7700 
7701 	if (equal < 0)
7702 		return -1;
7703 	if (!equal)
7704 		isl_die(ctx, isl_error_unknown, "unexpected result", return -1);
7705 
7706 	return 0;
7707 }
7708 
7709 /* Basic test for isl_pw_multi_aff_product.
7710  *
7711  * Check that multiple pieces are properly handled.
7712  */
test_product_pma(isl_ctx * ctx)7713 static int test_product_pma(isl_ctx *ctx)
7714 {
7715 	isl_stat equal;
7716 	const char *str;
7717 	isl_pw_multi_aff *pma1, *pma2;
7718 
7719 	str = "{ A[i] -> B[1] : i < 0; A[i] -> B[2] : i >= 0 }";
7720 	pma1 = isl_pw_multi_aff_read_from_str(ctx, str);
7721 	str = "{ C[] -> D[] }";
7722 	pma2 = isl_pw_multi_aff_read_from_str(ctx, str);
7723 	pma1 = isl_pw_multi_aff_product(pma1, pma2);
7724 	str = "{ [A[i] -> C[]] -> [B[(1)] -> D[]] : i < 0;"
7725 		"[A[i] -> C[]] -> [B[(2)] -> D[]] : i >= 0 }";
7726 	equal = pw_multi_aff_check_plain_equal(pma1, str);
7727 	isl_pw_multi_aff_free(pma1);
7728 	if (equal < 0)
7729 		return -1;
7730 
7731 	return 0;
7732 }
7733 
test_product(isl_ctx * ctx)7734 int test_product(isl_ctx *ctx)
7735 {
7736 	const char *str;
7737 	isl_set *set;
7738 	isl_union_set *uset1, *uset2;
7739 	int ok;
7740 
7741 	str = "{ A[i] }";
7742 	set = isl_set_read_from_str(ctx, str);
7743 	set = isl_set_product(set, isl_set_copy(set));
7744 	ok = isl_set_is_wrapping(set);
7745 	isl_set_free(set);
7746 	if (ok < 0)
7747 		return -1;
7748 	if (!ok)
7749 		isl_die(ctx, isl_error_unknown, "unexpected result", return -1);
7750 
7751 	str = "{ [] }";
7752 	uset1 = isl_union_set_read_from_str(ctx, str);
7753 	uset1 = isl_union_set_product(uset1, isl_union_set_copy(uset1));
7754 	str = "{ [[] -> []] }";
7755 	uset2 = isl_union_set_read_from_str(ctx, str);
7756 	ok = isl_union_set_is_equal(uset1, uset2);
7757 	isl_union_set_free(uset1);
7758 	isl_union_set_free(uset2);
7759 	if (ok < 0)
7760 		return -1;
7761 	if (!ok)
7762 		isl_die(ctx, isl_error_unknown, "unexpected result", return -1);
7763 
7764 	if (test_product_pma(ctx) < 0)
7765 		return -1;
7766 
7767 	return 0;
7768 }
7769 
7770 /* Check that two sets are not considered disjoint just because
7771  * they have a different set of (named) parameters.
7772  */
test_disjoint(isl_ctx * ctx)7773 static int test_disjoint(isl_ctx *ctx)
7774 {
7775 	const char *str;
7776 	isl_set *set, *set2;
7777 	int disjoint;
7778 
7779 	str = "[n] -> { [[]->[]] }";
7780 	set = isl_set_read_from_str(ctx, str);
7781 	str = "{ [[]->[]] }";
7782 	set2 = isl_set_read_from_str(ctx, str);
7783 	disjoint = isl_set_is_disjoint(set, set2);
7784 	isl_set_free(set);
7785 	isl_set_free(set2);
7786 	if (disjoint < 0)
7787 		return -1;
7788 	if (disjoint)
7789 		isl_die(ctx, isl_error_unknown, "unexpected result", return -1);
7790 
7791 	return 0;
7792 }
7793 
7794 /* Inputs for isl_pw_multi_aff_is_equal tests.
7795  * "f1" and "f2" are the two function that need to be compared.
7796  * "equal" is the expected result.
7797  */
7798 struct {
7799 	int equal;
7800 	const char *f1;
7801 	const char *f2;
7802 } pma_equal_tests[] = {
7803 	{ 1, "[N] -> { [floor(N/2)] : 0 <= N <= 1 }",
7804 	     "[N] -> { [0] : 0 <= N <= 1 }" },
7805 	{ 1, "[N] -> { [floor(N/2)] : 0 <= N <= 2 }",
7806 	     "[N] -> { [0] : 0 <= N <= 1; [1] : N = 2 }" },
7807 	{ 0, "[N] -> { [floor(N/2)] : 0 <= N <= 2 }",
7808 	     "[N] -> { [0] : 0 <= N <= 1 }" },
7809 	{ 0, "{ [NaN] }", "{ [NaN] }" },
7810 };
7811 
test_equal(isl_ctx * ctx)7812 int test_equal(isl_ctx *ctx)
7813 {
7814 	int i;
7815 	const char *str;
7816 	isl_set *set, *set2;
7817 	int equal;
7818 
7819 	str = "{ S_6[i] }";
7820 	set = isl_set_read_from_str(ctx, str);
7821 	str = "{ S_7[i] }";
7822 	set2 = isl_set_read_from_str(ctx, str);
7823 	equal = isl_set_is_equal(set, set2);
7824 	isl_set_free(set);
7825 	isl_set_free(set2);
7826 	if (equal < 0)
7827 		return -1;
7828 	if (equal)
7829 		isl_die(ctx, isl_error_unknown, "unexpected result", return -1);
7830 
7831 	for (i = 0; i < ARRAY_SIZE(pma_equal_tests); ++i) {
7832 		int expected = pma_equal_tests[i].equal;
7833 		isl_pw_multi_aff *f1, *f2;
7834 
7835 		f1 = isl_pw_multi_aff_read_from_str(ctx, pma_equal_tests[i].f1);
7836 		f2 = isl_pw_multi_aff_read_from_str(ctx, pma_equal_tests[i].f2);
7837 		equal = isl_pw_multi_aff_is_equal(f1, f2);
7838 		isl_pw_multi_aff_free(f1);
7839 		isl_pw_multi_aff_free(f2);
7840 		if (equal < 0)
7841 			return -1;
7842 		if (equal != expected)
7843 			isl_die(ctx, isl_error_unknown,
7844 				"unexpected equality result", return -1);
7845 	}
7846 
7847 	return 0;
7848 }
7849 
test_plain_fixed(isl_ctx * ctx,__isl_take isl_map * map,enum isl_dim_type type,unsigned pos,int fixed)7850 static int test_plain_fixed(isl_ctx *ctx, __isl_take isl_map *map,
7851 	enum isl_dim_type type, unsigned pos, int fixed)
7852 {
7853 	isl_bool test;
7854 
7855 	test = isl_map_plain_is_fixed(map, type, pos, NULL);
7856 	isl_map_free(map);
7857 	if (test < 0)
7858 		return -1;
7859 	if (test == fixed)
7860 		return 0;
7861 	if (fixed)
7862 		isl_die(ctx, isl_error_unknown,
7863 			"map not detected as fixed", return -1);
7864 	else
7865 		isl_die(ctx, isl_error_unknown,
7866 			"map detected as fixed", return -1);
7867 }
7868 
test_fixed(isl_ctx * ctx)7869 int test_fixed(isl_ctx *ctx)
7870 {
7871 	const char *str;
7872 	isl_map *map;
7873 
7874 	str = "{ [i] -> [i] }";
7875 	map = isl_map_read_from_str(ctx, str);
7876 	if (test_plain_fixed(ctx, map, isl_dim_out, 0, 0))
7877 		return -1;
7878 	str = "{ [i] -> [1] }";
7879 	map = isl_map_read_from_str(ctx, str);
7880 	if (test_plain_fixed(ctx, map, isl_dim_out, 0, 1))
7881 		return -1;
7882 	str = "{ S_1[p1] -> [o0] : o0 = -2 and p1 >= 1 and p1 <= 7 }";
7883 	map = isl_map_read_from_str(ctx, str);
7884 	if (test_plain_fixed(ctx, map, isl_dim_out, 0, 1))
7885 		return -1;
7886 	map = isl_map_read_from_str(ctx, str);
7887 	map = isl_map_neg(map);
7888 	if (test_plain_fixed(ctx, map, isl_dim_out, 0, 1))
7889 		return -1;
7890 
7891 	return 0;
7892 }
7893 
7894 struct isl_vertices_test_data {
7895 	const char *set;
7896 	int n;
7897 	const char *vertex[6];
7898 } vertices_tests[] = {
7899 	{ "{ A[t, i] : t = 12 and i >= 4 and i <= 12 }",
7900 	  2, { "{ A[12, 4] }", "{ A[12, 12] }" } },
7901 	{ "{ A[t, i] : t = 14 and i = 1 }",
7902 	  1, { "{ A[14, 1] }" } },
7903 	{ "[n, m] -> { [a, b, c] : b <= a and a <= n and b > 0 and c >= b and "
7904 				"c <= m and m <= n and m > 0 }",
7905 	  6, {
7906 		"[n, m] -> { [n, m, m] : 0 < m <= n }",
7907 		"[n, m] -> { [n, 1, m] : 0 < m <= n }",
7908 		"[n, m] -> { [n, 1, 1] : 0 < m <= n }",
7909 		"[n, m] -> { [m, m, m] : 0 < m <= n }",
7910 		"[n, m] -> { [1, 1, m] : 0 < m <= n }",
7911 		"[n, m] -> { [1, 1, 1] : 0 < m <= n }"
7912 	    } },
7913 	/* An input with implicit equality constraints among the parameters. */
7914 	{ "[N, M] -> { [a, b] : M >= 3 and 9 + 3M <= a <= 29 + 2N + 11M and "
7915 			    "2b >= M + a and 5 - 2N - M + a <= 2b <= 3 + a and "
7916 			    "3b >= 15 + a }",
7917 	  2, {
7918 		"[N, M] -> { [(21), (12)] : M = 3 and N >= 0 }",
7919 		"[N, M] -> { [(61 + 2N), (32 + N)] : M = 3 and N >= 0 }",
7920 	     }
7921 	},
7922 };
7923 
7924 /* Check that "vertex" corresponds to one of the vertices in data->vertex.
7925  */
find_vertex(__isl_take isl_vertex * vertex,void * user)7926 static isl_stat find_vertex(__isl_take isl_vertex *vertex, void *user)
7927 {
7928 	struct isl_vertices_test_data *data = user;
7929 	isl_ctx *ctx;
7930 	isl_multi_aff *ma;
7931 	isl_basic_set *bset;
7932 	isl_pw_multi_aff *pma;
7933 	int i;
7934 	isl_bool equal;
7935 
7936 	ctx = isl_vertex_get_ctx(vertex);
7937 	bset = isl_vertex_get_domain(vertex);
7938 	ma = isl_vertex_get_expr(vertex);
7939 	pma = isl_pw_multi_aff_alloc(isl_set_from_basic_set(bset), ma);
7940 
7941 	for (i = 0; i < data->n; ++i) {
7942 		isl_pw_multi_aff *pma_i;
7943 
7944 		pma_i = isl_pw_multi_aff_read_from_str(ctx, data->vertex[i]);
7945 		equal = isl_pw_multi_aff_plain_is_equal(pma, pma_i);
7946 		isl_pw_multi_aff_free(pma_i);
7947 
7948 		if (equal < 0 || equal)
7949 			break;
7950 	}
7951 
7952 	isl_pw_multi_aff_free(pma);
7953 	isl_vertex_free(vertex);
7954 
7955 	if (equal < 0)
7956 		return isl_stat_error;
7957 
7958 	return equal ? isl_stat_ok : isl_stat_error;
7959 }
7960 
test_vertices(isl_ctx * ctx)7961 int test_vertices(isl_ctx *ctx)
7962 {
7963 	int i;
7964 
7965 	for (i = 0; i < ARRAY_SIZE(vertices_tests); ++i) {
7966 		isl_basic_set *bset;
7967 		isl_vertices *vertices;
7968 		int ok = 1;
7969 		isl_size n;
7970 
7971 		bset = isl_basic_set_read_from_str(ctx, vertices_tests[i].set);
7972 		vertices = isl_basic_set_compute_vertices(bset);
7973 		n = isl_vertices_get_n_vertices(vertices);
7974 		if (vertices_tests[i].n != n)
7975 			ok = 0;
7976 		if (isl_vertices_foreach_vertex(vertices, &find_vertex,
7977 						&vertices_tests[i]) < 0)
7978 			ok = 0;
7979 		isl_vertices_free(vertices);
7980 		isl_basic_set_free(bset);
7981 
7982 		if (n < 0)
7983 			return -1;
7984 		if (!ok)
7985 			isl_die(ctx, isl_error_unknown, "unexpected vertices",
7986 				return -1);
7987 	}
7988 
7989 	return 0;
7990 }
7991 
7992 /* Inputs for basic tests of unary operations on isl_union_map.
7993  * "fn" is the function that is being tested.
7994  * "arg" is a string description of the input.
7995  * "res" is a string description of the expected result.
7996  */
7997 static struct {
7998 	__isl_give isl_union_map *(*fn)(__isl_take isl_union_map *umap);
7999 	const char *arg;
8000 	const char *res;
8001 } umap_un_tests[] = {
8002 	{ &isl_union_map_range_reverse,
8003 	  "{ A[] -> [B[] -> C[]]; A[] -> B[]; A[0] -> N[B[1] -> B[2]] }",
8004 	  "{ A[] -> [C[] -> B[]]; A[0] -> N[B[2] -> B[1]] }" },
8005 	{ &isl_union_map_range_reverse,
8006 	  "{ A[] -> N[B[] -> C[]] }",
8007 	  "{ A[] -> [C[] -> B[]] }" },
8008 	{ &isl_union_map_range_reverse,
8009 	  "{ A[] -> N[B[x] -> B[y]] }",
8010 	  "{ A[] -> N[B[*] -> B[*]] }" },
8011 };
8012 
8013 /* Perform basic tests of unary operations on isl_union_map.
8014  */
test_un_union_map(isl_ctx * ctx)8015 static isl_stat test_un_union_map(isl_ctx *ctx)
8016 {
8017 	int i;
8018 
8019 	for (i = 0; i < ARRAY_SIZE(umap_un_tests); ++i) {
8020 		const char *str;
8021 		isl_union_map *umap, *res;
8022 		isl_bool equal;
8023 
8024 		str = umap_un_tests[i].arg;
8025 		umap = isl_union_map_read_from_str(ctx, str);
8026 		str = umap_un_tests[i].res;
8027 		res = isl_union_map_read_from_str(ctx, str);
8028 		umap = umap_un_tests[i].fn(umap);
8029 		equal = isl_union_map_is_equal(umap, res);
8030 		isl_union_map_free(umap);
8031 		isl_union_map_free(res);
8032 		if (equal < 0)
8033 			return isl_stat_error;
8034 		if (!equal)
8035 			isl_die(ctx, isl_error_unknown,
8036 				"unexpected result", return isl_stat_error);
8037 	}
8038 
8039 	return isl_stat_ok;
8040 }
8041 
8042 /* Inputs for basic tests of binary operations on isl_union_map.
8043  * "fn" is the function that is being tested.
8044  * "arg1" and "arg2" are string descriptions of the inputs.
8045  * "res" is a string description of the expected result.
8046  */
8047 static struct {
8048 	__isl_give isl_union_map *(*fn)(__isl_take isl_union_map *umap1,
8049 				__isl_take isl_union_map *umap2);
8050 	const char *arg1;
8051 	const char *arg2;
8052 	const char *res;
8053 } umap_bin_tests[] = {
8054 	{ &isl_union_map_intersect,
8055 	  "[n] -> { A[i] -> [] : 0 <= i <= n; B[] -> [] }",
8056 	  "[m] -> { A[i] -> [] : 0 <= i <= m; C[] -> [] }",
8057 	  "[m, n] -> { A[i] -> [] : 0 <= i <= n and i <= m }" },
8058 	{ &isl_union_map_intersect_domain_factor_domain,
8059 	  "{ [A[i] -> B[i + 1]] -> C[i + 2] }",
8060 	  "[N] -> { B[i] -> C[N] }",
8061 	  "{ }" },
8062 	{ &isl_union_map_intersect_domain_factor_domain,
8063 	  "{ [A[i] -> B[i + 1]] -> C[i + 2] }",
8064 	  "[N] -> { A[i] -> C[N] }",
8065 	  "[N] -> { [A[N - 2] -> B[N - 1]] -> C[N] }" },
8066 	{ &isl_union_map_intersect_domain_factor_domain,
8067 	  "{ T[A[i] -> B[i + 1]] -> C[i + 2] }",
8068 	  "[N] -> { A[i] -> C[N] }",
8069 	  "[N] -> { T[A[N - 2] -> B[N - 1]] -> C[N] }" },
8070 	{ &isl_union_map_intersect_domain_factor_range,
8071 	  "{ [A[i] -> B[i + 1]] -> C[i + 2] }",
8072 	  "[N] -> { B[i] -> C[N] }",
8073 	  "[N] -> { [A[N - 2] -> B[N - 1]] -> C[N] }" },
8074 	{ &isl_union_map_intersect_domain_factor_range,
8075 	  "{ T[A[i] -> B[i + 1]] -> C[i + 2] }",
8076 	  "[N] -> { B[i] -> C[N] }",
8077 	  "[N] -> { T[A[N - 2] -> B[N - 1]] -> C[N] }" },
8078 	{ &isl_union_map_intersect_domain_factor_range,
8079 	  "{ [A[i] -> B[i + 1]] -> C[i + 2] }",
8080 	  "[N] -> { A[i] -> C[N] }",
8081 	  "{ }" },
8082 	{ &isl_union_map_intersect_range_factor_domain,
8083 	  "{ A[i] -> [B[i + 1] -> C[i + 2]] }",
8084 	  "[N] -> { A[i] -> B[N] }",
8085 	  "[N] -> { A[N - 1] -> [B[N] -> C[N + 1]] }" },
8086 	{ &isl_union_map_intersect_range_factor_domain,
8087 	  "{ A[i] -> T[B[i + 1] -> C[i + 2]] }",
8088 	  "[N] -> { A[i] -> B[N] }",
8089 	  "[N] -> { A[N - 1] -> T[B[N] -> C[N + 1]] }" },
8090 	{ &isl_union_map_intersect_range_factor_domain,
8091 	  "{ A[i] -> [B[i + 1] -> C[i + 2]] }",
8092 	  "[N] -> { A[i] -> C[N] }",
8093 	  "{ }" },
8094 	{ &isl_union_map_intersect_range_factor_range,
8095 	  "{ A[i] -> [B[i + 1] -> C[i + 2]] }",
8096 	  "[N] -> { A[i] -> C[N] }",
8097 	  "[N] -> { A[N - 2] -> [B[N - 1] -> C[N]] }" },
8098 	{ &isl_union_map_intersect_range_factor_range,
8099 	  "{ A[i] -> T[B[i + 1] -> C[i + 2]] }",
8100 	  "[N] -> { A[i] -> C[N] }",
8101 	  "[N] -> { A[N - 2] -> T[B[N - 1] -> C[N]] }" },
8102 	{ &isl_union_map_intersect_range_factor_range,
8103 	  "{ A[i] -> [B[i + 1] -> C[i + 2]] }",
8104 	  "[N] -> { A[i] -> B[N] }",
8105 	  "{ }" },
8106 };
8107 
8108 /* Perform basic tests of binary operations on isl_union_map.
8109  */
test_bin_union_map(isl_ctx * ctx)8110 static isl_stat test_bin_union_map(isl_ctx *ctx)
8111 {
8112 	int i;
8113 
8114 	for (i = 0; i < ARRAY_SIZE(umap_bin_tests); ++i) {
8115 		const char *str;
8116 		isl_union_map *umap1, *umap2, *res;
8117 		isl_bool equal;
8118 
8119 		str = umap_bin_tests[i].arg1;
8120 		umap1 = isl_union_map_read_from_str(ctx, str);
8121 		str = umap_bin_tests[i].arg2;
8122 		umap2 = isl_union_map_read_from_str(ctx, str);
8123 		str = umap_bin_tests[i].res;
8124 		res = isl_union_map_read_from_str(ctx, str);
8125 		umap1 = umap_bin_tests[i].fn(umap1, umap2);
8126 		equal = isl_union_map_is_equal(umap1, res);
8127 		isl_union_map_free(umap1);
8128 		isl_union_map_free(res);
8129 		if (equal < 0)
8130 			return isl_stat_error;
8131 		if (!equal)
8132 			isl_die(ctx, isl_error_unknown,
8133 				"unexpected result", return isl_stat_error);
8134 	}
8135 
8136 	return isl_stat_ok;
8137 }
8138 
8139 /* Check that isl_union_set_contains finds space independently
8140  * of the parameters.
8141  */
test_union_set_contains(isl_ctx * ctx)8142 static isl_stat test_union_set_contains(isl_ctx *ctx)
8143 {
8144 	const char *str;
8145 	isl_bool ok;
8146 	isl_space *space;
8147 	isl_id *id;
8148 	isl_union_set *uset;
8149 
8150 	str = "[N] -> { A[0:N]; B[*,*] }";
8151 	uset = isl_union_set_read_from_str(ctx, str);
8152 	space = isl_space_unit(ctx);
8153 	id = isl_id_alloc(ctx, "A", NULL);
8154 	space = isl_space_add_named_tuple_id_ui(space, id, 1);
8155 	ok = isl_union_set_contains(uset, space);
8156 	isl_space_free(space);
8157 	isl_union_set_free(uset);
8158 
8159 	if (ok < 0)
8160 		return isl_stat_error;
8161 	if (!ok)
8162 		isl_die(ctx, isl_error_unknown,
8163 			"unexpected result", return isl_stat_error);
8164 
8165 	return isl_stat_ok;
8166 }
8167 
8168 /* Perform basic tests of operations on isl_union_map or isl_union_set.
8169  */
test_union_map(isl_ctx * ctx)8170 static int test_union_map(isl_ctx *ctx)
8171 {
8172 	if (test_un_union_map(ctx) < 0)
8173 		return -1;
8174 	if (test_bin_union_map(ctx) < 0)
8175 		return -1;
8176 	if (test_union_set_contains(ctx) < 0)
8177 		return -1;
8178 	return 0;
8179 }
8180 
test_union_pw(isl_ctx * ctx)8181 int test_union_pw(isl_ctx *ctx)
8182 {
8183 	int equal;
8184 	const char *str;
8185 	isl_union_set *uset;
8186 	isl_union_pw_qpolynomial *upwqp1, *upwqp2;
8187 
8188 	str = "{ [x] -> x^2 }";
8189 	upwqp1 = isl_union_pw_qpolynomial_read_from_str(ctx, str);
8190 	upwqp2 = isl_union_pw_qpolynomial_copy(upwqp1);
8191 	uset = isl_union_pw_qpolynomial_domain(upwqp1);
8192 	upwqp1 = isl_union_pw_qpolynomial_copy(upwqp2);
8193 	upwqp1 = isl_union_pw_qpolynomial_intersect_domain(upwqp1, uset);
8194 	equal = isl_union_pw_qpolynomial_plain_is_equal(upwqp1, upwqp2);
8195 	isl_union_pw_qpolynomial_free(upwqp1);
8196 	isl_union_pw_qpolynomial_free(upwqp2);
8197 	if (equal < 0)
8198 		return -1;
8199 	if (!equal)
8200 		isl_die(ctx, isl_error_unknown, "unexpected result", return -1);
8201 
8202 	return 0;
8203 }
8204 
8205 /* Inputs for basic tests of functions that select
8206  * subparts of the domain of an isl_multi_union_pw_aff.
8207  * "fn" is the function that is tested.
8208  * "arg" is a string description of the input.
8209  * "res" is a string description of the expected result.
8210  */
8211 struct {
8212 	__isl_give isl_union_set *(*fn)(
8213 		__isl_take isl_multi_union_pw_aff *mupa);
8214 	const char *arg;
8215 	const char *res;
8216 } un_locus_tests[] = {
8217 	{ &isl_multi_union_pw_aff_zero_union_set,
8218 	  "F[{ A[i,j] -> [i]; B[i,j] -> [i] }]",
8219 	  "{ A[0,j]; B[0,j] }" },
8220 	{ &isl_multi_union_pw_aff_zero_union_set,
8221 	  "F[{ A[i,j] -> [i-j]; B[i,j] -> [i-j] : i >= 0 }]",
8222 	  "{ A[i,i]; B[i,i] : i >= 0 }" },
8223 	{ &isl_multi_union_pw_aff_zero_union_set,
8224 	  "(F[] : { A[i,j]; B[i,i] : i >= 0 })",
8225 	  "{ A[i,j]; B[i,i] : i >= 0 }" },
8226 };
8227 
8228 /* Perform some basic tests of functions that select
8229  * subparts of the domain of an isl_multi_union_pw_aff.
8230  */
test_un_locus(isl_ctx * ctx)8231 static int test_un_locus(isl_ctx *ctx)
8232 {
8233 	int i;
8234 	isl_bool ok;
8235 	isl_union_set *uset, *res;
8236 	isl_multi_union_pw_aff *mupa;
8237 
8238 	for (i = 0; i < ARRAY_SIZE(un_locus_tests); ++i) {
8239 		mupa = isl_multi_union_pw_aff_read_from_str(ctx,
8240 						    un_locus_tests[i].arg);
8241 		res = isl_union_set_read_from_str(ctx, un_locus_tests[i].res);
8242 		uset = un_locus_tests[i].fn(mupa);
8243 		ok = isl_union_set_is_equal(uset, res);
8244 		isl_union_set_free(uset);
8245 		isl_union_set_free(res);
8246 		if (ok < 0)
8247 			return -1;
8248 		if (!ok)
8249 			isl_die(ctx, isl_error_unknown,
8250 				"unexpected result", return -1);
8251 	}
8252 
8253 	return 0;
8254 }
8255 
8256 /* Inputs for basic tests of functions that select
8257  * subparts of an isl_union_map based on a relation
8258  * specified by an isl_multi_union_pw_aff.
8259  * "fn" is the function that is tested.
8260  * "arg1" and "arg2" are string descriptions of the inputs.
8261  * "res" is a string description of the expected result.
8262  */
8263 struct {
8264 	__isl_give isl_union_map *(*fn)(
8265 		__isl_take isl_union_map *umap,
8266 		__isl_take isl_multi_union_pw_aff *mupa);
8267 	const char *arg1;
8268 	const char *arg2;
8269 	const char *res;
8270 } bin_locus_tests[] = {
8271 	{ &isl_union_map_eq_at_multi_union_pw_aff,
8272 	  "{ A[i,j] -> B[i',j'] }",
8273 	  "F[{ A[i,j] -> [i]; B[i,j] -> [i] }]",
8274 	  "{ A[i,j] -> B[i,j'] }" },
8275 	{ &isl_union_map_eq_at_multi_union_pw_aff,
8276 	  "{ A[i,j] -> B[i',j'] }",
8277 	  "F[{ A[i,j] -> [i]; B[i,j] -> [i] }, "
8278 	    "{ A[i,j] -> [j]; B[i,j] -> [j] }]",
8279 	  "{ A[i,j] -> B[i,j] }" },
8280 	{ &isl_union_map_eq_at_multi_union_pw_aff,
8281 	  "{ A[i,j] -> B[i',j']; A[i,j] -> C[i',j'] }",
8282 	  "F[{ A[i,j] -> [i]; B[i,j] -> [i] }]",
8283 	  "{ A[i,j] -> B[i,j'] }" },
8284 	{ &isl_union_map_eq_at_multi_union_pw_aff,
8285 	  "{ A[i,j] -> B[i',j']; A[i,j] -> C[i',j'] }",
8286 	  "F[{ A[i,j] -> [i]; B[i,j] -> [i]; C[i,j] -> [0] }]",
8287 	  "{ A[i,j] -> B[i,j']; A[0,j] -> C[i',j'] }" },
8288 	{ &isl_union_map_eq_at_multi_union_pw_aff,
8289 	  "{ A[i,j] -> B[i',j'] }",
8290 	  "F[{ A[i,j] -> [i] : i > j; B[i,j] -> [i] }]",
8291 	  "{ A[i,j] -> B[i,j'] : i > j }" },
8292 	{ &isl_union_map_lex_le_at_multi_union_pw_aff,
8293 	  "{ A[i,j] -> B[i',j'] }",
8294 	  "F[{ A[i,j] -> [i]; B[i,j] -> [i] }, "
8295 	    "{ A[i,j] -> [j]; B[i,j] -> [j] }]",
8296 	  "{ A[i,j] -> B[i',j'] : i,j <<= i',j' }" },
8297 	{ &isl_union_map_lex_lt_at_multi_union_pw_aff,
8298 	  "{ A[i,j] -> B[i',j'] }",
8299 	  "F[{ A[i,j] -> [i]; B[i,j] -> [i] }, "
8300 	    "{ A[i,j] -> [j]; B[i,j] -> [j] }]",
8301 	  "{ A[i,j] -> B[i',j'] : i,j << i',j' }" },
8302 	{ &isl_union_map_lex_ge_at_multi_union_pw_aff,
8303 	  "{ A[i,j] -> B[i',j'] }",
8304 	  "F[{ A[i,j] -> [i]; B[i,j] -> [i] }, "
8305 	    "{ A[i,j] -> [j]; B[i,j] -> [j] }]",
8306 	  "{ A[i,j] -> B[i',j'] : i,j >>= i',j' }" },
8307 	{ &isl_union_map_lex_gt_at_multi_union_pw_aff,
8308 	  "{ A[i,j] -> B[i',j'] }",
8309 	  "F[{ A[i,j] -> [i]; B[i,j] -> [i] }, "
8310 	    "{ A[i,j] -> [j]; B[i,j] -> [j] }]",
8311 	  "{ A[i,j] -> B[i',j'] : i,j >> i',j' }" },
8312 	{ &isl_union_map_eq_at_multi_union_pw_aff,
8313 	  "{ A[i,j] -> B[i',j']; A[i,j] -> C[i',j'] }",
8314 	  "(F[] : { A[i,j]; B[i,j] })",
8315 	  "{ A[i,j] -> B[i',j'] }" },
8316 	{ &isl_union_map_eq_at_multi_union_pw_aff,
8317 	  "{ A[i,j] -> B[i',j'] }",
8318 	  "(F[] : { A[i,j] : i > j; B[i,j] : i < j })",
8319 	  "{ A[i,j] -> B[i',j'] : i > j and i' < j' }" },
8320 	{ &isl_union_map_eq_at_multi_union_pw_aff,
8321 	  "[N] -> { A[i,j] -> B[i',j'] : i,i' <= N }",
8322 	  "(F[] : { A[i,j] : i > j; B[i,j] : i < j })",
8323 	  "[N] -> { A[i,j] -> B[i',j'] : i > j and i' < j' and i,i' <= N }" },
8324 	{ &isl_union_map_eq_at_multi_union_pw_aff,
8325 	  "{ A[i,j] -> B[i',j'] }",
8326 	  "[N] -> (F[] : { A[i,j] : i < N; B[i,j] : i < N })",
8327 	  "[N] -> { A[i,j] -> B[i',j'] : i,i' < N }" },
8328 	{ &isl_union_map_eq_at_multi_union_pw_aff,
8329 	  "{ A[i,j] -> B[i',j'] }",
8330 	  "[N] -> (F[] : { : N >= 0 })",
8331 	  "[N] -> { A[i,j] -> B[i',j'] : N >= 0 }" },
8332 };
8333 
8334 /* Perform some basic tests of functions that select
8335  * subparts of an isl_union_map based on a relation
8336  * specified by an isl_multi_union_pw_aff.
8337  */
test_bin_locus(isl_ctx * ctx)8338 static int test_bin_locus(isl_ctx *ctx)
8339 {
8340 	int i;
8341 	isl_bool ok;
8342 	isl_union_map *umap, *res;
8343 	isl_multi_union_pw_aff *mupa;
8344 
8345 	for (i = 0; i < ARRAY_SIZE(bin_locus_tests); ++i) {
8346 		umap = isl_union_map_read_from_str(ctx,
8347 						    bin_locus_tests[i].arg1);
8348 		mupa = isl_multi_union_pw_aff_read_from_str(ctx,
8349 						    bin_locus_tests[i].arg2);
8350 		res = isl_union_map_read_from_str(ctx, bin_locus_tests[i].res);
8351 		umap = bin_locus_tests[i].fn(umap, mupa);
8352 		ok = isl_union_map_is_equal(umap, res);
8353 		isl_union_map_free(umap);
8354 		isl_union_map_free(res);
8355 		if (ok < 0)
8356 			return -1;
8357 		if (!ok)
8358 			isl_die(ctx, isl_error_unknown,
8359 				"unexpected result", return -1);
8360 	}
8361 
8362 	return 0;
8363 }
8364 
8365 /* Inputs for basic tests of functions that determine
8366  * the part of the domain where two isl_multi_aff objects
8367  * related to each other in a specific way.
8368  * "fn" is the function that is being tested.
8369  * "arg1" and "arg2" are string descriptions of the inputs.
8370  * "res" is a string description of the expected result.
8371  */
8372 static struct {
8373 	__isl_give isl_set *(*fn)(__isl_take isl_multi_aff *ma1,
8374 		__isl_take isl_multi_aff *ma2);
8375 	const char *arg1;
8376 	const char *arg2;
8377 	const char *res;
8378 } bin_locus_ma_tests[] = {
8379 	{ &isl_multi_aff_lex_le_set, "{ [] }", "{ [] }", "{ : }" },
8380 	{ &isl_multi_aff_lex_lt_set, "{ [] }", "{ [] }", "{ : false }" },
8381 	{ &isl_multi_aff_lex_le_set,
8382 	  "{ A[i] -> [i] }", "{ A[i] -> [0] }",
8383 	  "{ A[i] : i <= 0 }" },
8384 	{ &isl_multi_aff_lex_lt_set,
8385 	  "{ A[i] -> [i] }", "{ A[i] -> [0] }",
8386 	  "{ A[i] : i < 0 }" },
8387 	{ &isl_multi_aff_lex_le_set,
8388 	  "{ A[i] -> [i, i] }", "{ A[i] -> [0, 0] }",
8389 	  "{ A[i] : i <= 0 }" },
8390 	{ &isl_multi_aff_lex_le_set,
8391 	  "{ A[i] -> [i, 0] }", "{ A[i] -> [0, 0] }",
8392 	  "{ A[i] : i <= 0 }" },
8393 	{ &isl_multi_aff_lex_le_set,
8394 	  "{ A[i] -> [i, 1] }", "{ A[i] -> [0, 0] }",
8395 	  "{ A[i] : i < 0 }" },
8396 };
8397 
8398 /* Perform some basic tests of functions that determine
8399  * the part of the domain where two isl_multi_aff objects
8400  * related to each other in a specific way.
8401  */
test_bin_locus_ma(isl_ctx * ctx)8402 static isl_stat test_bin_locus_ma(isl_ctx *ctx)
8403 {
8404 	int i;
8405 
8406 	for (i = 0; i < ARRAY_SIZE(bin_locus_ma_tests); ++i) {
8407 		const char *str;
8408 		isl_bool ok;
8409 		isl_multi_aff *ma1, *ma2;
8410 		isl_set *set, *res;
8411 
8412 		str = bin_locus_ma_tests[i].arg1;
8413 		ma1 = isl_multi_aff_read_from_str(ctx, str);
8414 		str = bin_locus_ma_tests[i].arg2;
8415 		ma2 = isl_multi_aff_read_from_str(ctx, str);
8416 		res = isl_set_read_from_str(ctx, bin_locus_ma_tests[i].res);
8417 		set = bin_locus_ma_tests[i].fn(ma1, ma2);
8418 		ok = isl_set_is_equal(set, res);
8419 		isl_set_free(set);
8420 		isl_set_free(res);
8421 		if (ok < 0)
8422 			return isl_stat_error;
8423 		if (!ok)
8424 			isl_die(ctx, isl_error_unknown,
8425 				"unexpected result", return isl_stat_error);
8426 	}
8427 
8428 	return isl_stat_ok;
8429 }
8430 
8431 /* Perform basic locus tests.
8432  */
test_locus(isl_ctx * ctx)8433 static int test_locus(isl_ctx *ctx)
8434 {
8435 	if (test_un_locus(ctx) < 0)
8436 		return -1;
8437 	if (test_bin_locus(ctx) < 0)
8438 		return -1;
8439 	if (test_bin_locus_ma(ctx) < 0)
8440 		return -1;
8441 	return 0;
8442 }
8443 
8444 /* Test that isl_union_pw_qpolynomial_eval picks up the function
8445  * defined over the correct domain space.
8446  */
test_eval_1(isl_ctx * ctx)8447 static int test_eval_1(isl_ctx *ctx)
8448 {
8449 	const char *str;
8450 	isl_point *pnt;
8451 	isl_set *set;
8452 	isl_union_pw_qpolynomial *upwqp;
8453 	isl_val *v;
8454 	int cmp;
8455 
8456 	str = "{ A[x] -> x^2; B[x] -> -x^2 }";
8457 	upwqp = isl_union_pw_qpolynomial_read_from_str(ctx, str);
8458 	str = "{ A[6] }";
8459 	set = isl_set_read_from_str(ctx, str);
8460 	pnt = isl_set_sample_point(set);
8461 	v = isl_union_pw_qpolynomial_eval(upwqp, pnt);
8462 	cmp = isl_val_cmp_si(v, 36);
8463 	isl_val_free(v);
8464 
8465 	if (!v)
8466 		return -1;
8467 	if (cmp != 0)
8468 		isl_die(ctx, isl_error_unknown, "unexpected value", return -1);
8469 
8470 	return 0;
8471 }
8472 
8473 /* Check that isl_qpolynomial_eval handles getting called on a void point.
8474  */
test_eval_2(isl_ctx * ctx)8475 static int test_eval_2(isl_ctx *ctx)
8476 {
8477 	const char *str;
8478 	isl_point *pnt;
8479 	isl_set *set;
8480 	isl_qpolynomial *qp;
8481 	isl_val *v;
8482 	isl_bool ok;
8483 
8484 	str = "{ A[x] -> [x] }";
8485 	qp = isl_qpolynomial_from_aff(isl_aff_read_from_str(ctx, str));
8486 	str = "{ A[x] : false }";
8487 	set = isl_set_read_from_str(ctx, str);
8488 	pnt = isl_set_sample_point(set);
8489 	v = isl_qpolynomial_eval(qp, pnt);
8490 	ok = isl_val_is_nan(v);
8491 	isl_val_free(v);
8492 
8493 	if (ok < 0)
8494 		return -1;
8495 	if (!ok)
8496 		isl_die(ctx, isl_error_unknown, "expecting NaN", return -1);
8497 
8498 	return 0;
8499 }
8500 
8501 /* Check that a polynomial (without local variables) can be evaluated
8502  * in a rational point.
8503  */
test_eval_3(isl_ctx * ctx)8504 static isl_stat test_eval_3(isl_ctx *ctx)
8505 {
8506 	isl_pw_qpolynomial *pwqp;
8507 	isl_point *pnt;
8508 	isl_val *v;
8509 	isl_stat r;
8510 
8511 	pwqp = isl_pw_qpolynomial_read_from_str(ctx, "{ [x] -> x^2 }");
8512 	pnt = isl_point_zero(isl_pw_qpolynomial_get_domain_space(pwqp));
8513 	v = isl_val_read_from_str(ctx, "1/2");
8514 	pnt = isl_point_set_coordinate_val(pnt, isl_dim_set, 0, v);
8515 	v = isl_pw_qpolynomial_eval(pwqp, pnt);
8516 	r = val_check_equal(v, "1/4");
8517 	isl_val_free(v);
8518 
8519 	return r;
8520 }
8521 
8522 /* Inputs for isl_pw_aff_eval test.
8523  * "f" is the affine function.
8524  * "p" is the point where the function should be evaluated.
8525  * "res" is the expected result.
8526  */
8527 struct {
8528 	const char *f;
8529 	const char *p;
8530 	const char *res;
8531 } aff_eval_tests[] = {
8532 	{ "{ [i] -> [2 * i] }", "{ [4] }", "8" },
8533 	{ "{ [i] -> [2 * i] }", "{ [x] : false }", "NaN" },
8534 	{ "{ [i] -> [i + floor(i/2) + floor(i/3)] }", "{ [0] }", "0" },
8535 	{ "{ [i] -> [i + floor(i/2) + floor(i/3)] }", "{ [1] }", "1" },
8536 	{ "{ [i] -> [i + floor(i/2) + floor(i/3)] }", "{ [2] }", "3" },
8537 	{ "{ [i] -> [i + floor(i/2) + floor(i/3)] }", "{ [3] }", "5" },
8538 	{ "{ [i] -> [i + floor(i/2) + floor(i/3)] }", "{ [4] }", "7" },
8539 	{ "{ [i] -> [floor((3 * floor(i/2))/5)] }", "{ [0] }", "0" },
8540 	{ "{ [i] -> [floor((3 * floor(i/2))/5)] }", "{ [1] }", "0" },
8541 	{ "{ [i] -> [floor((3 * floor(i/2))/5)] }", "{ [2] }", "0" },
8542 	{ "{ [i] -> [floor((3 * floor(i/2))/5)] }", "{ [3] }", "0" },
8543 	{ "{ [i] -> [floor((3 * floor(i/2))/5)] }", "{ [4] }", "1" },
8544 	{ "{ [i] -> [floor((3 * floor(i/2))/5)] }", "{ [6] }", "1" },
8545 	{ "{ [i] -> [floor((3 * floor(i/2))/5)] }", "{ [8] }", "2" },
8546 	{ "{ [i] -> [i] : i > 0; [i] -> [-i] : i < 0 }", "{ [4] }", "4" },
8547 	{ "{ [i] -> [i] : i > 0; [i] -> [-i] : i < 0 }", "{ [-2] }", "2" },
8548 	{ "{ [i] -> [i] : i > 0; [i] -> [-i] : i < 0 }", "{ [0] }", "NaN" },
8549 	{ "[N] -> { [2 * N] }", "[N] -> { : N = 4 }", "8" },
8550 	{ "{ [i, j] -> [(i + j)/2] }", "{ [1, 1] }", "1" },
8551 	{ "{ [i, j] -> [(i + j)/2] }", "{ [1, 2] }", "3/2" },
8552 	{ "{ [i] -> [i] : i mod 2 = 0 }", "{ [4] }", "4" },
8553 	{ "{ [i] -> [i] : i mod 2 = 0 }", "{ [3] }", "NaN" },
8554 	{ "{ [i] -> [i] : i mod 2 = 0 }", "{ [x] : false }", "NaN" },
8555 };
8556 
8557 /* Perform basic isl_pw_aff_eval tests.
8558  */
test_eval_aff(isl_ctx * ctx)8559 static int test_eval_aff(isl_ctx *ctx)
8560 {
8561 	int i;
8562 
8563 	for (i = 0; i < ARRAY_SIZE(aff_eval_tests); ++i) {
8564 		isl_stat r;
8565 		isl_pw_aff *pa;
8566 		isl_set *set;
8567 		isl_point *pnt;
8568 		isl_val *v;
8569 
8570 		pa = isl_pw_aff_read_from_str(ctx, aff_eval_tests[i].f);
8571 		set = isl_set_read_from_str(ctx, aff_eval_tests[i].p);
8572 		pnt = isl_set_sample_point(set);
8573 		v = isl_pw_aff_eval(pa, pnt);
8574 		r = val_check_equal(v, aff_eval_tests[i].res);
8575 		isl_val_free(v);
8576 		if (r < 0)
8577 			return -1;
8578 	}
8579 	return 0;
8580 }
8581 
8582 /* Perform basic evaluation tests.
8583  */
test_eval(isl_ctx * ctx)8584 static int test_eval(isl_ctx *ctx)
8585 {
8586 	if (test_eval_1(ctx) < 0)
8587 		return -1;
8588 	if (test_eval_2(ctx) < 0)
8589 		return -1;
8590 	if (test_eval_3(ctx) < 0)
8591 		return -1;
8592 	if (test_eval_aff(ctx) < 0)
8593 		return -1;
8594 	return 0;
8595 }
8596 
8597 /* Descriptions of sets that are tested for reparsing after printing.
8598  */
8599 const char *output_tests[] = {
8600 	"{ [1, y] : 0 <= y <= 1; [x, -x] : 0 <= x <= 1 }",
8601 	"{ [x] : 1 = 0 }",
8602 	"{ [x] : false }",
8603 	"{ [x] : x mod 2 = 0 }",
8604 	"{ [x] : x mod 2 = 1 }",
8605 	"{ [x, y] : x mod 2 = 0 and 3*floor(y/2) < x }",
8606 	"{ [y, x] : x mod 2 = 0 and 3*floor(y/2) < x }",
8607 	"{ [x, y] : x mod 2 = 0 and 3*floor(y/2) = x + y }",
8608 	"{ [y, x] : x mod 2 = 0 and 3*floor(y/2) = x + y }",
8609 	"[n] -> { [y, x] : 2*((x + 2y) mod 3) = n }",
8610 	"{ [x, y] : (2*floor(x/3) + 3*floor(y/4)) mod 5 = x }",
8611 };
8612 
8613 /* Check that printing a set and reparsing a set from the printed output
8614  * results in the same set.
8615  */
test_output_set(isl_ctx * ctx)8616 static int test_output_set(isl_ctx *ctx)
8617 {
8618 	int i;
8619 	char *str;
8620 	isl_set *set1, *set2;
8621 	isl_bool equal;
8622 
8623 	for (i = 0; i < ARRAY_SIZE(output_tests); ++i) {
8624 		set1 = isl_set_read_from_str(ctx, output_tests[i]);
8625 		str = isl_set_to_str(set1);
8626 		set2 = isl_set_read_from_str(ctx, str);
8627 		free(str);
8628 		equal = isl_set_is_equal(set1, set2);
8629 		isl_set_free(set1);
8630 		isl_set_free(set2);
8631 		if (equal < 0)
8632 			return -1;
8633 		if (!equal)
8634 			isl_die(ctx, isl_error_unknown,
8635 				"parsed output not the same", return -1);
8636 	}
8637 
8638 	return 0;
8639 }
8640 
8641 /* Check that an isl_multi_aff is printed using a consistent space.
8642  */
test_output_ma(isl_ctx * ctx)8643 static isl_stat test_output_ma(isl_ctx *ctx)
8644 {
8645 	char *str;
8646 	isl_bool equal;
8647 	isl_aff *aff;
8648 	isl_multi_aff *ma, *ma2;
8649 
8650 	ma = isl_multi_aff_read_from_str(ctx, "{ [a, b] -> [a + b] }");
8651 	aff = isl_aff_read_from_str(ctx, "{ [c, d] -> [c + d] }");
8652 	ma = isl_multi_aff_set_aff(ma, 0, aff);
8653 	str = isl_multi_aff_to_str(ma);
8654 	ma2 = isl_multi_aff_read_from_str(ctx, str);
8655 	free(str);
8656 	equal = isl_multi_aff_plain_is_equal(ma, ma2);
8657 	isl_multi_aff_free(ma2);
8658 	isl_multi_aff_free(ma);
8659 
8660 	if (equal < 0)
8661 		return isl_stat_error;
8662 	if (!equal)
8663 		isl_die(ctx, isl_error_unknown, "bad conversion",
8664 			return isl_stat_error);
8665 
8666 	return isl_stat_ok;
8667 }
8668 
8669 /* Check that an isl_multi_pw_aff is printed using a consistent space.
8670  */
test_output_mpa(isl_ctx * ctx)8671 static isl_stat test_output_mpa(isl_ctx *ctx)
8672 {
8673 	char *str;
8674 	isl_bool equal;
8675 	isl_pw_aff *pa;
8676 	isl_multi_pw_aff *mpa, *mpa2;
8677 
8678 	mpa = isl_multi_pw_aff_read_from_str(ctx, "{ [a, b] -> [a + b] }");
8679 	pa = isl_pw_aff_read_from_str(ctx, "{ [c, d] -> [c + d] }");
8680 	mpa = isl_multi_pw_aff_set_pw_aff(mpa, 0, pa);
8681 	str = isl_multi_pw_aff_to_str(mpa);
8682 	mpa2 = isl_multi_pw_aff_read_from_str(ctx, str);
8683 	free(str);
8684 	equal = isl_multi_pw_aff_plain_is_equal(mpa, mpa2);
8685 	isl_multi_pw_aff_free(mpa2);
8686 	isl_multi_pw_aff_free(mpa);
8687 
8688 	if (equal < 0)
8689 		return isl_stat_error;
8690 	if (!equal)
8691 		isl_die(ctx, isl_error_unknown, "bad conversion",
8692 			return isl_stat_error);
8693 
8694 	return isl_stat_ok;
8695 }
8696 
test_output(isl_ctx * ctx)8697 int test_output(isl_ctx *ctx)
8698 {
8699 	char *s;
8700 	const char *str;
8701 	isl_pw_aff *pa;
8702 	isl_printer *p;
8703 	int equal;
8704 
8705 	if (test_output_set(ctx) < 0)
8706 		return -1;
8707 	if (test_output_ma(ctx) < 0)
8708 		return -1;
8709 	if (test_output_mpa(ctx) < 0)
8710 		return -1;
8711 
8712 	str = "[x] -> { [1] : x % 4 <= 2; [2] : x = 3 }";
8713 	pa = isl_pw_aff_read_from_str(ctx, str);
8714 
8715 	p = isl_printer_to_str(ctx);
8716 	p = isl_printer_set_output_format(p, ISL_FORMAT_C);
8717 	p = isl_printer_print_pw_aff(p, pa);
8718 	s = isl_printer_get_str(p);
8719 	isl_printer_free(p);
8720 	isl_pw_aff_free(pa);
8721 	if (!s)
8722 		equal = -1;
8723 	else
8724 		equal = !strcmp(s, "4 * floord(x, 4) + 2 >= x ? 1 : 2");
8725 	free(s);
8726 	if (equal < 0)
8727 		return -1;
8728 	if (!equal)
8729 		isl_die(ctx, isl_error_unknown, "unexpected result", return -1);
8730 
8731 	return 0;
8732 }
8733 
test_sample(isl_ctx * ctx)8734 int test_sample(isl_ctx *ctx)
8735 {
8736 	const char *str;
8737 	isl_basic_set *bset1, *bset2;
8738 	int empty, subset;
8739 
8740 	str = "{ [a, b, c, d, e, f, g, h, i, j, k] : "
8741 	    "3i >= 1073741823b - c - 1073741823e + f and c >= 0 and "
8742 	    "3i >= -1 + 3221225466b + c + d - 3221225466e - f and "
8743 	    "2e >= a - b and 3e <= 2a and 3k <= -a and f <= -1 + a and "
8744 	    "3i <= 4 - a + 4b + 2c - e - 2f and 3k <= -a + c - f and "
8745 	    "3h >= -2 + a and 3g >= -3 - a and 3k >= -2 - a and "
8746 	    "3i >= -2 - a - 2c + 3e + 2f and 3h <= a + c - f and "
8747 	    "3h >= a + 2147483646b + 2c - 2147483646e - 2f and "
8748 	    "3g <= -1 - a and 3i <= 1 + c + d - f and a <= 1073741823 and "
8749 	    "f >= 1 - a + 1073741822b + c + d - 1073741822e and "
8750 	    "3i >= 1 + 2b - 2c + e + 2f + 3g and "
8751 	    "1073741822f <= 1073741822 - a + 1073741821b + 1073741822c +"
8752 		"d - 1073741821e and "
8753 	    "3j <= 3 - a + 3b and 3g <= -2 - 2b + c + d - e - f and "
8754 	    "3j >= 1 - a + b + 2e and "
8755 	    "3f >= -3 + a + 3221225462b + 3c + d - 3221225465e and "
8756 	    "3i <= 4 - a + 4b - e and "
8757 	    "f <= 1073741822 + 1073741822b - 1073741822e and 3h <= a and "
8758 	    "f >= 0 and 2e <= 4 - a + 5b - d and 2e <= a - b + d and "
8759 	    "c <= -1 + a and 3i >= -2 - a + 3e and "
8760 	    "1073741822e <= 1073741823 - a + 1073741822b + c and "
8761 	    "3g >= -4 + 3221225464b + 3c + d - 3221225467e - 3f and "
8762 	    "3i >= -1 + 3221225466b + 3c + d - 3221225466e - 3f and "
8763 	    "1073741823e >= 1 + 1073741823b - d and "
8764 	    "3i >= 1073741823b + c - 1073741823e - f and "
8765 	    "3i >= 1 + 2b + e + 3g }";
8766 	bset1 = isl_basic_set_read_from_str(ctx, str);
8767 	bset2 = isl_basic_set_sample(isl_basic_set_copy(bset1));
8768 	empty = isl_basic_set_is_empty(bset2);
8769 	subset = isl_basic_set_is_subset(bset2, bset1);
8770 	isl_basic_set_free(bset1);
8771 	isl_basic_set_free(bset2);
8772 	if (empty < 0 || subset < 0)
8773 		return -1;
8774 	if (empty)
8775 		isl_die(ctx, isl_error_unknown, "point not found", return -1);
8776 	if (!subset)
8777 		isl_die(ctx, isl_error_unknown, "bad point found", return -1);
8778 
8779 	return 0;
8780 }
8781 
8782 /* Perform a projection on a basic set that is known to be empty
8783  * but that has not been assigned a canonical representation.
8784  * Earlier versions of isl would run into a stack overflow
8785  * on this example.
8786  */
test_empty_projection(isl_ctx * ctx)8787 static int test_empty_projection(isl_ctx *ctx)
8788 {
8789 	const char *str;
8790 	isl_bool empty;
8791 	isl_basic_set *bset;
8792 
8793 	str = "{ [a, b, c, d, e, f, g, h] : 5f = 1 + 4a - b + 5c - d - 2e and "
8794 		"3h = 2 + b + c and 14c >= 9 - 3a + 25b and "
8795 		"4c <= 50 - 3a + 23b and 6b <= -39 + a and "
8796 		"9g >= -6 + 3a + b + c and e < a + b - 2d and "
8797 		"7d >= -5 + 2a + 2b and 5g >= -14 + a - 4b + d + 2e and "
8798 		"9g <= -28 - 5b - 2c + 3d + 6e }";
8799 	bset = isl_basic_set_read_from_str(ctx, str);
8800 	empty = isl_basic_set_is_empty(bset);
8801 	bset = isl_basic_set_params(bset);
8802 	isl_basic_set_free(bset);
8803 
8804 	if (empty < 0)
8805 		return -1;
8806 
8807 	return 0;
8808 }
8809 
test_fixed_power(isl_ctx * ctx)8810 int test_fixed_power(isl_ctx *ctx)
8811 {
8812 	const char *str;
8813 	isl_map *map;
8814 	isl_val *exp;
8815 	int equal;
8816 
8817 	str = "{ [i] -> [i + 1] }";
8818 	map = isl_map_read_from_str(ctx, str);
8819 	exp = isl_val_int_from_si(ctx, 23);
8820 	map = isl_map_fixed_power_val(map, exp);
8821 	equal = map_check_equal(map, "{ [i] -> [i + 23] }");
8822 	isl_map_free(map);
8823 	if (equal < 0)
8824 		return -1;
8825 
8826 	return 0;
8827 }
8828 
test_slice(isl_ctx * ctx)8829 int test_slice(isl_ctx *ctx)
8830 {
8831 	const char *str;
8832 	isl_map *map;
8833 	int equal;
8834 
8835 	str = "{ [i] -> [j] }";
8836 	map = isl_map_read_from_str(ctx, str);
8837 	map = isl_map_equate(map, isl_dim_in, 0, isl_dim_out, 0);
8838 	equal = map_check_equal(map, "{ [i] -> [i] }");
8839 	isl_map_free(map);
8840 	if (equal < 0)
8841 		return -1;
8842 
8843 	str = "{ [i] -> [j] }";
8844 	map = isl_map_read_from_str(ctx, str);
8845 	map = isl_map_equate(map, isl_dim_in, 0, isl_dim_in, 0);
8846 	equal = map_check_equal(map, "{ [i] -> [j] }");
8847 	isl_map_free(map);
8848 	if (equal < 0)
8849 		return -1;
8850 
8851 	str = "{ [i] -> [j] }";
8852 	map = isl_map_read_from_str(ctx, str);
8853 	map = isl_map_oppose(map, isl_dim_in, 0, isl_dim_out, 0);
8854 	equal = map_check_equal(map, "{ [i] -> [-i] }");
8855 	isl_map_free(map);
8856 	if (equal < 0)
8857 		return -1;
8858 
8859 	str = "{ [i] -> [j] }";
8860 	map = isl_map_read_from_str(ctx, str);
8861 	map = isl_map_oppose(map, isl_dim_in, 0, isl_dim_in, 0);
8862 	equal = map_check_equal(map, "{ [0] -> [j] }");
8863 	isl_map_free(map);
8864 	if (equal < 0)
8865 		return -1;
8866 
8867 	str = "{ [i] -> [j] }";
8868 	map = isl_map_read_from_str(ctx, str);
8869 	map = isl_map_order_gt(map, isl_dim_in, 0, isl_dim_out, 0);
8870 	equal = map_check_equal(map, "{ [i] -> [j] : i > j }");
8871 	isl_map_free(map);
8872 	if (equal < 0)
8873 		return -1;
8874 
8875 	str = "{ [i] -> [j] }";
8876 	map = isl_map_read_from_str(ctx, str);
8877 	map = isl_map_order_gt(map, isl_dim_in, 0, isl_dim_in, 0);
8878 	equal = map_check_equal(map, "{ [i] -> [j] : false }");
8879 	isl_map_free(map);
8880 	if (equal < 0)
8881 		return -1;
8882 
8883 	return 0;
8884 }
8885 
test_eliminate(isl_ctx * ctx)8886 int test_eliminate(isl_ctx *ctx)
8887 {
8888 	const char *str;
8889 	isl_map *map;
8890 	int equal;
8891 
8892 	str = "{ [i] -> [j] : i = 2j }";
8893 	map = isl_map_read_from_str(ctx, str);
8894 	map = isl_map_eliminate(map, isl_dim_out, 0, 1);
8895 	equal = map_check_equal(map, "{ [i] -> [j] : exists a : i = 2a }");
8896 	isl_map_free(map);
8897 	if (equal < 0)
8898 		return -1;
8899 
8900 	return 0;
8901 }
8902 
8903 /* Check basic functionality of isl_map_deltas_map.
8904  */
test_deltas_map(isl_ctx * ctx)8905 static int test_deltas_map(isl_ctx *ctx)
8906 {
8907 	const char *str;
8908 	isl_map *map;
8909 	int equal;
8910 
8911 	str = "{ A[i] -> A[i + 1] }";
8912 	map = isl_map_read_from_str(ctx, str);
8913 	map = isl_map_deltas_map(map);
8914 	equal = map_check_equal(map, "{ [A[i] -> A[i + 1]] -> A[1] }");
8915 	isl_map_free(map);
8916 	if (equal < 0)
8917 		return -1;
8918 
8919 	return 0;
8920 }
8921 
8922 /* Check that isl_set_dim_residue_class detects that the values of j
8923  * in the set below are all odd and that it does not detect any spurious
8924  * strides.
8925  */
test_residue_class(isl_ctx * ctx)8926 static int test_residue_class(isl_ctx *ctx)
8927 {
8928 	const char *str;
8929 	isl_set *set;
8930 	isl_int m, r;
8931 	isl_stat res;
8932 
8933 	str = "{ [i,j] : j = 4 i + 1 and 0 <= i <= 100; "
8934 		"[i,j] : j = 4 i + 3 and 500 <= i <= 600 }";
8935 	set = isl_set_read_from_str(ctx, str);
8936 	isl_int_init(m);
8937 	isl_int_init(r);
8938 	res = isl_set_dim_residue_class(set, 1, &m, &r);
8939 	if (res >= 0 &&
8940 	    (isl_int_cmp_si(m, 2) != 0 || isl_int_cmp_si(r, 1) != 0))
8941 		isl_die(ctx, isl_error_unknown, "incorrect residue class",
8942 			res = isl_stat_error);
8943 	isl_int_clear(r);
8944 	isl_int_clear(m);
8945 	isl_set_free(set);
8946 
8947 	return res;
8948 }
8949 
test_align_parameters_1(isl_ctx * ctx)8950 static int test_align_parameters_1(isl_ctx *ctx)
8951 {
8952 	const char *str;
8953 	isl_space *space;
8954 	isl_multi_aff *ma1, *ma2;
8955 	int equal;
8956 
8957 	str = "{ A[B[] -> C[]] -> D[E[] -> F[]] }";
8958 	ma1 = isl_multi_aff_read_from_str(ctx, str);
8959 
8960 	space = isl_space_params_alloc(ctx, 1);
8961 	space = isl_space_set_dim_name(space, isl_dim_param, 0, "N");
8962 	ma1 = isl_multi_aff_align_params(ma1, space);
8963 
8964 	str = "[N] -> { A[B[] -> C[]] -> D[E[] -> F[]] }";
8965 	ma2 = isl_multi_aff_read_from_str(ctx, str);
8966 
8967 	equal = isl_multi_aff_plain_is_equal(ma1, ma2);
8968 
8969 	isl_multi_aff_free(ma1);
8970 	isl_multi_aff_free(ma2);
8971 
8972 	if (equal < 0)
8973 		return -1;
8974 	if (!equal)
8975 		isl_die(ctx, isl_error_unknown,
8976 			"result not as expected", return -1);
8977 
8978 	return 0;
8979 }
8980 
8981 /* Check the isl_multi_*_from_*_list operation in case inputs
8982  * have unaligned parameters.
8983  * In particular, older versions of isl would simply fail
8984  * (without printing any error message).
8985  */
test_align_parameters_2(isl_ctx * ctx)8986 static isl_stat test_align_parameters_2(isl_ctx *ctx)
8987 {
8988 	isl_space *space;
8989 	isl_map *map;
8990 	isl_aff *aff;
8991 	isl_multi_aff *ma;
8992 
8993 	map = isl_map_read_from_str(ctx, "{ A[] -> M[x] }");
8994 	space = isl_map_get_space(map);
8995 	isl_map_free(map);
8996 
8997 	aff = isl_aff_read_from_str(ctx, "[N] -> { A[] -> [N] }");
8998 	ma = isl_multi_aff_from_aff_list(space, isl_aff_list_from_aff(aff));
8999 	isl_multi_aff_free(ma);
9000 
9001 	if (!ma)
9002 		return isl_stat_error;
9003 	return isl_stat_ok;
9004 }
9005 
9006 /* Perform basic parameter alignment tests.
9007  */
test_align_parameters(isl_ctx * ctx)9008 static int test_align_parameters(isl_ctx *ctx)
9009 {
9010 	if (test_align_parameters_1(ctx) < 0)
9011 		return -1;
9012 	if (test_align_parameters_2(ctx) < 0)
9013 		return -1;
9014 
9015 	return 0;
9016 }
9017 
9018 /* Check that isl_*_drop_unused_params actually drops the unused parameters
9019  * by comparing the result using isl_*_plain_is_equal.
9020  * Note that this assumes that isl_*_plain_is_equal does not consider
9021  * objects that only differ by unused parameters to be equal.
9022  */
test_drop_unused_parameters(isl_ctx * ctx)9023 int test_drop_unused_parameters(isl_ctx *ctx)
9024 {
9025 	const char *str_with, *str_without;
9026 	isl_basic_set *bset1, *bset2;
9027 	isl_set *set1, *set2;
9028 	isl_pw_aff *pwa1, *pwa2;
9029 	int equal;
9030 
9031 	str_with = "[n, m, o] -> { [m] }";
9032 	str_without = "[m] -> { [m] }";
9033 
9034 	bset1 = isl_basic_set_read_from_str(ctx, str_with);
9035 	bset2 = isl_basic_set_read_from_str(ctx, str_without);
9036 	bset1 = isl_basic_set_drop_unused_params(bset1);
9037 	equal = isl_basic_set_plain_is_equal(bset1, bset2);
9038 	isl_basic_set_free(bset1);
9039 	isl_basic_set_free(bset2);
9040 
9041 	if (equal < 0)
9042 		return -1;
9043 	if (!equal)
9044 		isl_die(ctx, isl_error_unknown,
9045 			"result not as expected", return -1);
9046 
9047 	set1 = isl_set_read_from_str(ctx, str_with);
9048 	set2 = isl_set_read_from_str(ctx, str_without);
9049 	set1 = isl_set_drop_unused_params(set1);
9050 	equal = isl_set_plain_is_equal(set1, set2);
9051 	isl_set_free(set1);
9052 	isl_set_free(set2);
9053 
9054 	if (equal < 0)
9055 		return -1;
9056 	if (!equal)
9057 		isl_die(ctx, isl_error_unknown,
9058 			"result not as expected", return -1);
9059 
9060 	pwa1 = isl_pw_aff_read_from_str(ctx, str_with);
9061 	pwa2 = isl_pw_aff_read_from_str(ctx, str_without);
9062 	pwa1 = isl_pw_aff_drop_unused_params(pwa1);
9063 	equal = isl_pw_aff_plain_is_equal(pwa1, pwa2);
9064 	isl_pw_aff_free(pwa1);
9065 	isl_pw_aff_free(pwa2);
9066 
9067 	if (equal < 0)
9068 		return -1;
9069 	if (!equal)
9070 		isl_die(ctx, isl_error_unknown,
9071 			"result not as expected", return -1);
9072 
9073 	return 0;
9074 }
9075 
test_list(isl_ctx * ctx)9076 static int test_list(isl_ctx *ctx)
9077 {
9078 	isl_id *a, *b, *c, *d, *id;
9079 	isl_id_list *list;
9080 	isl_size n;
9081 	int ok;
9082 
9083 	a = isl_id_alloc(ctx, "a", NULL);
9084 	b = isl_id_alloc(ctx, "b", NULL);
9085 	c = isl_id_alloc(ctx, "c", NULL);
9086 	d = isl_id_alloc(ctx, "d", NULL);
9087 
9088 	list = isl_id_list_alloc(ctx, 4);
9089 	list = isl_id_list_add(list, b);
9090 	list = isl_id_list_insert(list, 0, a);
9091 	list = isl_id_list_add(list, c);
9092 	list = isl_id_list_add(list, d);
9093 	list = isl_id_list_drop(list, 1, 1);
9094 
9095 	n = isl_id_list_n_id(list);
9096 	if (n < 0)
9097 		return -1;
9098 	if (n != 3) {
9099 		isl_id_list_free(list);
9100 		isl_die(ctx, isl_error_unknown,
9101 			"unexpected number of elements in list", return -1);
9102 	}
9103 
9104 	id = isl_id_list_get_id(list, 0);
9105 	ok = id == a;
9106 	isl_id_free(id);
9107 	id = isl_id_list_get_id(list, 1);
9108 	ok = ok && id == c;
9109 	isl_id_free(id);
9110 	id = isl_id_list_get_id(list, 2);
9111 	ok = ok && id == d;
9112 	isl_id_free(id);
9113 
9114 	isl_id_list_free(list);
9115 
9116 	if (!ok)
9117 		isl_die(ctx, isl_error_unknown,
9118 			"unexpected elements in list", return -1);
9119 
9120 	return 0;
9121 }
9122 
9123 /* Check the conversion from an isl_multi_aff to an isl_basic_set.
9124  */
test_ma_conversion(isl_ctx * ctx)9125 static isl_stat test_ma_conversion(isl_ctx *ctx)
9126 {
9127 	const char *str;
9128 	isl_bool equal;
9129 	isl_multi_aff *ma;
9130 	isl_basic_set *bset1, *bset2;
9131 
9132 	str = "[N] -> { A[0, N + 1] }";
9133 	ma = isl_multi_aff_read_from_str(ctx, str);
9134 	bset1 = isl_basic_set_read_from_str(ctx, str);
9135 	bset2 = isl_basic_set_from_multi_aff(ma);
9136 	equal = isl_basic_set_is_equal(bset1, bset2);
9137 	isl_basic_set_free(bset1);
9138 	isl_basic_set_free(bset2);
9139 	if (equal < 0)
9140 		return isl_stat_error;
9141 	if (!equal)
9142 		isl_die(ctx, isl_error_unknown, "bad conversion",
9143 			return isl_stat_error);
9144 	return isl_stat_ok;
9145 }
9146 
9147 const char *set_conversion_tests[] = {
9148 	"[N] -> { [i] : N - 1 <= 2 i <= N }",
9149 	"[N] -> { [i] : exists a : i = 4 a and N - 1 <= i <= N }",
9150 	"[N] -> { [i,j] : exists a : i = 4 a and N - 1 <= i, 2j <= N }",
9151 	"[N] -> { [[i]->[j]] : exists a : i = 4 a and N - 1 <= i, 2j <= N }",
9152 	"[N] -> { [3*floor(N/2) + 5*floor(N/3)] }",
9153 	"[a, b] -> { [c, d] : (4*floor((-a + c)/4) = -a + c and "
9154 			"32*floor((-b + d)/32) = -b + d and 5 <= c <= 8 and "
9155 			"-3 + c <= d <= 28 + c) }",
9156 };
9157 
9158 /* Check that converting from isl_set to isl_pw_multi_aff and back
9159  * to isl_set produces the original isl_set.
9160  */
test_set_conversion(isl_ctx * ctx)9161 static int test_set_conversion(isl_ctx *ctx)
9162 {
9163 	int i;
9164 	const char *str;
9165 	isl_set *set1, *set2;
9166 	isl_pw_multi_aff *pma;
9167 	int equal;
9168 
9169 	for (i = 0; i < ARRAY_SIZE(set_conversion_tests); ++i) {
9170 		str = set_conversion_tests[i];
9171 		set1 = isl_set_read_from_str(ctx, str);
9172 		pma = isl_pw_multi_aff_from_set(isl_set_copy(set1));
9173 		set2 = isl_set_from_pw_multi_aff(pma);
9174 		equal = isl_set_is_equal(set1, set2);
9175 		isl_set_free(set1);
9176 		isl_set_free(set2);
9177 
9178 		if (equal < 0)
9179 			return -1;
9180 		if (!equal)
9181 			isl_die(ctx, isl_error_unknown, "bad conversion",
9182 				return -1);
9183 	}
9184 
9185 	return 0;
9186 }
9187 
9188 const char *conversion_tests[] = {
9189 	"{ [a, b, c, d] -> s0[a, b, e, f] : "
9190 	    "exists (e0 = [(a - 2c)/3], e1 = [(-4 + b - 5d)/9], "
9191 	    "e2 = [(-d + f)/9]: 3e0 = a - 2c and 9e1 = -4 + b - 5d and "
9192 	    "9e2 = -d + f and f >= 0 and f <= 8 and 9e >= -5 - 2a and "
9193 	    "9e <= -2 - 2a) }",
9194 	"{ [a, b] -> [c] : exists (e0 = floor((-a - b + c)/5): "
9195 	    "5e0 = -a - b + c and c >= -a and c <= 4 - a) }",
9196 	"{ [a, b] -> [c] : exists d : 18 * d = -3 - a + 2c and 1 <= c <= 3 }",
9197 };
9198 
9199 /* Check that converting from isl_map to isl_pw_multi_aff and back
9200  * to isl_map produces the original isl_map.
9201  */
test_map_conversion(isl_ctx * ctx)9202 static int test_map_conversion(isl_ctx *ctx)
9203 {
9204 	int i;
9205 	isl_map *map1, *map2;
9206 	isl_pw_multi_aff *pma;
9207 	int equal;
9208 
9209 	for (i = 0; i < ARRAY_SIZE(conversion_tests); ++i) {
9210 		map1 = isl_map_read_from_str(ctx, conversion_tests[i]);
9211 		pma = isl_pw_multi_aff_from_map(isl_map_copy(map1));
9212 		map2 = isl_map_from_pw_multi_aff(pma);
9213 		equal = isl_map_is_equal(map1, map2);
9214 		isl_map_free(map1);
9215 		isl_map_free(map2);
9216 
9217 		if (equal < 0)
9218 			return -1;
9219 		if (!equal)
9220 			isl_die(ctx, isl_error_unknown, "bad conversion",
9221 				return -1);
9222 	}
9223 
9224 	return 0;
9225 }
9226 
9227 /* Descriptions of isl_pw_multi_aff objects for testing conversion
9228  * to isl_multi_pw_aff and back.
9229  */
9230 const char *mpa_conversion_tests[] = {
9231 	"{ [x] -> A[x] }",
9232 	"{ [x] -> A[x] : x >= 0 }",
9233 	"{ [x] -> A[x] : x >= 0; [x] -> A[-x] : x < 0 }",
9234 	"{ [x] -> A[x, x + 1] }",
9235 	"{ [x] -> A[] }",
9236 	"{ [x] -> A[] : x >= 0 }",
9237 };
9238 
9239 /* Check that conversion from isl_pw_multi_aff to isl_multi_pw_aff and
9240  * back to isl_pw_multi_aff preserves the original meaning.
9241  */
test_mpa_conversion(isl_ctx * ctx)9242 static int test_mpa_conversion(isl_ctx *ctx)
9243 {
9244 	int i;
9245 	isl_pw_multi_aff *pma1, *pma2;
9246 	isl_multi_pw_aff *mpa;
9247 	int equal;
9248 
9249 	for (i = 0; i < ARRAY_SIZE(mpa_conversion_tests); ++i) {
9250 		const char *str;
9251 		str = mpa_conversion_tests[i];
9252 		pma1 = isl_pw_multi_aff_read_from_str(ctx, str);
9253 		pma2 = isl_pw_multi_aff_copy(pma1);
9254 		mpa = isl_multi_pw_aff_from_pw_multi_aff(pma1);
9255 		pma1 = isl_pw_multi_aff_from_multi_pw_aff(mpa);
9256 		equal = isl_pw_multi_aff_plain_is_equal(pma1, pma2);
9257 		isl_pw_multi_aff_free(pma1);
9258 		isl_pw_multi_aff_free(pma2);
9259 
9260 		if (equal < 0)
9261 			return -1;
9262 		if (!equal)
9263 			isl_die(ctx, isl_error_unknown, "bad conversion",
9264 				return -1);
9265 	}
9266 
9267 	return 0;
9268 }
9269 
9270 /* Descriptions of union maps that should be convertible
9271  * to an isl_multi_union_pw_aff.
9272  */
9273 const char *umap_mupa_conversion_tests[] = {
9274 	"{ [a, b, c, d] -> s0[a, b, e, f] : "
9275 	    "exists (e0 = [(a - 2c)/3], e1 = [(-4 + b - 5d)/9], "
9276 	    "e2 = [(-d + f)/9]: 3e0 = a - 2c and 9e1 = -4 + b - 5d and "
9277 	    "9e2 = -d + f and f >= 0 and f <= 8 and 9e >= -5 - 2a and "
9278 	    "9e <= -2 - 2a) }",
9279 	"{ [a, b] -> [c] : exists (e0 = floor((-a - b + c)/5): "
9280 	    "5e0 = -a - b + c and c >= -a and c <= 4 - a) }",
9281 	"{ [a, b] -> [c] : exists d : 18 * d = -3 - a + 2c and 1 <= c <= 3 }",
9282 	"{ A[] -> B[0]; C[] -> B[1] }",
9283 	"{ A[] -> B[]; C[] -> B[] }",
9284 };
9285 
9286 /* Check that converting from isl_union_map to isl_multi_union_pw_aff and back
9287  * to isl_union_map produces the original isl_union_map.
9288  */
test_union_map_mupa_conversion(isl_ctx * ctx)9289 static int test_union_map_mupa_conversion(isl_ctx *ctx)
9290 {
9291 	int i;
9292 	isl_union_map *umap1, *umap2;
9293 	isl_multi_union_pw_aff *mupa;
9294 	int equal;
9295 
9296 	for (i = 0; i < ARRAY_SIZE(umap_mupa_conversion_tests); ++i) {
9297 		const char *str;
9298 		str = umap_mupa_conversion_tests[i];
9299 		umap1 = isl_union_map_read_from_str(ctx, str);
9300 		umap2 = isl_union_map_copy(umap1);
9301 		mupa = isl_multi_union_pw_aff_from_union_map(umap2);
9302 		umap2 = isl_union_map_from_multi_union_pw_aff(mupa);
9303 		equal = isl_union_map_is_equal(umap1, umap2);
9304 		isl_union_map_free(umap1);
9305 		isl_union_map_free(umap2);
9306 
9307 		if (equal < 0)
9308 			return -1;
9309 		if (!equal)
9310 			isl_die(ctx, isl_error_unknown, "bad conversion",
9311 				return -1);
9312 	}
9313 
9314 	return 0;
9315 }
9316 
test_conversion(isl_ctx * ctx)9317 static int test_conversion(isl_ctx *ctx)
9318 {
9319 	if (test_ma_conversion(ctx) < 0)
9320 		return -1;
9321 	if (test_set_conversion(ctx) < 0)
9322 		return -1;
9323 	if (test_map_conversion(ctx) < 0)
9324 		return -1;
9325 	if (test_mpa_conversion(ctx) < 0)
9326 		return -1;
9327 	if (test_union_map_mupa_conversion(ctx) < 0)
9328 		return -1;
9329 	return 0;
9330 }
9331 
9332 /* Check that isl_basic_map_curry does not modify input.
9333  */
test_curry(isl_ctx * ctx)9334 static int test_curry(isl_ctx *ctx)
9335 {
9336 	const char *str;
9337 	isl_basic_map *bmap1, *bmap2;
9338 	int equal;
9339 
9340 	str = "{ [A[] -> B[]] -> C[] }";
9341 	bmap1 = isl_basic_map_read_from_str(ctx, str);
9342 	bmap2 = isl_basic_map_curry(isl_basic_map_copy(bmap1));
9343 	equal = isl_basic_map_is_equal(bmap1, bmap2);
9344 	isl_basic_map_free(bmap1);
9345 	isl_basic_map_free(bmap2);
9346 
9347 	if (equal < 0)
9348 		return -1;
9349 	if (equal)
9350 		isl_die(ctx, isl_error_unknown,
9351 			"curried map should not be equal to original",
9352 			return -1);
9353 
9354 	return 0;
9355 }
9356 
9357 struct {
9358 	const char *ma1;
9359 	const char *ma;
9360 	const char *res;
9361 } pullback_tests[] = {
9362 	{ "{ B[i,j] -> C[i + 2j] }" , "{ A[a,b] -> B[b,a] }",
9363 	  "{ A[a,b] -> C[b + 2a] }" },
9364 	{ "{ B[i] -> C[2i] }", "{ A[a] -> B[(a)/2] }", "{ A[a] -> C[a] }" },
9365 	{ "{ B[i] -> C[(i)/2] }", "{ A[a] -> B[2a] }", "{ A[a] -> C[a] }" },
9366 	{ "{ B[i] -> C[(i)/2] }", "{ A[a] -> B[(a)/3] }",
9367 	  "{ A[a] -> C[(a)/6] }" },
9368 	{ "{ B[i] -> C[2i] }", "{ A[a] -> B[5a] }", "{ A[a] -> C[10a] }" },
9369 	{ "{ B[i] -> C[2i] }", "{ A[a] -> B[(a)/3] }",
9370 	  "{ A[a] -> C[(2a)/3] }" },
9371 	{ "{ B[i,j] -> C[i + j] }", "{ A[a] -> B[a,a] }", "{ A[a] -> C[2a] }"},
9372 	{ "{ B[a] -> C[a,a] }", "{ A[i,j] -> B[i + j] }",
9373 	  "{ A[i,j] -> C[i + j, i + j] }"},
9374 	{ "{ B[i] -> C[([i/2])] }", "{ B[5] }", "{ C[2] }" },
9375 	{ "[n] -> { B[i,j] -> C[([i/2]) + 2j] }",
9376 	  "[n] -> { B[n,[n/3]] }", "[n] -> { C[([n/2]) + 2*[n/3]] }", },
9377 	{ "{ [i, j] -> [floor((i)/4) + floor((2*i+j)/5)] }",
9378 	  "{ [i, j] -> [floor((i)/3), j] }",
9379 	  "{ [i, j] -> [(floor((i)/12) + floor((j + 2*floor((i)/3))/5))] }" },
9380 };
9381 
test_pullback(isl_ctx * ctx)9382 static int test_pullback(isl_ctx *ctx)
9383 {
9384 	int i;
9385 	isl_multi_aff *ma1, *ma2;
9386 	isl_multi_aff *ma;
9387 	int equal;
9388 
9389 	for (i = 0; i < ARRAY_SIZE(pullback_tests); ++i) {
9390 		ma1 = isl_multi_aff_read_from_str(ctx, pullback_tests[i].ma1);
9391 		ma = isl_multi_aff_read_from_str(ctx, pullback_tests[i].ma);
9392 		ma2 = isl_multi_aff_read_from_str(ctx, pullback_tests[i].res);
9393 		ma1 = isl_multi_aff_pullback_multi_aff(ma1, ma);
9394 		equal = isl_multi_aff_plain_is_equal(ma1, ma2);
9395 		isl_multi_aff_free(ma1);
9396 		isl_multi_aff_free(ma2);
9397 		if (equal < 0)
9398 			return -1;
9399 		if (!equal)
9400 			isl_die(ctx, isl_error_unknown, "bad pullback",
9401 				return -1);
9402 	}
9403 
9404 	return 0;
9405 }
9406 
9407 /* Check that negation is printed correctly and that equal expressions
9408  * are correctly identified.
9409  */
test_ast(isl_ctx * ctx)9410 static int test_ast(isl_ctx *ctx)
9411 {
9412 	isl_ast_expr *expr, *expr1, *expr2, *expr3;
9413 	char *str;
9414 	int ok, equal;
9415 
9416 	expr1 = isl_ast_expr_from_id(isl_id_alloc(ctx, "A", NULL));
9417 	expr2 = isl_ast_expr_from_id(isl_id_alloc(ctx, "B", NULL));
9418 	expr = isl_ast_expr_add(expr1, expr2);
9419 	expr2 = isl_ast_expr_copy(expr);
9420 	expr = isl_ast_expr_neg(expr);
9421 	expr2 = isl_ast_expr_neg(expr2);
9422 	equal = isl_ast_expr_is_equal(expr, expr2);
9423 	str = isl_ast_expr_to_C_str(expr);
9424 	ok = str ? !strcmp(str, "-(A + B)") : -1;
9425 	free(str);
9426 	isl_ast_expr_free(expr);
9427 	isl_ast_expr_free(expr2);
9428 
9429 	if (ok < 0 || equal < 0)
9430 		return -1;
9431 	if (!equal)
9432 		isl_die(ctx, isl_error_unknown,
9433 			"equal expressions not considered equal", return -1);
9434 	if (!ok)
9435 		isl_die(ctx, isl_error_unknown,
9436 			"isl_ast_expr printed incorrectly", return -1);
9437 
9438 	expr1 = isl_ast_expr_from_id(isl_id_alloc(ctx, "A", NULL));
9439 	expr2 = isl_ast_expr_from_id(isl_id_alloc(ctx, "B", NULL));
9440 	expr = isl_ast_expr_add(expr1, expr2);
9441 	expr3 = isl_ast_expr_from_id(isl_id_alloc(ctx, "C", NULL));
9442 	expr = isl_ast_expr_sub(expr3, expr);
9443 	str = isl_ast_expr_to_C_str(expr);
9444 	ok = str ? !strcmp(str, "C - (A + B)") : -1;
9445 	free(str);
9446 	isl_ast_expr_free(expr);
9447 
9448 	if (ok < 0)
9449 		return -1;
9450 	if (!ok)
9451 		isl_die(ctx, isl_error_unknown,
9452 			"isl_ast_expr printed incorrectly", return -1);
9453 
9454 	return 0;
9455 }
9456 
9457 /* Check that isl_ast_build_expr_from_set returns a valid expression
9458  * for an empty set.  Note that isl_ast_build_expr_from_set getting
9459  * called on an empty set probably indicates a bug in the caller.
9460  */
test_ast_build(isl_ctx * ctx)9461 static int test_ast_build(isl_ctx *ctx)
9462 {
9463 	isl_set *set;
9464 	isl_ast_build *build;
9465 	isl_ast_expr *expr;
9466 
9467 	set = isl_set_universe(isl_space_params_alloc(ctx, 0));
9468 	build = isl_ast_build_from_context(set);
9469 
9470 	set = isl_set_empty(isl_space_params_alloc(ctx, 0));
9471 	expr = isl_ast_build_expr_from_set(build, set);
9472 
9473 	isl_ast_expr_free(expr);
9474 	isl_ast_build_free(build);
9475 
9476 	if (!expr)
9477 		return -1;
9478 
9479 	return 0;
9480 }
9481 
9482 /* Internal data structure for before_for and after_for callbacks.
9483  *
9484  * depth is the current depth
9485  * before is the number of times before_for has been called
9486  * after is the number of times after_for has been called
9487  */
9488 struct isl_test_codegen_data {
9489 	int depth;
9490 	int before;
9491 	int after;
9492 };
9493 
9494 /* This function is called before each for loop in the AST generated
9495  * from test_ast_gen1.
9496  *
9497  * Increment the number of calls and the depth.
9498  * Check that the space returned by isl_ast_build_get_schedule_space
9499  * matches the target space of the schedule returned by
9500  * isl_ast_build_get_schedule.
9501  * Return an isl_id that is checked by the corresponding call
9502  * to after_for.
9503  */
before_for(__isl_keep isl_ast_build * build,void * user)9504 static __isl_give isl_id *before_for(__isl_keep isl_ast_build *build,
9505 	void *user)
9506 {
9507 	struct isl_test_codegen_data *data = user;
9508 	isl_ctx *ctx;
9509 	isl_space *space;
9510 	isl_union_map *schedule;
9511 	isl_union_set *uset;
9512 	isl_set *set;
9513 	isl_bool empty;
9514 	isl_size n;
9515 	char name[] = "d0";
9516 
9517 	ctx = isl_ast_build_get_ctx(build);
9518 
9519 	if (data->before >= 3)
9520 		isl_die(ctx, isl_error_unknown,
9521 			"unexpected number of for nodes", return NULL);
9522 	if (data->depth < 0 || data->depth >= 2)
9523 		isl_die(ctx, isl_error_unknown,
9524 			"unexpected depth", return NULL);
9525 
9526 	snprintf(name, sizeof(name), "d%d", data->depth);
9527 	data->before++;
9528 	data->depth++;
9529 
9530 	schedule = isl_ast_build_get_schedule(build);
9531 	uset = isl_union_map_range(schedule);
9532 	n = isl_union_set_n_set(uset);
9533 	if (n != 1) {
9534 		isl_union_set_free(uset);
9535 		if (n < 0)
9536 			return NULL;
9537 		isl_die(ctx, isl_error_unknown,
9538 			"expecting single range space", return NULL);
9539 	}
9540 
9541 	space = isl_ast_build_get_schedule_space(build);
9542 	set = isl_union_set_extract_set(uset, space);
9543 	isl_union_set_free(uset);
9544 	empty = isl_set_is_empty(set);
9545 	isl_set_free(set);
9546 
9547 	if (empty < 0)
9548 		return NULL;
9549 	if (empty)
9550 		isl_die(ctx, isl_error_unknown,
9551 			"spaces don't match", return NULL);
9552 
9553 	return isl_id_alloc(ctx, name, NULL);
9554 }
9555 
9556 /* This function is called after each for loop in the AST generated
9557  * from test_ast_gen1.
9558  *
9559  * Increment the number of calls and decrement the depth.
9560  * Check that the annotation attached to the node matches
9561  * the isl_id returned by the corresponding call to before_for.
9562  */
after_for(__isl_take isl_ast_node * node,__isl_keep isl_ast_build * build,void * user)9563 static __isl_give isl_ast_node *after_for(__isl_take isl_ast_node *node,
9564 	__isl_keep isl_ast_build *build, void *user)
9565 {
9566 	struct isl_test_codegen_data *data = user;
9567 	isl_id *id;
9568 	const char *name;
9569 	int valid;
9570 
9571 	data->after++;
9572 	data->depth--;
9573 
9574 	if (data->after > data->before)
9575 		isl_die(isl_ast_node_get_ctx(node), isl_error_unknown,
9576 			"mismatch in number of for nodes",
9577 			return isl_ast_node_free(node));
9578 
9579 	id = isl_ast_node_get_annotation(node);
9580 	if (!id)
9581 		isl_die(isl_ast_node_get_ctx(node), isl_error_unknown,
9582 			"missing annotation", return isl_ast_node_free(node));
9583 
9584 	name = isl_id_get_name(id);
9585 	valid = name && atoi(name + 1) == data->depth;
9586 	isl_id_free(id);
9587 
9588 	if (!valid)
9589 		isl_die(isl_ast_node_get_ctx(node), isl_error_unknown,
9590 			"wrong annotation", return isl_ast_node_free(node));
9591 
9592 	return node;
9593 }
9594 
9595 /* Check that the before_each_for and after_each_for callbacks
9596  * are called for each for loop in the generated code,
9597  * that they are called in the right order and that the isl_id
9598  * returned from the before_each_for callback is attached to
9599  * the isl_ast_node passed to the corresponding after_each_for call.
9600  */
test_ast_gen1(isl_ctx * ctx)9601 static int test_ast_gen1(isl_ctx *ctx)
9602 {
9603 	const char *str;
9604 	isl_set *set;
9605 	isl_union_map *schedule;
9606 	isl_ast_build *build;
9607 	isl_ast_node *tree;
9608 	struct isl_test_codegen_data data;
9609 
9610 	str = "[N] -> { : N >= 10 }";
9611 	set = isl_set_read_from_str(ctx, str);
9612 	str = "[N] -> { A[i,j] -> S[8,i,3,j] : 0 <= i,j <= N; "
9613 		    "B[i,j] -> S[8,j,9,i] : 0 <= i,j <= N }";
9614 	schedule = isl_union_map_read_from_str(ctx, str);
9615 
9616 	data.before = 0;
9617 	data.after = 0;
9618 	data.depth = 0;
9619 	build = isl_ast_build_from_context(set);
9620 	build = isl_ast_build_set_before_each_for(build,
9621 			&before_for, &data);
9622 	build = isl_ast_build_set_after_each_for(build,
9623 			&after_for, &data);
9624 	tree = isl_ast_build_node_from_schedule_map(build, schedule);
9625 	isl_ast_build_free(build);
9626 	if (!tree)
9627 		return -1;
9628 
9629 	isl_ast_node_free(tree);
9630 
9631 	if (data.before != 3 || data.after != 3)
9632 		isl_die(ctx, isl_error_unknown,
9633 			"unexpected number of for nodes", return -1);
9634 
9635 	return 0;
9636 }
9637 
9638 /* Check that the AST generator handles domains that are integrally disjoint
9639  * but not rationally disjoint.
9640  */
test_ast_gen2(isl_ctx * ctx)9641 static int test_ast_gen2(isl_ctx *ctx)
9642 {
9643 	const char *str;
9644 	isl_set *set;
9645 	isl_union_map *schedule;
9646 	isl_union_map *options;
9647 	isl_ast_build *build;
9648 	isl_ast_node *tree;
9649 
9650 	str = "{ A[i,j] -> [i,j] : 0 <= i,j <= 1 }";
9651 	schedule = isl_union_map_read_from_str(ctx, str);
9652 	set = isl_set_universe(isl_space_params_alloc(ctx, 0));
9653 	build = isl_ast_build_from_context(set);
9654 
9655 	str = "{ [i,j] -> atomic[1] : i + j = 1; [i,j] -> unroll[1] : i = j }";
9656 	options = isl_union_map_read_from_str(ctx, str);
9657 	build = isl_ast_build_set_options(build, options);
9658 	tree = isl_ast_build_node_from_schedule_map(build, schedule);
9659 	isl_ast_build_free(build);
9660 	if (!tree)
9661 		return -1;
9662 	isl_ast_node_free(tree);
9663 
9664 	return 0;
9665 }
9666 
9667 /* Increment *user on each call.
9668  */
count_domains(__isl_take isl_ast_node * node,__isl_keep isl_ast_build * build,void * user)9669 static __isl_give isl_ast_node *count_domains(__isl_take isl_ast_node *node,
9670 	__isl_keep isl_ast_build *build, void *user)
9671 {
9672 	int *n = user;
9673 
9674 	(*n)++;
9675 
9676 	return node;
9677 }
9678 
9679 /* Test that unrolling tries to minimize the number of instances.
9680  * In particular, for the schedule given below, make sure it generates
9681  * 3 nodes (rather than 101).
9682  */
test_ast_gen3(isl_ctx * ctx)9683 static int test_ast_gen3(isl_ctx *ctx)
9684 {
9685 	const char *str;
9686 	isl_set *set;
9687 	isl_union_map *schedule;
9688 	isl_union_map *options;
9689 	isl_ast_build *build;
9690 	isl_ast_node *tree;
9691 	int n_domain = 0;
9692 
9693 	str = "[n] -> { A[i] -> [i] : 0 <= i <= 100 and n <= i <= n + 2 }";
9694 	schedule = isl_union_map_read_from_str(ctx, str);
9695 	set = isl_set_universe(isl_space_params_alloc(ctx, 0));
9696 
9697 	str = "{ [i] -> unroll[0] }";
9698 	options = isl_union_map_read_from_str(ctx, str);
9699 
9700 	build = isl_ast_build_from_context(set);
9701 	build = isl_ast_build_set_options(build, options);
9702 	build = isl_ast_build_set_at_each_domain(build,
9703 			&count_domains, &n_domain);
9704 	tree = isl_ast_build_node_from_schedule_map(build, schedule);
9705 	isl_ast_build_free(build);
9706 	if (!tree)
9707 		return -1;
9708 
9709 	isl_ast_node_free(tree);
9710 
9711 	if (n_domain != 3)
9712 		isl_die(ctx, isl_error_unknown,
9713 			"unexpected number of for nodes", return -1);
9714 
9715 	return 0;
9716 }
9717 
9718 /* Check that if the ast_build_exploit_nested_bounds options is set,
9719  * we do not get an outer if node in the generated AST,
9720  * while we do get such an outer if node if the options is not set.
9721  */
test_ast_gen4(isl_ctx * ctx)9722 static int test_ast_gen4(isl_ctx *ctx)
9723 {
9724 	const char *str;
9725 	isl_set *set;
9726 	isl_union_map *schedule;
9727 	isl_ast_build *build;
9728 	isl_ast_node *tree;
9729 	enum isl_ast_node_type type;
9730 	int enb;
9731 
9732 	enb = isl_options_get_ast_build_exploit_nested_bounds(ctx);
9733 	str = "[N,M] -> { A[i,j] -> [i,j] : 0 <= i <= N and 0 <= j <= M }";
9734 
9735 	isl_options_set_ast_build_exploit_nested_bounds(ctx, 1);
9736 
9737 	schedule = isl_union_map_read_from_str(ctx, str);
9738 	set = isl_set_universe(isl_space_params_alloc(ctx, 0));
9739 	build = isl_ast_build_from_context(set);
9740 	tree = isl_ast_build_node_from_schedule_map(build, schedule);
9741 	isl_ast_build_free(build);
9742 	if (!tree)
9743 		return -1;
9744 
9745 	type = isl_ast_node_get_type(tree);
9746 	isl_ast_node_free(tree);
9747 
9748 	if (type == isl_ast_node_if)
9749 		isl_die(ctx, isl_error_unknown,
9750 			"not expecting if node", return -1);
9751 
9752 	isl_options_set_ast_build_exploit_nested_bounds(ctx, 0);
9753 
9754 	schedule = isl_union_map_read_from_str(ctx, str);
9755 	set = isl_set_universe(isl_space_params_alloc(ctx, 0));
9756 	build = isl_ast_build_from_context(set);
9757 	tree = isl_ast_build_node_from_schedule_map(build, schedule);
9758 	isl_ast_build_free(build);
9759 	if (!tree)
9760 		return -1;
9761 
9762 	type = isl_ast_node_get_type(tree);
9763 	isl_ast_node_free(tree);
9764 
9765 	if (type != isl_ast_node_if)
9766 		isl_die(ctx, isl_error_unknown,
9767 			"expecting if node", return -1);
9768 
9769 	isl_options_set_ast_build_exploit_nested_bounds(ctx, enb);
9770 
9771 	return 0;
9772 }
9773 
9774 /* This function is called for each leaf in the AST generated
9775  * from test_ast_gen5.
9776  *
9777  * We finalize the AST generation by extending the outer schedule
9778  * with a zero-dimensional schedule.  If this results in any for loops,
9779  * then this means that we did not pass along enough information
9780  * about the outer schedule to the inner AST generation.
9781  */
create_leaf(__isl_take isl_ast_build * build,void * user)9782 static __isl_give isl_ast_node *create_leaf(__isl_take isl_ast_build *build,
9783 	void *user)
9784 {
9785 	isl_union_map *schedule, *extra;
9786 	isl_ast_node *tree;
9787 
9788 	schedule = isl_ast_build_get_schedule(build);
9789 	extra = isl_union_map_copy(schedule);
9790 	extra = isl_union_map_from_domain(isl_union_map_domain(extra));
9791 	schedule = isl_union_map_range_product(schedule, extra);
9792 	tree = isl_ast_build_node_from_schedule_map(build, schedule);
9793 	isl_ast_build_free(build);
9794 
9795 	if (!tree)
9796 		return NULL;
9797 
9798 	if (isl_ast_node_get_type(tree) == isl_ast_node_for)
9799 		isl_die(isl_ast_node_get_ctx(tree), isl_error_unknown,
9800 			"code should not contain any for loop",
9801 			return isl_ast_node_free(tree));
9802 
9803 	return tree;
9804 }
9805 
9806 /* Check that we do not lose any information when going back and
9807  * forth between internal and external schedule.
9808  *
9809  * In particular, we create an AST where we unroll the only
9810  * non-constant dimension in the schedule.  We therefore do
9811  * not expect any for loops in the AST.  However, older versions
9812  * of isl would not pass along enough information about the outer
9813  * schedule when performing an inner code generation from a create_leaf
9814  * callback, resulting in the inner code generation producing a for loop.
9815  */
test_ast_gen5(isl_ctx * ctx)9816 static int test_ast_gen5(isl_ctx *ctx)
9817 {
9818 	const char *str;
9819 	isl_set *set;
9820 	isl_union_map *schedule, *options;
9821 	isl_ast_build *build;
9822 	isl_ast_node *tree;
9823 
9824 	str = "{ A[] -> [1, 1, 2]; B[i] -> [1, i, 0] : i >= 1 and i <= 2 }";
9825 	schedule = isl_union_map_read_from_str(ctx, str);
9826 
9827 	str = "{ [a, b, c] -> unroll[1] : exists (e0 = [(a)/4]: "
9828 				"4e0 >= -1 + a - b and 4e0 <= -2 + a + b) }";
9829 	options = isl_union_map_read_from_str(ctx, str);
9830 
9831 	set = isl_set_universe(isl_space_params_alloc(ctx, 0));
9832 	build = isl_ast_build_from_context(set);
9833 	build = isl_ast_build_set_options(build, options);
9834         build = isl_ast_build_set_create_leaf(build, &create_leaf, NULL);
9835 	tree = isl_ast_build_node_from_schedule_map(build, schedule);
9836 	isl_ast_build_free(build);
9837 	isl_ast_node_free(tree);
9838 	if (!tree)
9839 		return -1;
9840 
9841 	return 0;
9842 }
9843 
9844 /* Check that the expression
9845  *
9846  *	[n] -> { [n/2] : n <= 0 and n % 2 = 0; [0] : n > 0 }
9847  *
9848  * is not combined into
9849  *
9850  *	min(n/2, 0)
9851  *
9852  * as this would result in n/2 being evaluated in parts of
9853  * the definition domain where n is not a multiple of 2.
9854  */
test_ast_expr(isl_ctx * ctx)9855 static int test_ast_expr(isl_ctx *ctx)
9856 {
9857 	const char *str;
9858 	isl_pw_aff *pa;
9859 	isl_ast_build *build;
9860 	isl_ast_expr *expr;
9861 	int min_max;
9862 	int is_min;
9863 
9864 	min_max = isl_options_get_ast_build_detect_min_max(ctx);
9865 	isl_options_set_ast_build_detect_min_max(ctx, 1);
9866 
9867 	str = "[n] -> { [n/2] : n <= 0 and n % 2 = 0; [0] : n > 0 }";
9868 	pa = isl_pw_aff_read_from_str(ctx, str);
9869 	build = isl_ast_build_alloc(ctx);
9870 	expr = isl_ast_build_expr_from_pw_aff(build, pa);
9871 	is_min = isl_ast_expr_get_type(expr) == isl_ast_expr_op &&
9872 		 isl_ast_expr_get_op_type(expr) == isl_ast_expr_op_min;
9873 	isl_ast_build_free(build);
9874 	isl_ast_expr_free(expr);
9875 
9876 	isl_options_set_ast_build_detect_min_max(ctx, min_max);
9877 
9878 	if (!expr)
9879 		return -1;
9880 	if (is_min)
9881 		isl_die(ctx, isl_error_unknown,
9882 			"expressions should not be combined", return -1);
9883 
9884 	return 0;
9885 }
9886 
test_ast_gen(isl_ctx * ctx)9887 static int test_ast_gen(isl_ctx *ctx)
9888 {
9889 	if (test_ast_gen1(ctx) < 0)
9890 		return -1;
9891 	if (test_ast_gen2(ctx) < 0)
9892 		return -1;
9893 	if (test_ast_gen3(ctx) < 0)
9894 		return -1;
9895 	if (test_ast_gen4(ctx) < 0)
9896 		return -1;
9897 	if (test_ast_gen5(ctx) < 0)
9898 		return -1;
9899 	if (test_ast_expr(ctx) < 0)
9900 		return -1;
9901 	return 0;
9902 }
9903 
9904 /* Check if dropping output dimensions from an isl_pw_multi_aff
9905  * works properly.
9906  */
test_pw_multi_aff(isl_ctx * ctx)9907 static int test_pw_multi_aff(isl_ctx *ctx)
9908 {
9909 	const char *str;
9910 	isl_pw_multi_aff *pma1, *pma2;
9911 	int equal;
9912 
9913 	str = "{ [i,j] -> [i+j, 4i-j] }";
9914 	pma1 = isl_pw_multi_aff_read_from_str(ctx, str);
9915 	str = "{ [i,j] -> [4i-j] }";
9916 	pma2 = isl_pw_multi_aff_read_from_str(ctx, str);
9917 
9918 	pma1 = isl_pw_multi_aff_drop_dims(pma1, isl_dim_out, 0, 1);
9919 
9920 	equal = isl_pw_multi_aff_plain_is_equal(pma1, pma2);
9921 
9922 	isl_pw_multi_aff_free(pma1);
9923 	isl_pw_multi_aff_free(pma2);
9924 	if (equal < 0)
9925 		return -1;
9926 	if (!equal)
9927 		isl_die(ctx, isl_error_unknown,
9928 			"expressions not equal", return -1);
9929 
9930 	return 0;
9931 }
9932 
9933 /* Check that we can properly parse multi piecewise affine expressions
9934  * where the piecewise affine expressions have different domains.
9935  */
test_multi_pw_aff_1(isl_ctx * ctx)9936 static int test_multi_pw_aff_1(isl_ctx *ctx)
9937 {
9938 	const char *str;
9939 	isl_set *dom, *dom2;
9940 	isl_multi_pw_aff *mpa1, *mpa2;
9941 	isl_pw_aff *pa;
9942 	int equal;
9943 	int equal_domain;
9944 
9945 	mpa1 = isl_multi_pw_aff_read_from_str(ctx, "{ [i] -> [i] }");
9946 	dom = isl_set_read_from_str(ctx, "{ [i] : i > 0 }");
9947 	mpa1 = isl_multi_pw_aff_intersect_domain(mpa1, dom);
9948 	mpa2 = isl_multi_pw_aff_read_from_str(ctx, "{ [i] -> [2i] }");
9949 	mpa2 = isl_multi_pw_aff_flat_range_product(mpa1, mpa2);
9950 	str = "{ [i] -> [(i : i > 0), 2i] }";
9951 	mpa1 = isl_multi_pw_aff_read_from_str(ctx, str);
9952 
9953 	equal = isl_multi_pw_aff_plain_is_equal(mpa1, mpa2);
9954 
9955 	pa = isl_multi_pw_aff_get_pw_aff(mpa1, 0);
9956 	dom = isl_pw_aff_domain(pa);
9957 	pa = isl_multi_pw_aff_get_pw_aff(mpa1, 1);
9958 	dom2 = isl_pw_aff_domain(pa);
9959 	equal_domain = isl_set_is_equal(dom, dom2);
9960 
9961 	isl_set_free(dom);
9962 	isl_set_free(dom2);
9963 	isl_multi_pw_aff_free(mpa1);
9964 	isl_multi_pw_aff_free(mpa2);
9965 
9966 	if (equal < 0)
9967 		return -1;
9968 	if (!equal)
9969 		isl_die(ctx, isl_error_unknown,
9970 			"expressions not equal", return -1);
9971 
9972 	if (equal_domain < 0)
9973 		return -1;
9974 	if (equal_domain)
9975 		isl_die(ctx, isl_error_unknown,
9976 			"domains unexpectedly equal", return -1);
9977 
9978 	return 0;
9979 }
9980 
9981 /* Check that the dimensions in the explicit domain
9982  * of a multi piecewise affine expression are properly
9983  * taken into account.
9984  */
test_multi_pw_aff_2(isl_ctx * ctx)9985 static int test_multi_pw_aff_2(isl_ctx *ctx)
9986 {
9987 	const char *str;
9988 	isl_bool involves1, involves2, involves3, equal;
9989 	isl_multi_pw_aff *mpa, *mpa1, *mpa2;
9990 
9991 	str = "{ A[x,y] -> B[] : x >= y }";
9992 	mpa = isl_multi_pw_aff_read_from_str(ctx, str);
9993 	involves1 = isl_multi_pw_aff_involves_dims(mpa, isl_dim_in, 0, 2);
9994 	mpa1 = isl_multi_pw_aff_copy(mpa);
9995 
9996 	mpa = isl_multi_pw_aff_insert_dims(mpa, isl_dim_in, 0, 1);
9997 	involves2 = isl_multi_pw_aff_involves_dims(mpa, isl_dim_in, 0, 1);
9998 	involves3 = isl_multi_pw_aff_involves_dims(mpa, isl_dim_in, 1, 2);
9999 	str = "{ [a,x,y] -> B[] : x >= y }";
10000 	mpa2 = isl_multi_pw_aff_read_from_str(ctx, str);
10001 	equal = isl_multi_pw_aff_plain_is_equal(mpa, mpa2);
10002 	isl_multi_pw_aff_free(mpa2);
10003 
10004 	mpa = isl_multi_pw_aff_drop_dims(mpa, isl_dim_in, 0, 1);
10005 	mpa = isl_multi_pw_aff_set_tuple_name(mpa, isl_dim_in, "A");
10006 	if (equal >= 0 && equal)
10007 		equal = isl_multi_pw_aff_plain_is_equal(mpa, mpa1);
10008 	isl_multi_pw_aff_free(mpa1);
10009 	isl_multi_pw_aff_free(mpa);
10010 
10011 	if (involves1 < 0 || involves2 < 0 || involves3 < 0 || equal < 0)
10012 		return -1;
10013 	if (!equal)
10014 		isl_die(ctx, isl_error_unknown,
10015 			"incorrect result of dimension insertion/removal",
10016 			return isl_stat_error);
10017 	if (!involves1 || involves2 || !involves3)
10018 		isl_die(ctx, isl_error_unknown,
10019 			"incorrect characterization of involved dimensions",
10020 			return isl_stat_error);
10021 
10022 	return 0;
10023 }
10024 
10025 /* Check that isl_multi_union_pw_aff_multi_val_on_domain
10026  * sets the explicit domain of a zero-dimensional result,
10027  * such that it can be converted to an isl_union_map.
10028  */
test_multi_pw_aff_3(isl_ctx * ctx)10029 static isl_stat test_multi_pw_aff_3(isl_ctx *ctx)
10030 {
10031 	isl_space *space;
10032 	isl_union_set *dom;
10033 	isl_multi_val *mv;
10034 	isl_multi_union_pw_aff *mupa;
10035 	isl_union_map *umap;
10036 
10037 	dom = isl_union_set_read_from_str(ctx, "{ A[]; B[] }");
10038 	space = isl_union_set_get_space(dom);
10039 	mv = isl_multi_val_zero(isl_space_set_from_params(space));
10040 	mupa = isl_multi_union_pw_aff_multi_val_on_domain(dom, mv);
10041 	umap = isl_union_map_from_multi_union_pw_aff(mupa);
10042 	isl_union_map_free(umap);
10043 	if (!umap)
10044 		return isl_stat_error;
10045 
10046 	return isl_stat_ok;
10047 }
10048 
10049 /* String descriptions of boxes that
10050  * are used for reconstructing box maps from their lower and upper bounds.
10051  */
10052 static const char *multi_pw_aff_box_tests[] = {
10053 	"{ A[x, y] -> [] : x + y >= 0 }",
10054 	"[N] -> { A[x, y] -> [x] : x + y <= N }",
10055 	"[N] -> { A[x, y] -> [x : y] : x + y <= N }",
10056 };
10057 
10058 /* Check that map representations of boxes can be reconstructed
10059  * from their lower and upper bounds.
10060  */
test_multi_pw_aff_box(isl_ctx * ctx)10061 static isl_stat test_multi_pw_aff_box(isl_ctx *ctx)
10062 {
10063 	int i;
10064 
10065 	for (i = 0; i < ARRAY_SIZE(multi_pw_aff_box_tests); ++i) {
10066 		const char *str;
10067 		isl_bool equal;
10068 		isl_map *map, *box;
10069 		isl_multi_pw_aff *min, *max;
10070 
10071 		str = multi_pw_aff_box_tests[i];
10072 		map = isl_map_read_from_str(ctx, str);
10073 		min = isl_map_min_multi_pw_aff(isl_map_copy(map));
10074 		max = isl_map_max_multi_pw_aff(isl_map_copy(map));
10075 		box = isl_map_universe(isl_map_get_space(map));
10076 		box = isl_map_lower_bound_multi_pw_aff(box, min);
10077 		box = isl_map_upper_bound_multi_pw_aff(box, max);
10078 		equal = isl_map_is_equal(map, box);
10079 		isl_map_free(map);
10080 		isl_map_free(box);
10081 		if (equal < 0)
10082 			return isl_stat_error;
10083 		if (!equal)
10084 			isl_die(ctx, isl_error_unknown,
10085 				"unexpected result", return isl_stat_error);
10086 	}
10087 
10088 	return isl_stat_ok;
10089 }
10090 
10091 /* Perform some tests on multi piecewise affine expressions.
10092  */
test_multi_pw_aff(isl_ctx * ctx)10093 static int test_multi_pw_aff(isl_ctx *ctx)
10094 {
10095 	if (test_multi_pw_aff_1(ctx) < 0)
10096 		return -1;
10097 	if (test_multi_pw_aff_2(ctx) < 0)
10098 		return -1;
10099 	if (test_multi_pw_aff_3(ctx) < 0)
10100 		return -1;
10101 	if (test_multi_pw_aff_box(ctx) < 0)
10102 		return -1;
10103 	return 0;
10104 }
10105 
10106 /* This is a regression test for a bug where isl_basic_map_simplify
10107  * would end up in an infinite loop.  In particular, we construct
10108  * an empty basic set that is not obviously empty.
10109  * isl_basic_set_is_empty marks the basic set as empty.
10110  * After projecting out i3, the variable can be dropped completely,
10111  * but isl_basic_map_simplify refrains from doing so if the basic set
10112  * is empty and would end up in an infinite loop if it didn't test
10113  * explicitly for empty basic maps in the outer loop.
10114  */
test_simplify_1(isl_ctx * ctx)10115 static int test_simplify_1(isl_ctx *ctx)
10116 {
10117 	const char *str;
10118 	isl_basic_set *bset;
10119 	int empty;
10120 
10121 	str = "{ [i0, i1, i2, i3] : i0 >= -2 and 6i2 <= 4 + i0 + 5i1 and "
10122 		"i2 <= 22 and 75i2 <= 111 + 13i0 + 60i1 and "
10123 		"25i2 >= 38 + 6i0 + 20i1 and i0 <= -1 and i2 >= 20 and "
10124 		"i3 >= i2 }";
10125 	bset = isl_basic_set_read_from_str(ctx, str);
10126 	empty = isl_basic_set_is_empty(bset);
10127 	bset = isl_basic_set_project_out(bset, isl_dim_set, 3, 1);
10128 	isl_basic_set_free(bset);
10129 	if (!bset)
10130 		return -1;
10131 	if (!empty)
10132 		isl_die(ctx, isl_error_unknown,
10133 			"basic set should be empty", return -1);
10134 
10135 	return 0;
10136 }
10137 
10138 /* Check that the equality in the set description below
10139  * is simplified away.
10140  */
test_simplify_2(isl_ctx * ctx)10141 static int test_simplify_2(isl_ctx *ctx)
10142 {
10143 	const char *str;
10144 	isl_basic_set *bset;
10145 	isl_bool universe;
10146 
10147 	str = "{ [a] : exists e0, e1: 32e1 = 31 + 31a + 31e0 }";
10148 	bset = isl_basic_set_read_from_str(ctx, str);
10149 	universe = isl_basic_set_plain_is_universe(bset);
10150 	isl_basic_set_free(bset);
10151 
10152 	if (universe < 0)
10153 		return -1;
10154 	if (!universe)
10155 		isl_die(ctx, isl_error_unknown,
10156 			"equality not simplified away", return -1);
10157 	return 0;
10158 }
10159 
10160 /* Some simplification tests.
10161  */
test_simplify(isl_ctx * ctx)10162 static int test_simplify(isl_ctx *ctx)
10163 {
10164 	if (test_simplify_1(ctx) < 0)
10165 		return -1;
10166 	if (test_simplify_2(ctx) < 0)
10167 		return -1;
10168 	return 0;
10169 }
10170 
10171 /* This is a regression test for a bug where isl_tab_basic_map_partial_lexopt
10172  * with gbr context would fail to disable the use of the shifted tableau
10173  * when transferring equalities for the input to the context, resulting
10174  * in invalid sample values.
10175  */
test_partial_lexmin(isl_ctx * ctx)10176 static int test_partial_lexmin(isl_ctx *ctx)
10177 {
10178 	const char *str;
10179 	isl_basic_set *bset;
10180 	isl_basic_map *bmap;
10181 	isl_map *map;
10182 
10183 	str = "{ [1, b, c, 1 - c] -> [e] : 2e <= -c and 2e >= -3 + c }";
10184 	bmap = isl_basic_map_read_from_str(ctx, str);
10185 	str = "{ [a, b, c, d] : c <= 1 and 2d >= 6 - 4b - c }";
10186 	bset = isl_basic_set_read_from_str(ctx, str);
10187 	map = isl_basic_map_partial_lexmin(bmap, bset, NULL);
10188 	isl_map_free(map);
10189 
10190 	if (!map)
10191 		return -1;
10192 
10193 	return 0;
10194 }
10195 
10196 /* Check that the variable compression performed on the existentially
10197  * quantified variables inside isl_basic_set_compute_divs is not confused
10198  * by the implicit equalities among the parameters.
10199  */
test_compute_divs(isl_ctx * ctx)10200 static int test_compute_divs(isl_ctx *ctx)
10201 {
10202 	const char *str;
10203 	isl_basic_set *bset;
10204 	isl_set *set;
10205 
10206 	str = "[a, b, c, d, e] -> { [] : exists (e0: 2d = b and a <= 124 and "
10207 		"b <= 2046 and b >= 0 and b <= 60 + 64a and 2e >= b + 2c and "
10208 		"2e >= b and 2e <= 1 + b and 2e <= 1 + b + 2c and "
10209 		"32768e0 >= -124 + a and 2097152e0 <= 60 + 64a - b) }";
10210 	bset = isl_basic_set_read_from_str(ctx, str);
10211 	set = isl_basic_set_compute_divs(bset);
10212 	isl_set_free(set);
10213 	if (!set)
10214 		return -1;
10215 
10216 	return 0;
10217 }
10218 
10219 /* Check that isl_schedule_get_map is not confused by a schedule tree
10220  * with divergent filter node parameters, as can result from a call
10221  * to isl_schedule_intersect_domain.
10222  */
test_schedule_tree(isl_ctx * ctx)10223 static int test_schedule_tree(isl_ctx *ctx)
10224 {
10225 	const char *str;
10226 	isl_union_set *uset;
10227 	isl_schedule *sched1, *sched2;
10228 	isl_union_map *umap;
10229 
10230 	uset = isl_union_set_read_from_str(ctx, "{ A[i] }");
10231 	sched1 = isl_schedule_from_domain(uset);
10232 	uset = isl_union_set_read_from_str(ctx, "{ B[] }");
10233 	sched2 = isl_schedule_from_domain(uset);
10234 
10235 	sched1 = isl_schedule_sequence(sched1, sched2);
10236 	str = "[n] -> { A[i] : 0 <= i < n; B[] }";
10237 	uset = isl_union_set_read_from_str(ctx, str);
10238 	sched1 = isl_schedule_intersect_domain(sched1, uset);
10239 	umap = isl_schedule_get_map(sched1);
10240 	isl_schedule_free(sched1);
10241 	isl_union_map_free(umap);
10242 	if (!umap)
10243 		return -1;
10244 
10245 	return 0;
10246 }
10247 
10248 /* Check that a zero-dimensional prefix schedule keeps track
10249  * of the domain and outer filters.
10250  */
test_schedule_tree_prefix(isl_ctx * ctx)10251 static int test_schedule_tree_prefix(isl_ctx *ctx)
10252 {
10253 	const char *str;
10254 	isl_bool equal;
10255 	isl_union_set *uset;
10256 	isl_union_set_list *filters;
10257 	isl_multi_union_pw_aff *mupa, *mupa2;
10258 	isl_schedule_node *node;
10259 
10260 	str = "{ S1[i,j] : 0 <= i,j < 10; S2[i,j] : 0 <= i,j < 10 }";
10261 	uset = isl_union_set_read_from_str(ctx, str);
10262 	node = isl_schedule_node_from_domain(uset);
10263 	node = isl_schedule_node_child(node, 0);
10264 
10265 	str = "{ S1[i,j] : i > j }";
10266 	uset = isl_union_set_read_from_str(ctx, str);
10267 	filters = isl_union_set_list_from_union_set(uset);
10268 	str = "{ S1[i,j] : i <= j; S2[i,j] }";
10269 	uset = isl_union_set_read_from_str(ctx, str);
10270 	filters = isl_union_set_list_add(filters, uset);
10271 	node = isl_schedule_node_insert_sequence(node, filters);
10272 
10273 	node = isl_schedule_node_child(node, 0);
10274 	node = isl_schedule_node_child(node, 0);
10275 	mupa = isl_schedule_node_get_prefix_schedule_multi_union_pw_aff(node);
10276 	str = "([] : { S1[i,j] : i > j })";
10277 	mupa2 = isl_multi_union_pw_aff_read_from_str(ctx, str);
10278 	equal = isl_multi_union_pw_aff_plain_is_equal(mupa, mupa2);
10279 	isl_multi_union_pw_aff_free(mupa2);
10280 	isl_multi_union_pw_aff_free(mupa);
10281 	isl_schedule_node_free(node);
10282 
10283 	if (equal < 0)
10284 		return -1;
10285 	if (!equal)
10286 		isl_die(ctx, isl_error_unknown, "unexpected prefix schedule",
10287 			return -1);
10288 
10289 	return 0;
10290 }
10291 
10292 /* Check that the reaching domain elements and the prefix schedule
10293  * at a leaf node are the same before and after grouping.
10294  */
test_schedule_tree_group_1(isl_ctx * ctx)10295 static int test_schedule_tree_group_1(isl_ctx *ctx)
10296 {
10297 	int equal;
10298 	const char *str;
10299 	isl_id *id;
10300 	isl_union_set *uset;
10301 	isl_multi_union_pw_aff *mupa;
10302 	isl_union_pw_multi_aff *upma1, *upma2;
10303 	isl_union_set *domain1, *domain2;
10304 	isl_union_map *umap1, *umap2;
10305 	isl_schedule_node *node;
10306 
10307 	str = "{ S1[i,j] : 0 <= i,j < 10; S2[i,j] : 0 <= i,j < 10 }";
10308 	uset = isl_union_set_read_from_str(ctx, str);
10309 	node = isl_schedule_node_from_domain(uset);
10310 	node = isl_schedule_node_child(node, 0);
10311 	str = "[{ S1[i,j] -> [i]; S2[i,j] -> [9 - i] }]";
10312 	mupa = isl_multi_union_pw_aff_read_from_str(ctx, str);
10313 	node = isl_schedule_node_insert_partial_schedule(node, mupa);
10314 	node = isl_schedule_node_child(node, 0);
10315 	str = "[{ S1[i,j] -> [j]; S2[i,j] -> [j] }]";
10316 	mupa = isl_multi_union_pw_aff_read_from_str(ctx, str);
10317 	node = isl_schedule_node_insert_partial_schedule(node, mupa);
10318 	node = isl_schedule_node_child(node, 0);
10319 	umap1 = isl_schedule_node_get_prefix_schedule_union_map(node);
10320 	upma1 = isl_schedule_node_get_prefix_schedule_union_pw_multi_aff(node);
10321 	domain1 = isl_schedule_node_get_domain(node);
10322 	id = isl_id_alloc(ctx, "group", NULL);
10323 	node = isl_schedule_node_parent(node);
10324 	node = isl_schedule_node_group(node, id);
10325 	node = isl_schedule_node_child(node, 0);
10326 	umap2 = isl_schedule_node_get_prefix_schedule_union_map(node);
10327 	upma2 = isl_schedule_node_get_prefix_schedule_union_pw_multi_aff(node);
10328 	domain2 = isl_schedule_node_get_domain(node);
10329 	equal = isl_union_pw_multi_aff_plain_is_equal(upma1, upma2);
10330 	if (equal >= 0 && equal)
10331 		equal = isl_union_set_is_equal(domain1, domain2);
10332 	if (equal >= 0 && equal)
10333 		equal = isl_union_map_is_equal(umap1, umap2);
10334 	isl_union_map_free(umap1);
10335 	isl_union_map_free(umap2);
10336 	isl_union_set_free(domain1);
10337 	isl_union_set_free(domain2);
10338 	isl_union_pw_multi_aff_free(upma1);
10339 	isl_union_pw_multi_aff_free(upma2);
10340 	isl_schedule_node_free(node);
10341 
10342 	if (equal < 0)
10343 		return -1;
10344 	if (!equal)
10345 		isl_die(ctx, isl_error_unknown,
10346 			"expressions not equal", return -1);
10347 
10348 	return 0;
10349 }
10350 
10351 /* Check that we can have nested groupings and that the union map
10352  * schedule representation is the same before and after the grouping.
10353  * Note that after the grouping, the union map representation contains
10354  * the domain constraints from the ranges of the expansion nodes,
10355  * while they are missing from the union map representation of
10356  * the tree without expansion nodes.
10357  *
10358  * Also check that the global expansion is as expected.
10359  */
test_schedule_tree_group_2(isl_ctx * ctx)10360 static int test_schedule_tree_group_2(isl_ctx *ctx)
10361 {
10362 	int equal, equal_expansion;
10363 	const char *str;
10364 	isl_id *id;
10365 	isl_union_set *uset;
10366 	isl_union_map *umap1, *umap2;
10367 	isl_union_map *expansion1, *expansion2;
10368 	isl_union_set_list *filters;
10369 	isl_multi_union_pw_aff *mupa;
10370 	isl_schedule *schedule;
10371 	isl_schedule_node *node;
10372 
10373 	str = "{ S1[i,j] : 0 <= i,j < 10; S2[i,j] : 0 <= i,j < 10; "
10374 		"S3[i,j] : 0 <= i,j < 10 }";
10375 	uset = isl_union_set_read_from_str(ctx, str);
10376 	node = isl_schedule_node_from_domain(uset);
10377 	node = isl_schedule_node_child(node, 0);
10378 	str = "[{ S1[i,j] -> [i]; S2[i,j] -> [i]; S3[i,j] -> [i] }]";
10379 	mupa = isl_multi_union_pw_aff_read_from_str(ctx, str);
10380 	node = isl_schedule_node_insert_partial_schedule(node, mupa);
10381 	node = isl_schedule_node_child(node, 0);
10382 	str = "{ S1[i,j] }";
10383 	uset = isl_union_set_read_from_str(ctx, str);
10384 	filters = isl_union_set_list_from_union_set(uset);
10385 	str = "{ S2[i,j]; S3[i,j] }";
10386 	uset = isl_union_set_read_from_str(ctx, str);
10387 	filters = isl_union_set_list_add(filters, uset);
10388 	node = isl_schedule_node_insert_sequence(node, filters);
10389 	node = isl_schedule_node_child(node, 1);
10390 	node = isl_schedule_node_child(node, 0);
10391 	str = "{ S2[i,j] }";
10392 	uset = isl_union_set_read_from_str(ctx, str);
10393 	filters = isl_union_set_list_from_union_set(uset);
10394 	str = "{ S3[i,j] }";
10395 	uset = isl_union_set_read_from_str(ctx, str);
10396 	filters = isl_union_set_list_add(filters, uset);
10397 	node = isl_schedule_node_insert_sequence(node, filters);
10398 
10399 	schedule = isl_schedule_node_get_schedule(node);
10400 	umap1 = isl_schedule_get_map(schedule);
10401 	uset = isl_schedule_get_domain(schedule);
10402 	umap1 = isl_union_map_intersect_domain(umap1, uset);
10403 	isl_schedule_free(schedule);
10404 
10405 	node = isl_schedule_node_parent(node);
10406 	node = isl_schedule_node_parent(node);
10407 	id = isl_id_alloc(ctx, "group1", NULL);
10408 	node = isl_schedule_node_group(node, id);
10409 	node = isl_schedule_node_child(node, 1);
10410 	node = isl_schedule_node_child(node, 0);
10411 	id = isl_id_alloc(ctx, "group2", NULL);
10412 	node = isl_schedule_node_group(node, id);
10413 
10414 	schedule = isl_schedule_node_get_schedule(node);
10415 	umap2 = isl_schedule_get_map(schedule);
10416 	isl_schedule_free(schedule);
10417 
10418 	node = isl_schedule_node_root(node);
10419 	node = isl_schedule_node_child(node, 0);
10420 	expansion1 = isl_schedule_node_get_subtree_expansion(node);
10421 	isl_schedule_node_free(node);
10422 
10423 	str = "{ group1[i] -> S1[i,j] : 0 <= i,j < 10; "
10424 		"group1[i] -> S2[i,j] : 0 <= i,j < 10; "
10425 		"group1[i] -> S3[i,j] : 0 <= i,j < 10 }";
10426 
10427 	expansion2 = isl_union_map_read_from_str(ctx, str);
10428 
10429 	equal = isl_union_map_is_equal(umap1, umap2);
10430 	equal_expansion = isl_union_map_is_equal(expansion1, expansion2);
10431 
10432 	isl_union_map_free(umap1);
10433 	isl_union_map_free(umap2);
10434 	isl_union_map_free(expansion1);
10435 	isl_union_map_free(expansion2);
10436 
10437 	if (equal < 0 || equal_expansion < 0)
10438 		return -1;
10439 	if (!equal)
10440 		isl_die(ctx, isl_error_unknown,
10441 			"expressions not equal", return -1);
10442 	if (!equal_expansion)
10443 		isl_die(ctx, isl_error_unknown,
10444 			"unexpected expansion", return -1);
10445 
10446 	return 0;
10447 }
10448 
10449 /* Some tests for the isl_schedule_node_group function.
10450  */
test_schedule_tree_group(isl_ctx * ctx)10451 static int test_schedule_tree_group(isl_ctx *ctx)
10452 {
10453 	if (test_schedule_tree_group_1(ctx) < 0)
10454 		return -1;
10455 	if (test_schedule_tree_group_2(ctx) < 0)
10456 		return -1;
10457 	return 0;
10458 }
10459 
10460 struct {
10461 	const char *set;
10462 	const char *dual;
10463 } coef_tests[] = {
10464 	{ "{ rat: [i] : 0 <= i <= 10 }",
10465 	  "{ rat: coefficients[[cst] -> [a]] : cst >= 0 and 10a + cst >= 0 }" },
10466 	{ "{ rat: [i] : FALSE }",
10467 	  "{ rat: coefficients[[cst] -> [a]] }" },
10468 	{ "{ rat: [i] : }",
10469 	  "{ rat: coefficients[[cst] -> [0]] : cst >= 0 }" },
10470 	{ "{ [0:,1,2:3] }",
10471 	  "{ rat: coefficients[[c_cst] -> [a, b, c]] : "
10472 		"a >= 0 and 2c >= -c_cst - b and 3c >= -c_cst - b }" },
10473 	{ "[M, N] -> { [x = (1 - N):-1, -4x:(M - 4x)] }",
10474 	  "{ rat: coefficients[[c_cst, c_M = 0:, c_N = 0:] -> [a, b = -c_M:]] :"
10475 		"4b >= -c_N + a and 4b >= -c_cst - 2c_N + a }" },
10476 	{ "{ rat : [x, y] : 1 <= 2x <= 9 and 2 <= 3y <= 16 }",
10477 	  "{ rat: coefficients[[c_cst] -> [c_x, c_y]] : "
10478 		"4c_y >= -6c_cst - 3c_x and 4c_y >= -6c_cst - 27c_x and "
10479 		"32c_y >= -6c_cst - 3c_x and 32c_y >= -6c_cst - 27c_x }" },
10480 	{ "{ [x, y, z] : 3y <= 2x - 2 and y >= -2 + 2x and 2y >= 2 - x }",
10481 	  "{ rat: coefficients[[cst] -> [a, b, c]] }" },
10482 };
10483 
10484 struct {
10485 	const char *set;
10486 	const char *dual;
10487 } sol_tests[] = {
10488 	{ "{ rat: coefficients[[cst] -> [a]] : cst >= 0 and 10a + cst >= 0 }",
10489 	  "{ rat: [i] : 0 <= i <= 10 }" },
10490 	{ "{ rat: coefficients[[cst] -> [a]] : FALSE }",
10491 	  "{ rat: [i] }" },
10492 	{ "{ rat: coefficients[[cst] -> [a]] }",
10493 	  "{ rat: [i] : FALSE }" },
10494 };
10495 
10496 /* Test the basic functionality of isl_basic_set_coefficients and
10497  * isl_basic_set_solutions.
10498  */
test_dual(isl_ctx * ctx)10499 static int test_dual(isl_ctx *ctx)
10500 {
10501 	int i;
10502 
10503 	for (i = 0; i < ARRAY_SIZE(coef_tests); ++i) {
10504 		int equal;
10505 		isl_basic_set *bset1, *bset2;
10506 
10507 		bset1 = isl_basic_set_read_from_str(ctx, coef_tests[i].set);
10508 		bset2 = isl_basic_set_read_from_str(ctx, coef_tests[i].dual);
10509 		bset1 = isl_basic_set_coefficients(bset1);
10510 		equal = isl_basic_set_is_equal(bset1, bset2);
10511 		isl_basic_set_free(bset1);
10512 		isl_basic_set_free(bset2);
10513 		if (equal < 0)
10514 			return -1;
10515 		if (!equal)
10516 			isl_die(ctx, isl_error_unknown,
10517 				"incorrect dual", return -1);
10518 	}
10519 
10520 	for (i = 0; i < ARRAY_SIZE(sol_tests); ++i) {
10521 		int equal;
10522 		isl_basic_set *bset1, *bset2;
10523 
10524 		bset1 = isl_basic_set_read_from_str(ctx, sol_tests[i].set);
10525 		bset2 = isl_basic_set_read_from_str(ctx, sol_tests[i].dual);
10526 		bset1 = isl_basic_set_solutions(bset1);
10527 		equal = isl_basic_set_is_equal(bset1, bset2);
10528 		isl_basic_set_free(bset1);
10529 		isl_basic_set_free(bset2);
10530 		if (equal < 0)
10531 			return -1;
10532 		if (!equal)
10533 			isl_die(ctx, isl_error_unknown,
10534 				"incorrect dual", return -1);
10535 	}
10536 
10537 	return 0;
10538 }
10539 
10540 struct {
10541 	int scale_tile;
10542 	int shift_point;
10543 	const char *domain;
10544 	const char *schedule;
10545 	const char *sizes;
10546 	const char *tile;
10547 	const char *point;
10548 } tile_tests[] = {
10549 	{ 0, 0, "[n] -> { S[i,j] : 0 <= i,j < n }",
10550 	  "[{ S[i,j] -> [i] }, { S[i,j] -> [j] }]",
10551 	  "{ [32,32] }",
10552 	  "[{ S[i,j] -> [floor(i/32)] }, { S[i,j] -> [floor(j/32)] }]",
10553 	  "[{ S[i,j] -> [i] }, { S[i,j] -> [j] }]",
10554 	},
10555 	{ 1, 0, "[n] -> { S[i,j] : 0 <= i,j < n }",
10556 	  "[{ S[i,j] -> [i] }, { S[i,j] -> [j] }]",
10557 	  "{ [32,32] }",
10558 	  "[{ S[i,j] -> [32*floor(i/32)] }, { S[i,j] -> [32*floor(j/32)] }]",
10559 	  "[{ S[i,j] -> [i] }, { S[i,j] -> [j] }]",
10560 	},
10561 	{ 0, 1, "[n] -> { S[i,j] : 0 <= i,j < n }",
10562 	  "[{ S[i,j] -> [i] }, { S[i,j] -> [j] }]",
10563 	  "{ [32,32] }",
10564 	  "[{ S[i,j] -> [floor(i/32)] }, { S[i,j] -> [floor(j/32)] }]",
10565 	  "[{ S[i,j] -> [i%32] }, { S[i,j] -> [j%32] }]",
10566 	},
10567 	{ 1, 1, "[n] -> { S[i,j] : 0 <= i,j < n }",
10568 	  "[{ S[i,j] -> [i] }, { S[i,j] -> [j] }]",
10569 	  "{ [32,32] }",
10570 	  "[{ S[i,j] -> [32*floor(i/32)] }, { S[i,j] -> [32*floor(j/32)] }]",
10571 	  "[{ S[i,j] -> [i%32] }, { S[i,j] -> [j%32] }]",
10572 	},
10573 };
10574 
10575 /* Basic tiling tests.  Create a schedule tree with a domain and a band node,
10576  * tile the band and then check if the tile and point bands have the
10577  * expected partial schedule.
10578  */
test_tile(isl_ctx * ctx)10579 static int test_tile(isl_ctx *ctx)
10580 {
10581 	int i;
10582 	int scale;
10583 	int shift;
10584 
10585 	scale = isl_options_get_tile_scale_tile_loops(ctx);
10586 	shift = isl_options_get_tile_shift_point_loops(ctx);
10587 
10588 	for (i = 0; i < ARRAY_SIZE(tile_tests); ++i) {
10589 		int opt;
10590 		int equal;
10591 		const char *str;
10592 		isl_union_set *domain;
10593 		isl_multi_union_pw_aff *mupa, *mupa2;
10594 		isl_schedule_node *node;
10595 		isl_multi_val *sizes;
10596 
10597 		opt = tile_tests[i].scale_tile;
10598 		isl_options_set_tile_scale_tile_loops(ctx, opt);
10599 		opt = tile_tests[i].shift_point;
10600 		isl_options_set_tile_shift_point_loops(ctx, opt);
10601 
10602 		str = tile_tests[i].domain;
10603 		domain = isl_union_set_read_from_str(ctx, str);
10604 		node = isl_schedule_node_from_domain(domain);
10605 		node = isl_schedule_node_child(node, 0);
10606 		str = tile_tests[i].schedule;
10607 		mupa = isl_multi_union_pw_aff_read_from_str(ctx, str);
10608 		node = isl_schedule_node_insert_partial_schedule(node, mupa);
10609 		str = tile_tests[i].sizes;
10610 		sizes = isl_multi_val_read_from_str(ctx, str);
10611 		node = isl_schedule_node_band_tile(node, sizes);
10612 
10613 		str = tile_tests[i].tile;
10614 		mupa = isl_multi_union_pw_aff_read_from_str(ctx, str);
10615 		mupa2 = isl_schedule_node_band_get_partial_schedule(node);
10616 		equal = isl_multi_union_pw_aff_plain_is_equal(mupa, mupa2);
10617 		isl_multi_union_pw_aff_free(mupa);
10618 		isl_multi_union_pw_aff_free(mupa2);
10619 
10620 		node = isl_schedule_node_child(node, 0);
10621 
10622 		str = tile_tests[i].point;
10623 		mupa = isl_multi_union_pw_aff_read_from_str(ctx, str);
10624 		mupa2 = isl_schedule_node_band_get_partial_schedule(node);
10625 		if (equal >= 0 && equal)
10626 			equal = isl_multi_union_pw_aff_plain_is_equal(mupa,
10627 									mupa2);
10628 		isl_multi_union_pw_aff_free(mupa);
10629 		isl_multi_union_pw_aff_free(mupa2);
10630 
10631 		isl_schedule_node_free(node);
10632 
10633 		if (equal < 0)
10634 			return -1;
10635 		if (!equal)
10636 			isl_die(ctx, isl_error_unknown,
10637 				"unexpected result", return -1);
10638 	}
10639 
10640 	isl_options_set_tile_scale_tile_loops(ctx, scale);
10641 	isl_options_set_tile_shift_point_loops(ctx, shift);
10642 
10643 	return 0;
10644 }
10645 
10646 /* Check that the domain hash of a space is equal to the hash
10647  * of the domain of the space, both ignoring parameters.
10648  */
test_domain_hash(isl_ctx * ctx)10649 static int test_domain_hash(isl_ctx *ctx)
10650 {
10651 	isl_map *map;
10652 	isl_space *space;
10653 	uint32_t hash1, hash2;
10654 
10655 	map = isl_map_read_from_str(ctx, "[n] -> { A[B[x] -> C[]] -> D[] }");
10656 	space = isl_map_get_space(map);
10657 	isl_map_free(map);
10658 	hash1 = isl_space_get_tuple_domain_hash(space);
10659 	space = isl_space_domain(space);
10660 	hash2 = isl_space_get_tuple_hash(space);
10661 	isl_space_free(space);
10662 
10663 	if (!space)
10664 		return -1;
10665 	if (hash1 != hash2)
10666 		isl_die(ctx, isl_error_unknown,
10667 			"domain hash not equal to hash of domain", return -1);
10668 
10669 	return 0;
10670 }
10671 
10672 /* Check that a universe basic set that is not obviously equal to the universe
10673  * is still recognized as being equal to the universe.
10674  */
test_universe(isl_ctx * ctx)10675 static int test_universe(isl_ctx *ctx)
10676 {
10677 	const char *s;
10678 	isl_basic_set *bset;
10679 	isl_bool is_univ;
10680 
10681 	s = "{ [] : exists x, y : 3y <= 2x and y >= -3 + 2x and 2y >= 2 - x }";
10682 	bset = isl_basic_set_read_from_str(ctx, s);
10683 	is_univ = isl_basic_set_is_universe(bset);
10684 	isl_basic_set_free(bset);
10685 
10686 	if (is_univ < 0)
10687 		return -1;
10688 	if (!is_univ)
10689 		isl_die(ctx, isl_error_unknown,
10690 			"not recognized as universe set", return -1);
10691 
10692 	return 0;
10693 }
10694 
10695 /* Sets for which chambers are computed and checked.
10696  */
10697 const char *chambers_tests[] = {
10698 	"[A, B, C] -> { [x, y, z] : x >= 0 and y >= 0 and y <= A - x and "
10699 				"z >= 0 and z <= C - y and z <= B - x - y }",
10700 };
10701 
10702 /* Add the domain of "cell" to "cells".
10703  */
add_cell(__isl_take isl_cell * cell,void * user)10704 static isl_stat add_cell(__isl_take isl_cell *cell, void *user)
10705 {
10706 	isl_basic_set_list **cells = user;
10707 	isl_basic_set *dom;
10708 
10709 	dom = isl_cell_get_domain(cell);
10710 	isl_cell_free(cell);
10711 	*cells = isl_basic_set_list_add(*cells, dom);
10712 
10713 	return *cells ? isl_stat_ok : isl_stat_error;
10714 }
10715 
10716 /* Check that the elements of "list" are pairwise disjoint.
10717  */
check_pairwise_disjoint(__isl_keep isl_basic_set_list * list)10718 static isl_stat check_pairwise_disjoint(__isl_keep isl_basic_set_list *list)
10719 {
10720 	int i, j;
10721 	isl_size n;
10722 
10723 	n = isl_basic_set_list_n_basic_set(list);
10724 	if (n < 0)
10725 		return isl_stat_error;
10726 
10727 	for (i = 0; i < n; ++i) {
10728 		isl_basic_set *bset_i;
10729 
10730 		bset_i = isl_basic_set_list_get_basic_set(list, i);
10731 		for (j = i + 1; j < n; ++j) {
10732 			isl_basic_set *bset_j;
10733 			isl_bool disjoint;
10734 
10735 			bset_j = isl_basic_set_list_get_basic_set(list, j);
10736 			disjoint = isl_basic_set_is_disjoint(bset_i, bset_j);
10737 			isl_basic_set_free(bset_j);
10738 			if (!disjoint)
10739 				isl_die(isl_basic_set_list_get_ctx(list),
10740 					isl_error_unknown, "not disjoint",
10741 					break);
10742 			if (disjoint < 0 || !disjoint)
10743 				break;
10744 		}
10745 		isl_basic_set_free(bset_i);
10746 		if (j < n)
10747 			return isl_stat_error;
10748 	}
10749 
10750 	return isl_stat_ok;
10751 }
10752 
10753 /* Check that the chambers computed by isl_vertices_foreach_disjoint_cell
10754  * are pairwise disjoint.
10755  */
test_chambers(isl_ctx * ctx)10756 static int test_chambers(isl_ctx *ctx)
10757 {
10758 	int i;
10759 
10760 	for (i = 0; i < ARRAY_SIZE(chambers_tests); ++i) {
10761 		isl_basic_set *bset;
10762 		isl_vertices *vertices;
10763 		isl_basic_set_list *cells;
10764 		isl_stat ok;
10765 
10766 		bset = isl_basic_set_read_from_str(ctx, chambers_tests[i]);
10767 		vertices = isl_basic_set_compute_vertices(bset);
10768 		cells = isl_basic_set_list_alloc(ctx, 0);
10769 		if (isl_vertices_foreach_disjoint_cell(vertices, &add_cell,
10770 							&cells) < 0)
10771 			cells = isl_basic_set_list_free(cells);
10772 		ok = check_pairwise_disjoint(cells);
10773 		isl_basic_set_list_free(cells);
10774 		isl_vertices_free(vertices);
10775 		isl_basic_set_free(bset);
10776 
10777 		if (ok < 0)
10778 			return -1;
10779 	}
10780 
10781 	return 0;
10782 }
10783 
10784 struct {
10785 	const char *name;
10786 	int (*fn)(isl_ctx *ctx);
10787 } tests [] = {
10788 	{ "universe", &test_universe },
10789 	{ "domain hash", &test_domain_hash },
10790 	{ "dual", &test_dual },
10791 	{ "dependence analysis", &test_flow },
10792 	{ "val", &test_val },
10793 	{ "compute divs", &test_compute_divs },
10794 	{ "partial lexmin", &test_partial_lexmin },
10795 	{ "simplify", &test_simplify },
10796 	{ "curry", &test_curry },
10797 	{ "piecewise multi affine expressions", &test_pw_multi_aff },
10798 	{ "multi piecewise affine expressions", &test_multi_pw_aff },
10799 	{ "conversion", &test_conversion },
10800 	{ "list", &test_list },
10801 	{ "align parameters", &test_align_parameters },
10802 	{ "drop unused parameters", &test_drop_unused_parameters },
10803 	{ "pullback", &test_pullback },
10804 	{ "AST", &test_ast },
10805 	{ "AST build", &test_ast_build },
10806 	{ "AST generation", &test_ast_gen },
10807 	{ "eliminate", &test_eliminate },
10808 	{ "deltas_map", &test_deltas_map },
10809 	{ "residue class", &test_residue_class },
10810 	{ "div", &test_div },
10811 	{ "slice", &test_slice },
10812 	{ "fixed power", &test_fixed_power },
10813 	{ "sample", &test_sample },
10814 	{ "empty projection", &test_empty_projection },
10815 	{ "output", &test_output },
10816 	{ "vertices", &test_vertices },
10817 	{ "chambers", &test_chambers },
10818 	{ "fixed", &test_fixed },
10819 	{ "equal", &test_equal },
10820 	{ "disjoint", &test_disjoint },
10821 	{ "product", &test_product },
10822 	{ "dim_max", &test_dim_max },
10823 	{ "affine", &test_aff },
10824 	{ "injective", &test_injective },
10825 	{ "schedule (whole component)", &test_schedule_whole },
10826 	{ "schedule (incremental)", &test_schedule_incremental },
10827 	{ "schedule tree", &test_schedule_tree },
10828 	{ "schedule tree prefix", &test_schedule_tree_prefix },
10829 	{ "schedule tree grouping", &test_schedule_tree_group },
10830 	{ "tile", &test_tile },
10831 	{ "union map", &test_union_map },
10832 	{ "union_pw", &test_union_pw },
10833 	{ "locus", &test_locus },
10834 	{ "eval", &test_eval },
10835 	{ "parse", &test_parse },
10836 	{ "single-valued", &test_sv },
10837 	{ "recession cone", &test_recession_cone },
10838 	{ "affine hull", &test_affine_hull },
10839 	{ "simple_hull", &test_simple_hull },
10840 	{ "box hull", &test_box_hull },
10841 	{ "coalesce", &test_coalesce },
10842 	{ "factorize", &test_factorize },
10843 	{ "subset", &test_subset },
10844 	{ "subtract", &test_subtract },
10845 	{ "intersect", &test_intersect },
10846 	{ "lexmin", &test_lexmin },
10847 	{ "min", &test_min },
10848 	{ "set lower bounds", &test_min_mpa },
10849 	{ "gist", &test_gist },
10850 	{ "piecewise quasi-polynomials", &test_pwqp },
10851 	{ "lift", &test_lift },
10852 	{ "bind parameters", &test_bind },
10853 	{ "unbind parameters", &test_unbind },
10854 	{ "bound", &test_bound },
10855 	{ "get lists", &test_get_list },
10856 	{ "union", &test_union },
10857 	{ "split periods", &test_split_periods },
10858 	{ "lexicographic order", &test_lex },
10859 	{ "bijectivity", &test_bijective },
10860 	{ "dataflow analysis", &test_dep },
10861 	{ "reading", &test_read },
10862 	{ "bounded", &test_bounded },
10863 	{ "construction", &test_construction },
10864 	{ "dimension manipulation", &test_dim },
10865 	{ "map application", &test_application },
10866 	{ "convex hull", &test_convex_hull },
10867 	{ "transitive closure", &test_closure },
10868 	{ "isl_bool", &test_isl_bool},
10869 };
10870 
main(int argc,char ** argv)10871 int main(int argc, char **argv)
10872 {
10873 	int i;
10874 	struct isl_ctx *ctx;
10875 	struct isl_options *options;
10876 
10877 	options = isl_options_new_with_defaults();
10878 	assert(options);
10879 	argc = isl_options_parse(options, argc, argv, ISL_ARG_ALL);
10880 
10881 	ctx = isl_ctx_alloc_with_options(&isl_options_args, options);
10882 	for (i = 0; i < ARRAY_SIZE(tests); ++i) {
10883 		printf("%s\n", tests[i].name);
10884 		if (tests[i].fn(ctx) < 0)
10885 			goto error;
10886 	}
10887 	isl_ctx_free(ctx);
10888 	return 0;
10889 error:
10890 	isl_ctx_free(ctx);
10891 	return -1;
10892 }
10893