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 };
139 
140 #undef BASE
141 #define BASE multi_pw_aff
142 
143 #include "check_reparse_templ.c"
144 #include "check_reparse_test_templ.c"
145 
146 /* String descriptions of piecewise multi affine expressions
147  * that are used for testing printing and parsing.
148  */
149 static const char *reparse_pw_multi_aff_tests[] = {
150 	"{ [x] -> [x] }",
151 	"{ [x] -> [x % 4] }",
152 	"{ [x] -> [x % 4] : x mod 3 = 1 }",
153 	"{ [x, x] -> [x % 4] }",
154 	"{ [x, x + 1] -> [x % 4] : x mod 3 = 1 }",
155 	"{ [x, x mod 2] -> [x % 4] }",
156 };
157 
158 #undef BASE
159 #define BASE pw_multi_aff
160 
161 #include "check_reparse_templ.c"
162 #include "check_reparse_test_templ.c"
163 
164 /* Test parsing of piecewise multi affine expressions by printing
165  * the expressions and checking that parsing the output results
166  * in the same expression.
167  * Do this for an expression converted from a map with an output
168  * dimension name that is equal to an automatically generated name, and
169  * a set of expressions parsed from strings.
170  */
test_parse_pma(isl_ctx * ctx)171 static isl_stat test_parse_pma(isl_ctx *ctx)
172 {
173 	isl_map *map;
174 	isl_pw_multi_aff *pma;
175 
176 	map = isl_map_read_from_str(ctx, "{ [a, a] -> [i1 = a + 1] }");
177 	pma = isl_pw_multi_aff_from_map(map);
178 	if (check_reparse_pw_multi_aff(ctx, pma) < 0)
179 		return isl_stat_error;
180 
181 	if (check_reparse_pw_multi_aff_tests(ctx) < 0)
182 		return isl_stat_error;
183 
184 	return isl_stat_ok;
185 }
186 
187 /* Test parsing of multi piecewise affine expressions by printing
188  * the expressions and checking that parsing the output results
189  * in the same expression.
190  * Do this for a couple of manually constructed expressions,
191  * an expression converted from a map with an output dimension name
192  * that is equal to an automatically generated name, and
193  * a set of expressions parsed from strings.
194  */
test_parse_mpa(isl_ctx * ctx)195 static int test_parse_mpa(isl_ctx *ctx)
196 {
197 	isl_space *space;
198 	isl_set *dom;
199 	isl_map *map;
200 	isl_pw_multi_aff *pma;
201 	isl_multi_pw_aff *mpa;
202 	isl_stat r;
203 
204 	space = isl_space_set_alloc(ctx, 0, 0);
205 	space = isl_space_set_tuple_name(space, isl_dim_set, "A");
206 	mpa = isl_multi_pw_aff_zero(space);
207 	r = check_reparse_multi_pw_aff(ctx, mpa);
208 	if (r < 0)
209 		return -1;
210 
211 	space = isl_space_set_alloc(ctx, 1, 0);
212 	space = isl_space_set_dim_name(space, isl_dim_param, 0, "N");
213 	space = isl_space_set_tuple_name(space, isl_dim_set, "A");
214 	dom = isl_set_universe(isl_space_params(isl_space_copy(space)));
215 	dom = isl_set_lower_bound_si(dom, isl_dim_param, 0, 5);
216 	mpa = isl_multi_pw_aff_zero(space);
217 	mpa = isl_multi_pw_aff_intersect_domain(mpa, dom);
218 	r = check_reparse_multi_pw_aff(ctx, mpa);
219 	if (r < 0)
220 		return -1;
221 
222 	map = isl_map_read_from_str(ctx, "{ [a, a] -> [i1 = a + 1] }");
223 	pma = isl_pw_multi_aff_from_map(map);
224 	mpa = isl_multi_pw_aff_from_pw_multi_aff(pma);
225 	if (check_reparse_multi_pw_aff(ctx, mpa) < 0)
226 		return -1;
227 
228 	if (check_reparse_multi_pw_aff_tests(ctx) < 0)
229 		return -1;
230 
231 	return 0;
232 }
233 
234 /* String descriptions of multi union piecewise affine expressions
235  * that are used for testing printing and parsing.
236  */
237 static const char *reparse_multi_union_pw_aff_tests[] = {
238 	"[]",
239 	"A[]",
240 	"A[B[] -> C[]]",
241 	"(A[] : { S[x] : x > 0; T[y] : y >= 0 })",
242 	"(A[] : { })",
243 	"[N] -> (A[] : { })",
244 	"[N] -> (A[] : { : N >= 0 })",
245 	"[N] -> (A[] : { S[x] : x > N; T[y] : y >= 0 })",
246 	"(A[] : [N] -> { S[x] : x > N; T[y] : y >= 0 })",
247 	"A[{ S[x] -> [x + 1]; T[x] -> [x] }]",
248 	"(A[{ S[x] -> [x + 1]; T[x] -> [x] }] : "
249 		"{ S[x] : x > 0; T[y] : y >= 0 })",
250 };
251 
252 #undef BASE
253 #define BASE multi_union_pw_aff
254 
255 #include "check_reparse_templ.c"
256 #include "check_reparse_test_templ.c"
257 
258 /* Test parsing of multi union piecewise affine expressions by printing
259  * the expressions and checking that parsing the output results
260  * in the same expression.
261  * Do this for a couple of manually constructed expressions and
262  * a set of expressions parsed from strings.
263  */
test_parse_mupa(isl_ctx * ctx)264 static int test_parse_mupa(isl_ctx *ctx)
265 {
266 	isl_space *space;
267 	isl_multi_union_pw_aff *mupa;
268 	isl_set *dom;
269 	isl_union_set *uset;
270 	isl_stat r;
271 
272 	space = isl_space_set_alloc(ctx, 0, 0);
273 	space = isl_space_set_tuple_name(space, isl_dim_set, "A");
274 	mupa = isl_multi_union_pw_aff_zero(space);
275 	r = check_reparse_multi_union_pw_aff(ctx, mupa);
276 	if (r < 0)
277 		return -1;
278 
279 	space = isl_space_set_alloc(ctx, 1, 0);
280 	space = isl_space_set_dim_name(space, isl_dim_param, 0, "N");
281 	space = isl_space_set_tuple_name(space, isl_dim_set, "A");
282 	dom = isl_set_universe(space);
283 	dom = isl_set_lower_bound_si(dom, isl_dim_param, 0, 5);
284 	uset = isl_union_set_from_set(dom);
285 	space = isl_space_set_alloc(ctx, 1, 0);
286 	space = isl_space_set_dim_name(space, isl_dim_param, 0, "N");
287 	space = isl_space_set_tuple_name(space, isl_dim_set, "B");
288 	mupa = isl_multi_union_pw_aff_zero(space);
289 	mupa = isl_multi_union_pw_aff_intersect_domain(mupa, uset);
290 	r = check_reparse_multi_union_pw_aff(ctx, mupa);
291 	if (r < 0)
292 		return -1;
293 
294 	if (check_reparse_multi_union_pw_aff_tests(ctx) < 0)
295 		return -1;
296 
297 	return 0;
298 }
299 
300 /* Test parsing of multi expressions.
301  */
test_parse_multi(isl_ctx * ctx)302 static int test_parse_multi(isl_ctx *ctx)
303 {
304 	if (test_parse_mpa(ctx) < 0)
305 		return -1;
306 	if (test_parse_mupa(ctx) < 0)
307 		return -1;
308 
309 	return 0;
310 }
311 
312 /* Pairs of binary relation representations that should represent
313  * the same binary relations.
314  */
315 struct {
316 	const char *map1;
317 	const char *map2;
318 } parse_map_equal_tests[] = {
319 	{ "{ [x,y]  : [([x/2]+y)/3] >= 1 }",
320 	  "{ [x, y] : 2y >= 6 - x }" },
321 	{ "{ [x,y] : x <= min(y, 2*y+3) }",
322 	  "{ [x,y] : x <= y, 2*y + 3 }" },
323 	{ "{ [x,y] : x >= min(y, 2*y+3) }",
324 	  "{ [x, y] : (y <= x and y >= -3) or (2y <= -3 + x and y <= -4) }" },
325 	{ "[n] -> { [c1] : c1>=0 and c1<=floord(n-4,3) }",
326 	  "[n] -> { [c1] : c1 >= 0 and 3c1 <= -4 + n }" },
327 	{ "{ [i,j] -> [i] : i < j; [i,j] -> [j] : j <= i }",
328 	  "{ [i,j] -> [min(i,j)] }" },
329 	{ "{ [i,j] : i != j }",
330 	  "{ [i,j] : i < j or i > j }" },
331 	{ "{ [i,j] : (i+1)*2 >= j }",
332 	  "{ [i, j] : j <= 2 + 2i }" },
333 	{ "{ [i] -> [i > 0 ? 4 : 5] }",
334 	  "{ [i] -> [5] : i <= 0; [i] -> [4] : i >= 1 }" },
335 	{ "[N=2,M] -> { [i=[(M+N)/4]] }",
336 	  "[N, M] -> { [i] : N = 2 and 4i <= 2 + M and 4i >= -1 + M }" },
337 	{ "{ [x] : x >= 0 }",
338 	  "{ [x] : x-0 >= 0 }" },
339 	{ "{ [i] : ((i > 10)) }",
340 	  "{ [i] : i >= 11 }" },
341 	{ "{ [i] -> [0] }",
342 	  "{ [i] -> [0 * i] }" },
343 	{ "{ [a] -> [b] : (not false) }",
344 	  "{ [a] -> [b] : true }" },
345 	{ "{ [i] : i/2 <= 5 }",
346 	  "{ [i] : i <= 10 }" },
347 	{ "{Sym=[n] [i] : i <= n }",
348 	  "[n] -> { [i] : i <= n }" },
349 	{ "{ [*] }",
350 	  "{ [a] }" },
351 	{ "{ [i] : 2*floor(i/2) = i }",
352 	  "{ [i] : exists a : i = 2 a }" },
353 	{ "{ [a] -> [b] : a = 5 implies b = 5 }",
354 	  "{ [a] -> [b] : a != 5 or b = 5 }" },
355 	{ "{ [a] -> [a - 1 : a > 0] }",
356 	  "{ [a] -> [a - 1] : a > 0 }" },
357 	{ "{ [a] -> [a - 1 : a > 0; a : a <= 0] }",
358 	  "{ [a] -> [a - 1] : a > 0; [a] -> [a] : a <= 0 }" },
359 	{ "{ [a] -> [(a) * 2 : a >= 0; 0 : a < 0] }",
360 	  "{ [a] -> [2a] : a >= 0; [a] -> [0] : a < 0 }" },
361 	{ "{ [a] -> [(a * 2) : a >= 0; 0 : a < 0] }",
362 	  "{ [a] -> [2a] : a >= 0; [a] -> [0] : a < 0 }" },
363 	{ "{ [a] -> [(a * 2 : a >= 0); 0 : a < 0] }",
364 	  "{ [a] -> [2a] : a >= 0; [a] -> [0] : a < 0 }" },
365 	{ "{ [a] -> [(a * 2 : a >= 0; 0 : a < 0)] }",
366 	  "{ [a] -> [2a] : a >= 0; [a] -> [0] : a < 0 }" },
367 	{ "{ [a,b] -> [i,j] : a,b << i,j }",
368 	  "{ [a,b] -> [i,j] : a < i or (a = i and b < j) }" },
369 	{ "{ [a,b] -> [i,j] : a,b <<= i,j }",
370 	  "{ [a,b] -> [i,j] : a < i or (a = i and b <= j) }" },
371 	{ "{ [a,b] -> [i,j] : a,b >> i,j }",
372 	  "{ [a,b] -> [i,j] : a > i or (a = i and b > j) }" },
373 	{ "{ [a,b] -> [i,j] : a,b >>= i,j }",
374 	  "{ [a,b] -> [i,j] : a > i or (a = i and b >= j) }" },
375 	{ "{ [n] -> [i] : exists (a, b, c: 8b <= i - 32a and "
376 			    "8b >= -7 + i - 32 a and b >= 0 and b <= 3 and "
377 			    "8c < n - 32a and i < n and c >= 0 and "
378 			    "c <= 3 and c >= -4a) }",
379 	  "{ [n] -> [i] : 0 <= i < n }" },
380 	{ "{ [x] -> [] : exists (a, b: 0 <= a <= 1 and 0 <= b <= 3 and "
381 			    "2b <= x - 8a and 2b >= -1 + x - 8a) }",
382 	  "{ [x] -> [] : 0 <= x <= 15 }" },
383 	{ "{ [x] -> [x] : }",
384 	  "{ [x] -> [x] }" },
385 	{ "{ [x=4:5] -> [x + 1] }",
386 	  "{ [x] -> [x + 1] : 4 <= x <= 5 }" },
387 	{ "{ [x=4:5] -> [x + 1 : x + 1] }",
388 	  "{ [x=4:5] -> [x + 1] }" },
389 	{ "{ [x] -> [x - 1 : x + 1] }",
390 	  "{ [x] -> [y] : x - 1 <= y <= x + 1 }" },
391 	{ "{ [x=4:] -> [x + 1] }",
392 	  "{ [x] -> [x + 1] : 4 <= x }" },
393 	{ "{ [x=:5] -> [x + 1] }",
394 	  "{ [x] -> [x + 1] : x <= 5 }" },
395 	{ "{ [x=:] -> [x + 1] }",
396 	  "{ [x] -> [x + 1] }" },
397 	{ "{ [:] -> [:] }",
398 	  "{ [x] -> [y] }" },
399 	{ "{ [x, x//4] }",
400 	  "{ [x, floor(x/4)] }" },
401 	{ "{ [10//4] }",
402 	  "{ [2] }" },
403 };
404 
test_parse(struct isl_ctx * ctx)405 int test_parse(struct isl_ctx *ctx)
406 {
407 	int i;
408 	isl_map *map, *map2;
409 	const char *str, *str2;
410 
411 	if (test_parse_multi_val(ctx, "{ A[B[2] -> C[5, 7]] }") < 0)
412 		return -1;
413 	if (test_parse_multi_val(ctx, "[n] -> { [2] }") < 0)
414 		return -1;
415 	if (test_parse_multi_val(ctx, "{ A[4, infty, NaN, -1/2, 2/3] }") < 0)
416 		return -1;
417 	if (test_parse_multi(ctx) < 0)
418 		return -1;
419 	if (test_parse_pma(ctx) < 0)
420 		return -1;
421 
422 	str = "{ [i] -> [-i] }";
423 	map = isl_map_read_from_str(ctx, str);
424 	assert(map);
425 	isl_map_free(map);
426 
427 	str = "{ A[i] -> L[([i/3])] }";
428 	map = isl_map_read_from_str(ctx, str);
429 	assert(map);
430 	isl_map_free(map);
431 
432 	test_parse_map(ctx, "{[[s] -> A[i]] -> [[s+1] -> A[i]]}");
433 	test_parse_map(ctx, "{ [p1, y1, y2] -> [2, y1, y2] : "
434 				"p1 = 1 && (y1 <= y2 || y2 = 0) }");
435 
436 	for (i = 0; i < ARRAY_SIZE(parse_map_equal_tests); ++i) {
437 		str = parse_map_equal_tests[i].map1;
438 		str2 = parse_map_equal_tests[i].map2;
439 		if (test_parse_map_equal(ctx, str, str2) < 0)
440 			return -1;
441 	}
442 
443 	str = "{[new,old] -> [new+1-2*[(new+1)/2],old+1-2*[(old+1)/2]]}";
444 	map = isl_map_read_from_str(ctx, str);
445 	str = "{ [new, old] -> [o0, o1] : "
446 	       "exists (e0 = [(-1 - new + o0)/2], e1 = [(-1 - old + o1)/2]: "
447 	       "2e0 = -1 - new + o0 and 2e1 = -1 - old + o1 and o0 >= 0 and "
448 	       "o0 <= 1 and o1 >= 0 and o1 <= 1) }";
449 	map2 = isl_map_read_from_str(ctx, str);
450 	assert(isl_map_is_equal(map, map2));
451 	isl_map_free(map);
452 	isl_map_free(map2);
453 
454 	str = "{[new,old] -> [new+1-2*[(new+1)/2],old+1-2*[(old+1)/2]]}";
455 	map = isl_map_read_from_str(ctx, str);
456 	str = "{[new,old] -> [(new+1)%2,(old+1)%2]}";
457 	map2 = isl_map_read_from_str(ctx, str);
458 	assert(isl_map_is_equal(map, map2));
459 	isl_map_free(map);
460 	isl_map_free(map2);
461 
462 	test_parse_pwqp(ctx, "{ [i] -> i + [ (i + [i/3])/2 ] }");
463 	test_parse_map(ctx, "{ S1[i] -> [([i/10]),i%10] : 0 <= i <= 45 }");
464 	test_parse_pwaff(ctx, "{ [i] -> [i + 1] : i > 0; [a] -> [a] : a < 0 }");
465 	test_parse_pwqp(ctx, "{ [x] -> ([(x)/2] * [(x)/3]) }");
466 	test_parse_pwaff(ctx, "{ [] -> [(100)] }");
467 
468 	return 0;
469 }
470 
test_read(isl_ctx * ctx)471 static int test_read(isl_ctx *ctx)
472 {
473 	char *filename;
474 	FILE *input;
475 	isl_basic_set *bset1, *bset2;
476 	const char *str = "{[y]: Exists ( alpha : 2alpha = y)}";
477 	int equal;
478 
479 	filename = get_filename(ctx, "set", "omega");
480 	assert(filename);
481 	input = fopen(filename, "r");
482 	assert(input);
483 
484 	bset1 = isl_basic_set_read_from_file(ctx, input);
485 	bset2 = isl_basic_set_read_from_str(ctx, str);
486 
487 	equal = isl_basic_set_is_equal(bset1, bset2);
488 
489 	isl_basic_set_free(bset1);
490 	isl_basic_set_free(bset2);
491 	free(filename);
492 
493 	fclose(input);
494 
495 	if (equal < 0)
496 		return -1;
497 	if (!equal)
498 		isl_die(ctx, isl_error_unknown,
499 			"read sets not equal", return -1);
500 
501 	return 0;
502 }
503 
test_bounded(isl_ctx * ctx)504 static int test_bounded(isl_ctx *ctx)
505 {
506 	isl_set *set;
507 	isl_bool bounded;
508 
509 	set = isl_set_read_from_str(ctx, "[n] -> {[i] : 0 <= i <= n }");
510 	bounded = isl_set_is_bounded(set);
511 	isl_set_free(set);
512 
513 	if (bounded < 0)
514 		return -1;
515 	if (!bounded)
516 		isl_die(ctx, isl_error_unknown,
517 			"set not considered bounded", return -1);
518 
519 	set = isl_set_read_from_str(ctx, "{[n, i] : 0 <= i <= n }");
520 	bounded = isl_set_is_bounded(set);
521 	assert(!bounded);
522 	isl_set_free(set);
523 
524 	if (bounded < 0)
525 		return -1;
526 	if (bounded)
527 		isl_die(ctx, isl_error_unknown,
528 			"set considered bounded", return -1);
529 
530 	set = isl_set_read_from_str(ctx, "[n] -> {[i] : i <= n }");
531 	bounded = isl_set_is_bounded(set);
532 	isl_set_free(set);
533 
534 	if (bounded < 0)
535 		return -1;
536 	if (bounded)
537 		isl_die(ctx, isl_error_unknown,
538 			"set considered bounded", return -1);
539 
540 	return 0;
541 }
542 
543 /* Construct the basic set { [i] : 5 <= i <= N } */
test_construction_1(isl_ctx * ctx)544 static int test_construction_1(isl_ctx *ctx)
545 {
546 	isl_space *space;
547 	isl_local_space *ls;
548 	isl_basic_set *bset;
549 	isl_constraint *c;
550 
551 	space = isl_space_set_alloc(ctx, 1, 1);
552 	bset = isl_basic_set_universe(isl_space_copy(space));
553 	ls = isl_local_space_from_space(space);
554 
555 	c = isl_constraint_alloc_inequality(isl_local_space_copy(ls));
556 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, -1);
557 	c = isl_constraint_set_coefficient_si(c, isl_dim_param, 0, 1);
558 	bset = isl_basic_set_add_constraint(bset, c);
559 
560 	c = isl_constraint_alloc_inequality(isl_local_space_copy(ls));
561 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, 1);
562 	c = isl_constraint_set_constant_si(c, -5);
563 	bset = isl_basic_set_add_constraint(bset, c);
564 
565 	isl_local_space_free(ls);
566 	isl_basic_set_free(bset);
567 
568 	return 0;
569 }
570 
571 /* Construct the basic set { [x] : -100 <= x <= 100 }
572  * using isl_basic_set_{lower,upper}_bound_val and
573  * check that it is equal the same basic set parsed from a string.
574  */
test_construction_2(isl_ctx * ctx)575 static int test_construction_2(isl_ctx *ctx)
576 {
577 	isl_bool equal;
578 	isl_val *v;
579 	isl_space *space;
580 	isl_basic_set *bset1, *bset2;
581 
582 	v = isl_val_int_from_si(ctx, 100);
583 	space = isl_space_set_alloc(ctx, 0, 1);
584 	bset1 = isl_basic_set_universe(space);
585 	bset1 = isl_basic_set_upper_bound_val(bset1, isl_dim_set, 0,
586 						isl_val_copy(v));
587 	bset1 = isl_basic_set_lower_bound_val(bset1, isl_dim_set, 0,
588 						isl_val_neg(v));
589 	bset2 = isl_basic_set_read_from_str(ctx, "{ [x] : -100 <= x <= 100 }");
590 	equal = isl_basic_set_is_equal(bset1, bset2);
591 	isl_basic_set_free(bset1);
592 	isl_basic_set_free(bset2);
593 
594 	if (equal < 0)
595 		return -1;
596 	if (!equal)
597 		isl_die(ctx, isl_error_unknown,
598 			"failed construction", return -1);
599 
600 	return 0;
601 }
602 
603 /* Basic tests for constructing basic sets.
604  */
test_construction(isl_ctx * ctx)605 static int test_construction(isl_ctx *ctx)
606 {
607 	if (test_construction_1(ctx) < 0)
608 		return -1;
609 	if (test_construction_2(ctx) < 0)
610 		return -1;
611 	return 0;
612 }
613 
test_dim(isl_ctx * ctx)614 static int test_dim(isl_ctx *ctx)
615 {
616 	const char *str;
617 	isl_map *map1, *map2;
618 	int equal;
619 
620 	map1 = isl_map_read_from_str(ctx,
621 	    "[n] -> { [i] -> [j] : exists (a = [i/10] : i - 10a <= n ) }");
622 	map1 = isl_map_add_dims(map1, isl_dim_in, 1);
623 	map2 = isl_map_read_from_str(ctx,
624 	    "[n] -> { [i,k] -> [j] : exists (a = [i/10] : i - 10a <= n ) }");
625 	equal = isl_map_is_equal(map1, map2);
626 	isl_map_free(map2);
627 
628 	map1 = isl_map_project_out(map1, isl_dim_in, 0, 1);
629 	map2 = isl_map_read_from_str(ctx, "[n] -> { [i] -> [j] : n >= 0 }");
630 	if (equal >= 0 && equal)
631 		equal = isl_map_is_equal(map1, map2);
632 
633 	isl_map_free(map1);
634 	isl_map_free(map2);
635 
636 	if (equal < 0)
637 		return -1;
638 	if (!equal)
639 		isl_die(ctx, isl_error_unknown,
640 			"unexpected result", return -1);
641 
642 	str = "[n] -> { [i] -> [] : exists a : 0 <= i <= n and i = 2 a }";
643 	map1 = isl_map_read_from_str(ctx, str);
644 	str = "{ [i] -> [j] : exists a : 0 <= i <= j and i = 2 a }";
645 	map2 = isl_map_read_from_str(ctx, str);
646 	map1 = isl_map_move_dims(map1, isl_dim_out, 0, isl_dim_param, 0, 1);
647 	equal = isl_map_is_equal(map1, map2);
648 	isl_map_free(map1);
649 	isl_map_free(map2);
650 
651 	if (equal < 0)
652 		return -1;
653 	if (!equal)
654 		isl_die(ctx, isl_error_unknown,
655 			"unexpected result", return -1);
656 
657 	return 0;
658 }
659 
660 #undef BASE
661 #define BASE	multi_val
662 #include "isl_test_plain_equal_templ.c"
663 
664 #undef BASE
665 #define BASE	multi_aff
666 #include "isl_test_plain_equal_templ.c"
667 
668 /* Check that "val" is equal to the value described by "str".
669  * If "str" is "NaN", then check for a NaN value explicitly.
670  */
val_check_equal(__isl_keep isl_val * val,const char * str)671 static isl_stat val_check_equal(__isl_keep isl_val *val, const char *str)
672 {
673 	isl_bool ok, is_nan;
674 	isl_ctx *ctx;
675 	isl_val *res;
676 
677 	if (!val)
678 		return isl_stat_error;
679 
680 	ctx = isl_val_get_ctx(val);
681 	res = isl_val_read_from_str(ctx, str);
682 	is_nan = isl_val_is_nan(res);
683 	if (is_nan < 0)
684 		ok = isl_bool_error;
685 	else if (is_nan)
686 		ok = isl_val_is_nan(val);
687 	else
688 		ok = isl_val_eq(val, res);
689 	isl_val_free(res);
690 	if (ok < 0)
691 		return isl_stat_error;
692 	if (!ok)
693 		isl_die(ctx, isl_error_unknown,
694 			"unexpected result", return isl_stat_error);
695 	return isl_stat_ok;
696 }
697 
698 struct {
699 	__isl_give isl_val *(*op)(__isl_take isl_val *v);
700 	const char *arg;
701 	const char *res;
702 } val_un_tests[] = {
703 	{ &isl_val_neg, "0", "0" },
704 	{ &isl_val_abs, "0", "0" },
705 	{ &isl_val_pow2, "0", "1" },
706 	{ &isl_val_floor, "0", "0" },
707 	{ &isl_val_ceil, "0", "0" },
708 	{ &isl_val_neg, "1", "-1" },
709 	{ &isl_val_neg, "-1", "1" },
710 	{ &isl_val_neg, "1/2", "-1/2" },
711 	{ &isl_val_neg, "-1/2", "1/2" },
712 	{ &isl_val_neg, "infty", "-infty" },
713 	{ &isl_val_neg, "-infty", "infty" },
714 	{ &isl_val_neg, "NaN", "NaN" },
715 	{ &isl_val_abs, "1", "1" },
716 	{ &isl_val_abs, "-1", "1" },
717 	{ &isl_val_abs, "1/2", "1/2" },
718 	{ &isl_val_abs, "-1/2", "1/2" },
719 	{ &isl_val_abs, "infty", "infty" },
720 	{ &isl_val_abs, "-infty", "infty" },
721 	{ &isl_val_abs, "NaN", "NaN" },
722 	{ &isl_val_floor, "1", "1" },
723 	{ &isl_val_floor, "-1", "-1" },
724 	{ &isl_val_floor, "1/2", "0" },
725 	{ &isl_val_floor, "-1/2", "-1" },
726 	{ &isl_val_floor, "infty", "infty" },
727 	{ &isl_val_floor, "-infty", "-infty" },
728 	{ &isl_val_floor, "NaN", "NaN" },
729 	{ &isl_val_ceil, "1", "1" },
730 	{ &isl_val_ceil, "-1", "-1" },
731 	{ &isl_val_ceil, "1/2", "1" },
732 	{ &isl_val_ceil, "-1/2", "0" },
733 	{ &isl_val_ceil, "infty", "infty" },
734 	{ &isl_val_ceil, "-infty", "-infty" },
735 	{ &isl_val_ceil, "NaN", "NaN" },
736 	{ &isl_val_pow2, "-3", "1/8" },
737 	{ &isl_val_pow2, "-1", "1/2" },
738 	{ &isl_val_pow2, "1", "2" },
739 	{ &isl_val_pow2, "2", "4" },
740 	{ &isl_val_pow2, "3", "8" },
741 	{ &isl_val_inv, "1", "1" },
742 	{ &isl_val_inv, "2", "1/2" },
743 	{ &isl_val_inv, "1/2", "2" },
744 	{ &isl_val_inv, "-2", "-1/2" },
745 	{ &isl_val_inv, "-1/2", "-2" },
746 	{ &isl_val_inv, "0", "NaN" },
747 	{ &isl_val_inv, "NaN", "NaN" },
748 	{ &isl_val_inv, "infty", "0" },
749 	{ &isl_val_inv, "-infty", "0" },
750 };
751 
752 /* Perform some basic tests of unary operations on isl_val objects.
753  */
test_un_val(isl_ctx * ctx)754 static int test_un_val(isl_ctx *ctx)
755 {
756 	int i;
757 	isl_val *v;
758 	__isl_give isl_val *(*fn)(__isl_take isl_val *v);
759 
760 	for (i = 0; i < ARRAY_SIZE(val_un_tests); ++i) {
761 		isl_stat r;
762 
763 		v = isl_val_read_from_str(ctx, val_un_tests[i].arg);
764 		fn = val_un_tests[i].op;
765 		v = fn(v);
766 		r = val_check_equal(v, val_un_tests[i].res);
767 		isl_val_free(v);
768 		if (r < 0)
769 			return -1;
770 	}
771 
772 	return 0;
773 }
774 
775 struct {
776 	__isl_give isl_val *(*fn)(__isl_take isl_val *v1,
777 				__isl_take isl_val *v2);
778 } val_bin_op[] = {
779 	['+'] = { &isl_val_add },
780 	['-'] = { &isl_val_sub },
781 	['*'] = { &isl_val_mul },
782 	['/'] = { &isl_val_div },
783 	['g'] = { &isl_val_gcd },
784 	['m'] = { &isl_val_min },
785 	['M'] = { &isl_val_max },
786 };
787 
788 struct {
789 	const char *arg1;
790 	unsigned char op;
791 	const char *arg2;
792 	const char *res;
793 } val_bin_tests[] = {
794 	{ "0", '+', "0", "0" },
795 	{ "1", '+', "0", "1" },
796 	{ "1", '+', "1", "2" },
797 	{ "1", '-', "1", "0" },
798 	{ "1", '*', "1", "1" },
799 	{ "1", '/', "1", "1" },
800 	{ "2", '*', "3", "6" },
801 	{ "2", '*', "1/2", "1" },
802 	{ "2", '*', "1/3", "2/3" },
803 	{ "2/3", '*', "3/5", "2/5" },
804 	{ "2/3", '*', "7/5", "14/15" },
805 	{ "2", '/', "1/2", "4" },
806 	{ "-2", '/', "-1/2", "4" },
807 	{ "-2", '/', "1/2", "-4" },
808 	{ "2", '/', "-1/2", "-4" },
809 	{ "2", '/', "2", "1" },
810 	{ "2", '/', "3", "2/3" },
811 	{ "2/3", '/', "5/3", "2/5" },
812 	{ "2/3", '/', "5/7", "14/15" },
813 	{ "0", '/', "0", "NaN" },
814 	{ "42", '/', "0", "NaN" },
815 	{ "-42", '/', "0", "NaN" },
816 	{ "infty", '/', "0", "NaN" },
817 	{ "-infty", '/', "0", "NaN" },
818 	{ "NaN", '/', "0", "NaN" },
819 	{ "0", '/', "NaN", "NaN" },
820 	{ "42", '/', "NaN", "NaN" },
821 	{ "-42", '/', "NaN", "NaN" },
822 	{ "infty", '/', "NaN", "NaN" },
823 	{ "-infty", '/', "NaN", "NaN" },
824 	{ "NaN", '/', "NaN", "NaN" },
825 	{ "0", '/', "infty", "0" },
826 	{ "42", '/', "infty", "0" },
827 	{ "-42", '/', "infty", "0" },
828 	{ "infty", '/', "infty", "NaN" },
829 	{ "-infty", '/', "infty", "NaN" },
830 	{ "NaN", '/', "infty", "NaN" },
831 	{ "0", '/', "-infty", "0" },
832 	{ "42", '/', "-infty", "0" },
833 	{ "-42", '/', "-infty", "0" },
834 	{ "infty", '/', "-infty", "NaN" },
835 	{ "-infty", '/', "-infty", "NaN" },
836 	{ "NaN", '/', "-infty", "NaN" },
837 	{ "1", '-', "1/3", "2/3" },
838 	{ "1/3", '+', "1/2", "5/6" },
839 	{ "1/2", '+', "1/2", "1" },
840 	{ "3/4", '-', "1/4", "1/2" },
841 	{ "1/2", '-', "1/3", "1/6" },
842 	{ "infty", '+', "42", "infty" },
843 	{ "infty", '+', "infty", "infty" },
844 	{ "42", '+', "infty", "infty" },
845 	{ "infty", '-', "infty", "NaN" },
846 	{ "infty", '*', "infty", "infty" },
847 	{ "infty", '*', "-infty", "-infty" },
848 	{ "-infty", '*', "infty", "-infty" },
849 	{ "-infty", '*', "-infty", "infty" },
850 	{ "0", '*', "infty", "NaN" },
851 	{ "1", '*', "infty", "infty" },
852 	{ "infty", '*', "0", "NaN" },
853 	{ "infty", '*', "42", "infty" },
854 	{ "42", '-', "infty", "-infty" },
855 	{ "infty", '+', "-infty", "NaN" },
856 	{ "4", 'g', "6", "2" },
857 	{ "5", 'g', "6", "1" },
858 	{ "42", 'm', "3", "3" },
859 	{ "42", 'M', "3", "42" },
860 	{ "3", 'm', "42", "3" },
861 	{ "3", 'M', "42", "42" },
862 	{ "42", 'm', "infty", "42" },
863 	{ "42", 'M', "infty", "infty" },
864 	{ "42", 'm', "-infty", "-infty" },
865 	{ "42", 'M', "-infty", "42" },
866 	{ "42", 'm', "NaN", "NaN" },
867 	{ "42", 'M', "NaN", "NaN" },
868 	{ "infty", 'm', "-infty", "-infty" },
869 	{ "infty", 'M', "-infty", "infty" },
870 };
871 
872 /* Perform some basic tests of binary operations on isl_val objects.
873  */
test_bin_val(isl_ctx * ctx)874 static int test_bin_val(isl_ctx *ctx)
875 {
876 	int i;
877 	isl_val *v1, *v2, *res;
878 	__isl_give isl_val *(*fn)(__isl_take isl_val *v1,
879 				__isl_take isl_val *v2);
880 	int ok;
881 
882 	for (i = 0; i < ARRAY_SIZE(val_bin_tests); ++i) {
883 		v1 = isl_val_read_from_str(ctx, val_bin_tests[i].arg1);
884 		v2 = isl_val_read_from_str(ctx, val_bin_tests[i].arg2);
885 		res = isl_val_read_from_str(ctx, val_bin_tests[i].res);
886 		fn = val_bin_op[val_bin_tests[i].op].fn;
887 		v1 = fn(v1, v2);
888 		if (isl_val_is_nan(res))
889 			ok = isl_val_is_nan(v1);
890 		else
891 			ok = isl_val_eq(v1, res);
892 		isl_val_free(v1);
893 		isl_val_free(res);
894 		if (ok < 0)
895 			return -1;
896 		if (!ok)
897 			isl_die(ctx, isl_error_unknown,
898 				"unexpected result", return -1);
899 	}
900 
901 	return 0;
902 }
903 
904 /* Perform some basic tests on isl_val objects.
905  */
test_val(isl_ctx * ctx)906 static int test_val(isl_ctx *ctx)
907 {
908 	if (test_un_val(ctx) < 0)
909 		return -1;
910 	if (test_bin_val(ctx) < 0)
911 		return -1;
912 	return 0;
913 }
914 
915 /* Sets described using existentially quantified variables that
916  * can also be described without.
917  */
918 static const char *elimination_tests[] = {
919 	"{ [i,j] : 2 * [i/2] + 3 * [j/4] <= 10 and 2 i = j }",
920 	"{ [m, w] : exists a : w - 2m - 5 <= 3a <= m - 2w }",
921 	"{ [m, w] : exists a : w >= 0 and a < m and -1 + w <= a <= 2m - w }",
922 };
923 
924 /* Check that redundant existentially quantified variables are
925  * getting removed.
926  */
test_elimination(isl_ctx * ctx)927 static int test_elimination(isl_ctx *ctx)
928 {
929 	int i;
930 	isl_size n;
931 	isl_basic_set *bset;
932 
933 	for (i = 0; i < ARRAY_SIZE(elimination_tests); ++i) {
934 		bset = isl_basic_set_read_from_str(ctx, elimination_tests[i]);
935 		n = isl_basic_set_dim(bset, isl_dim_div);
936 		isl_basic_set_free(bset);
937 		if (n < 0)
938 			return -1;
939 		if (n != 0)
940 			isl_die(ctx, isl_error_unknown,
941 				"expecting no existentials", return -1);
942 	}
943 
944 	return 0;
945 }
946 
test_div(isl_ctx * ctx)947 static int test_div(isl_ctx *ctx)
948 {
949 	const char *str;
950 	int empty;
951 	isl_space *space;
952 	isl_set *set;
953 	isl_local_space *ls;
954 	struct isl_basic_set *bset;
955 	struct isl_constraint *c;
956 
957 	/* test 1 */
958 	space = isl_space_set_alloc(ctx, 0, 3);
959 	bset = isl_basic_set_universe(isl_space_copy(space));
960 	ls = isl_local_space_from_space(space);
961 
962 	c = isl_constraint_alloc_equality(isl_local_space_copy(ls));
963 	c = isl_constraint_set_constant_si(c, -1);
964 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, 1);
965 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 1, 3);
966 	bset = isl_basic_set_add_constraint(bset, c);
967 
968 	c = isl_constraint_alloc_equality(isl_local_space_copy(ls));
969 	c = isl_constraint_set_constant_si(c, 1);
970 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, -1);
971 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 2, 3);
972 	bset = isl_basic_set_add_constraint(bset, c);
973 
974 	bset = isl_basic_set_project_out(bset, isl_dim_set, 1, 2);
975 
976 	assert(bset && bset->n_div == 1);
977 	isl_local_space_free(ls);
978 	isl_basic_set_free(bset);
979 
980 	/* test 2 */
981 	space = isl_space_set_alloc(ctx, 0, 3);
982 	bset = isl_basic_set_universe(isl_space_copy(space));
983 	ls = isl_local_space_from_space(space);
984 
985 	c = isl_constraint_alloc_equality(isl_local_space_copy(ls));
986 	c = isl_constraint_set_constant_si(c, 1);
987 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, -1);
988 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 1, 3);
989 	bset = isl_basic_set_add_constraint(bset, c);
990 
991 	c = isl_constraint_alloc_equality(isl_local_space_copy(ls));
992 	c = isl_constraint_set_constant_si(c, -1);
993 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, 1);
994 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 2, 3);
995 	bset = isl_basic_set_add_constraint(bset, c);
996 
997 	bset = isl_basic_set_project_out(bset, isl_dim_set, 1, 2);
998 
999 	assert(bset && bset->n_div == 1);
1000 	isl_local_space_free(ls);
1001 	isl_basic_set_free(bset);
1002 
1003 	/* test 3 */
1004 	space = isl_space_set_alloc(ctx, 0, 3);
1005 	bset = isl_basic_set_universe(isl_space_copy(space));
1006 	ls = isl_local_space_from_space(space);
1007 
1008 	c = isl_constraint_alloc_equality(isl_local_space_copy(ls));
1009 	c = isl_constraint_set_constant_si(c, 1);
1010 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, -1);
1011 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 1, 3);
1012 	bset = isl_basic_set_add_constraint(bset, c);
1013 
1014 	c = isl_constraint_alloc_equality(isl_local_space_copy(ls));
1015 	c = isl_constraint_set_constant_si(c, -3);
1016 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, 1);
1017 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 2, 4);
1018 	bset = isl_basic_set_add_constraint(bset, c);
1019 
1020 	bset = isl_basic_set_project_out(bset, isl_dim_set, 1, 2);
1021 
1022 	assert(bset && bset->n_div == 1);
1023 	isl_local_space_free(ls);
1024 	isl_basic_set_free(bset);
1025 
1026 	/* test 4 */
1027 	space = isl_space_set_alloc(ctx, 0, 3);
1028 	bset = isl_basic_set_universe(isl_space_copy(space));
1029 	ls = isl_local_space_from_space(space);
1030 
1031 	c = isl_constraint_alloc_equality(isl_local_space_copy(ls));
1032 	c = isl_constraint_set_constant_si(c, 2);
1033 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, -1);
1034 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 1, 3);
1035 	bset = isl_basic_set_add_constraint(bset, c);
1036 
1037 	c = isl_constraint_alloc_equality(isl_local_space_copy(ls));
1038 	c = isl_constraint_set_constant_si(c, -1);
1039 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, 1);
1040 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 2, 6);
1041 	bset = isl_basic_set_add_constraint(bset, c);
1042 
1043 	bset = isl_basic_set_project_out(bset, isl_dim_set, 1, 2);
1044 
1045 	assert(isl_basic_set_is_empty(bset));
1046 	isl_local_space_free(ls);
1047 	isl_basic_set_free(bset);
1048 
1049 	/* test 5 */
1050 	space = isl_space_set_alloc(ctx, 0, 3);
1051 	bset = isl_basic_set_universe(isl_space_copy(space));
1052 	ls = isl_local_space_from_space(space);
1053 
1054 	c = isl_constraint_alloc_equality(isl_local_space_copy(ls));
1055 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, -1);
1056 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 2, 3);
1057 	bset = isl_basic_set_add_constraint(bset, c);
1058 
1059 	c = isl_constraint_alloc_equality(isl_local_space_copy(ls));
1060 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, 1);
1061 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 1, -3);
1062 	bset = isl_basic_set_add_constraint(bset, c);
1063 
1064 	bset = isl_basic_set_project_out(bset, isl_dim_set, 2, 1);
1065 
1066 	assert(bset && bset->n_div == 0);
1067 	isl_basic_set_free(bset);
1068 	isl_local_space_free(ls);
1069 
1070 	/* test 6 */
1071 	space = isl_space_set_alloc(ctx, 0, 3);
1072 	bset = isl_basic_set_universe(isl_space_copy(space));
1073 	ls = isl_local_space_from_space(space);
1074 
1075 	c = isl_constraint_alloc_equality(isl_local_space_copy(ls));
1076 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, -1);
1077 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 2, 6);
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_coefficient_si(c, isl_dim_set, 0, 1);
1082 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 1, -3);
1083 	bset = isl_basic_set_add_constraint(bset, c);
1084 
1085 	bset = isl_basic_set_project_out(bset, isl_dim_set, 2, 1);
1086 
1087 	assert(bset && bset->n_div == 1);
1088 	isl_basic_set_free(bset);
1089 	isl_local_space_free(ls);
1090 
1091 	/* test 7 */
1092 	/* This test is a bit tricky.  We set up an equality
1093 	 *		a + 3b + 3c = 6 e0
1094 	 * Normalization of divs creates _two_ divs
1095 	 *		a = 3 e0
1096 	 *		c - b - e0 = 2 e1
1097 	 * Afterwards e0 is removed again because it has coefficient -1
1098 	 * and we end up with the original equality and div again.
1099 	 * Perhaps we can avoid the introduction of this temporary div.
1100 	 */
1101 	space = isl_space_set_alloc(ctx, 0, 4);
1102 	bset = isl_basic_set_universe(isl_space_copy(space));
1103 	ls = isl_local_space_from_space(space);
1104 
1105 	c = isl_constraint_alloc_equality(isl_local_space_copy(ls));
1106 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, -1);
1107 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 1, -3);
1108 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 2, -3);
1109 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 3, 6);
1110 	bset = isl_basic_set_add_constraint(bset, c);
1111 
1112 	bset = isl_basic_set_project_out(bset, isl_dim_set, 3, 1);
1113 
1114 	/* Test disabled for now */
1115 	/*
1116 	assert(bset && bset->n_div == 1);
1117 	*/
1118 	isl_local_space_free(ls);
1119 	isl_basic_set_free(bset);
1120 
1121 	/* test 8 */
1122 	space = isl_space_set_alloc(ctx, 0, 5);
1123 	bset = isl_basic_set_universe(isl_space_copy(space));
1124 	ls = isl_local_space_from_space(space);
1125 
1126 	c = isl_constraint_alloc_equality(isl_local_space_copy(ls));
1127 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, -1);
1128 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 1, -3);
1129 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 3, -3);
1130 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 4, 6);
1131 	bset = isl_basic_set_add_constraint(bset, c);
1132 
1133 	c = isl_constraint_alloc_equality(isl_local_space_copy(ls));
1134 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, -1);
1135 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 2, 1);
1136 	c = isl_constraint_set_constant_si(c, 1);
1137 	bset = isl_basic_set_add_constraint(bset, c);
1138 
1139 	bset = isl_basic_set_project_out(bset, isl_dim_set, 4, 1);
1140 
1141 	/* Test disabled for now */
1142 	/*
1143 	assert(bset && bset->n_div == 1);
1144 	*/
1145 	isl_local_space_free(ls);
1146 	isl_basic_set_free(bset);
1147 
1148 	/* test 9 */
1149 	space = isl_space_set_alloc(ctx, 0, 4);
1150 	bset = isl_basic_set_universe(isl_space_copy(space));
1151 	ls = isl_local_space_from_space(space);
1152 
1153 	c = isl_constraint_alloc_equality(isl_local_space_copy(ls));
1154 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, 1);
1155 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 1, -1);
1156 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 2, -2);
1157 	bset = isl_basic_set_add_constraint(bset, c);
1158 
1159 	c = isl_constraint_alloc_equality(isl_local_space_copy(ls));
1160 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, -1);
1161 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 3, 3);
1162 	c = isl_constraint_set_constant_si(c, 2);
1163 	bset = isl_basic_set_add_constraint(bset, c);
1164 
1165 	bset = isl_basic_set_project_out(bset, isl_dim_set, 2, 2);
1166 
1167 	bset = isl_basic_set_fix_si(bset, isl_dim_set, 0, 2);
1168 
1169 	assert(!isl_basic_set_is_empty(bset));
1170 
1171 	isl_local_space_free(ls);
1172 	isl_basic_set_free(bset);
1173 
1174 	/* test 10 */
1175 	space = isl_space_set_alloc(ctx, 0, 3);
1176 	bset = isl_basic_set_universe(isl_space_copy(space));
1177 	ls = isl_local_space_from_space(space);
1178 
1179 	c = isl_constraint_alloc_equality(isl_local_space_copy(ls));
1180 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, 1);
1181 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 2, -2);
1182 	bset = isl_basic_set_add_constraint(bset, c);
1183 
1184 	bset = isl_basic_set_project_out(bset, isl_dim_set, 2, 1);
1185 
1186 	bset = isl_basic_set_fix_si(bset, isl_dim_set, 0, 2);
1187 
1188 	isl_local_space_free(ls);
1189 	isl_basic_set_free(bset);
1190 
1191 	str = "{ [i] : exists (e0, e1: 3e1 >= 1 + 2e0 and "
1192 	    "8e1 <= -1 + 5i - 5e0 and 2e1 >= 1 + 2i - 5e0) }";
1193 	set = isl_set_read_from_str(ctx, str);
1194 	set = isl_set_compute_divs(set);
1195 	isl_set_free(set);
1196 	if (!set)
1197 		return -1;
1198 
1199 	if (test_elimination(ctx) < 0)
1200 		return -1;
1201 
1202 	str = "{ [i,j,k] : 3 + i + 2j >= 0 and 2 * [(i+2j)/4] <= k }";
1203 	set = isl_set_read_from_str(ctx, str);
1204 	set = isl_set_remove_divs_involving_dims(set, isl_dim_set, 0, 2);
1205 	set = isl_set_fix_si(set, isl_dim_set, 2, -3);
1206 	empty = isl_set_is_empty(set);
1207 	isl_set_free(set);
1208 	if (empty < 0)
1209 		return -1;
1210 	if (!empty)
1211 		isl_die(ctx, isl_error_unknown,
1212 			"result not as accurate as expected", return -1);
1213 
1214 	return 0;
1215 }
1216 
test_application_case(struct isl_ctx * ctx,const char * name)1217 void test_application_case(struct isl_ctx *ctx, const char *name)
1218 {
1219 	char *filename;
1220 	FILE *input;
1221 	struct isl_basic_set *bset1, *bset2;
1222 	struct isl_basic_map *bmap;
1223 
1224 	filename = get_filename(ctx, name, "omega");
1225 	assert(filename);
1226 	input = fopen(filename, "r");
1227 	assert(input);
1228 
1229 	bset1 = isl_basic_set_read_from_file(ctx, input);
1230 	bmap = isl_basic_map_read_from_file(ctx, input);
1231 
1232 	bset1 = isl_basic_set_apply(bset1, bmap);
1233 
1234 	bset2 = isl_basic_set_read_from_file(ctx, input);
1235 
1236 	assert(isl_basic_set_is_equal(bset1, bset2) == 1);
1237 
1238 	isl_basic_set_free(bset1);
1239 	isl_basic_set_free(bset2);
1240 	free(filename);
1241 
1242 	fclose(input);
1243 }
1244 
test_application(isl_ctx * ctx)1245 static int test_application(isl_ctx *ctx)
1246 {
1247 	test_application_case(ctx, "application");
1248 	test_application_case(ctx, "application2");
1249 
1250 	return 0;
1251 }
1252 
test_affine_hull_case(struct isl_ctx * ctx,const char * name)1253 void test_affine_hull_case(struct isl_ctx *ctx, const char *name)
1254 {
1255 	char *filename;
1256 	FILE *input;
1257 	struct isl_basic_set *bset1, *bset2;
1258 
1259 	filename = get_filename(ctx, name, "polylib");
1260 	assert(filename);
1261 	input = fopen(filename, "r");
1262 	assert(input);
1263 
1264 	bset1 = isl_basic_set_read_from_file(ctx, input);
1265 	bset2 = isl_basic_set_read_from_file(ctx, input);
1266 
1267 	bset1 = isl_basic_set_affine_hull(bset1);
1268 
1269 	assert(isl_basic_set_is_equal(bset1, bset2) == 1);
1270 
1271 	isl_basic_set_free(bset1);
1272 	isl_basic_set_free(bset2);
1273 	free(filename);
1274 
1275 	fclose(input);
1276 }
1277 
1278 /* Pairs of sets and the corresponding expected results of
1279  * isl_basic_set_recession_cone.
1280  */
1281 struct {
1282 	const char *set;
1283 	const char *cone;
1284 } recession_cone_tests[] = {
1285 	{ "{ [i] : 0 <= i <= 10 }", "{ [0] }" },
1286 	{ "{ [i] : 0 <= i }", "{ [i] : 0 <= i }" },
1287 	{ "{ [i] : i <= 10 }", "{ [i] : i <= 0 }" },
1288 	{ "{ [i] : false }", "{ [i] : false }" },
1289 };
1290 
1291 /* Perform some basic isl_basic_set_recession_cone tests.
1292  */
test_recession_cone(struct isl_ctx * ctx)1293 static int test_recession_cone(struct isl_ctx *ctx)
1294 {
1295 	int i;
1296 
1297 	for (i = 0; i < ARRAY_SIZE(recession_cone_tests); ++i) {
1298 		const char *str;
1299 		isl_basic_set *bset;
1300 		isl_basic_set *cone, *expected;
1301 		isl_bool equal;
1302 
1303 		str = recession_cone_tests[i].set;
1304 		bset = isl_basic_set_read_from_str(ctx, str);
1305 		str = recession_cone_tests[i].cone;
1306 		expected = isl_basic_set_read_from_str(ctx, str);
1307 		cone = isl_basic_set_recession_cone(bset);
1308 		equal = isl_basic_set_is_equal(cone, expected);
1309 		isl_basic_set_free(cone);
1310 		isl_basic_set_free(expected);
1311 		if (equal < 0)
1312 			return -1;
1313 		if (!equal)
1314 			isl_die(ctx, isl_error_unknown, "unexpected cone",
1315 				return -1);
1316 	}
1317 
1318 	return 0;
1319 }
1320 
test_affine_hull(struct isl_ctx * ctx)1321 int test_affine_hull(struct isl_ctx *ctx)
1322 {
1323 	const char *str;
1324 	isl_set *set;
1325 	isl_basic_set *bset, *bset2;
1326 	isl_size n;
1327 	isl_bool subset;
1328 
1329 	test_affine_hull_case(ctx, "affine2");
1330 	test_affine_hull_case(ctx, "affine");
1331 	test_affine_hull_case(ctx, "affine3");
1332 
1333 	str = "[m] -> { [i0] : exists (e0, e1: e1 <= 1 + i0 and "
1334 			"m >= 3 and 4i0 <= 2 + m and e1 >= i0 and "
1335 			"e1 >= 0 and e1 <= 2 and e1 >= 1 + 2e0 and "
1336 			"2e1 <= 1 + m + 4e0 and 2e1 >= 2 - m + 4i0 - 4e0) }";
1337 	set = isl_set_read_from_str(ctx, str);
1338 	bset = isl_set_affine_hull(set);
1339 	n = isl_basic_set_dim(bset, isl_dim_div);
1340 	isl_basic_set_free(bset);
1341 	if (n < 0)
1342 		return -1;
1343 	if (n != 0)
1344 		isl_die(ctx, isl_error_unknown, "not expecting any divs",
1345 			return -1);
1346 
1347 	/* Check that isl_map_affine_hull is not confused by
1348 	 * the reordering of divs in isl_map_align_divs.
1349 	 */
1350 	str = "{ [a, b, c, 0] : exists (e0 = [(b)/32], e1 = [(c)/32]: "
1351 				"32e0 = b and 32e1 = c); "
1352 		"[a, 0, c, 0] : exists (e0 = [(c)/32]: 32e0 = c) }";
1353 	set = isl_set_read_from_str(ctx, str);
1354 	bset = isl_set_affine_hull(set);
1355 	isl_basic_set_free(bset);
1356 	if (!bset)
1357 		return -1;
1358 
1359 	str = "{ [a] : exists e0, e1, e2: 32e1 = 31 + 31a + 31e0 and "
1360 			"32e2 = 31 + 31e0 }";
1361 	set = isl_set_read_from_str(ctx, str);
1362 	bset = isl_set_affine_hull(set);
1363 	str = "{ [a] : exists e : a = 32 e }";
1364 	bset2 = isl_basic_set_read_from_str(ctx, str);
1365 	subset = isl_basic_set_is_subset(bset, bset2);
1366 	isl_basic_set_free(bset);
1367 	isl_basic_set_free(bset2);
1368 	if (subset < 0)
1369 		return -1;
1370 	if (!subset)
1371 		isl_die(ctx, isl_error_unknown, "not as accurate as expected",
1372 			return -1);
1373 
1374 	return 0;
1375 }
1376 
1377 /* Test a special case of isl_set_plain_unshifted_simple_hull
1378  * where older versions of isl would include a redundant constraint
1379  * in the result.
1380  * Check that the result does not have any constraints.
1381  */
test_plain_unshifted_simple_hull_special(isl_ctx * ctx)1382 static isl_stat test_plain_unshifted_simple_hull_special(isl_ctx *ctx)
1383 {
1384 	const char *str;
1385 	isl_bool is_universe;
1386 	isl_set *set;
1387 	isl_basic_set *bset;
1388 
1389 	str = "{[x, y] : x = 0 or 2*((x+y)//2) <= y + 2 }";
1390 	set = isl_set_read_from_str(ctx, str);
1391 	bset = isl_set_plain_unshifted_simple_hull(set);
1392 	is_universe = isl_basic_set_plain_is_universe(bset);
1393 	isl_basic_set_free(bset);
1394 
1395 	if (is_universe < 0)
1396 		return isl_stat_error;
1397 	if (!is_universe)
1398 		isl_die(ctx, isl_error_unknown,
1399 			"hull should not have any constraints",
1400 			return isl_stat_error);
1401 
1402 	return isl_stat_ok;
1403 }
1404 
1405 /* Pairs of maps and the corresponding expected results of
1406  * isl_map_plain_unshifted_simple_hull.
1407  */
1408 struct {
1409 	const char *map;
1410 	const char *hull;
1411 } plain_unshifted_simple_hull_tests[] = {
1412 	{ "{ [i] -> [j] : i >= 1 and j >= 1 or i >= 2 and j <= 10 }",
1413 	  "{ [i] -> [j] : i >= 1 }" },
1414 	{ "{ [n] -> [i,j,k] : (i mod 3 = 2 and j mod 4 = 2) or "
1415 		"(j mod 4 = 2 and k mod 6 = n) }",
1416 	  "{ [n] -> [i,j,k] : j mod 4 = 2 }" },
1417 };
1418 
1419 /* Basic tests for isl_map_plain_unshifted_simple_hull.
1420  */
test_plain_unshifted_simple_hull(isl_ctx * ctx)1421 static int test_plain_unshifted_simple_hull(isl_ctx *ctx)
1422 {
1423 	int i;
1424 	isl_map *map;
1425 	isl_basic_map *hull, *expected;
1426 	isl_bool equal;
1427 
1428 	for (i = 0; i < ARRAY_SIZE(plain_unshifted_simple_hull_tests); ++i) {
1429 		const char *str;
1430 		str = plain_unshifted_simple_hull_tests[i].map;
1431 		map = isl_map_read_from_str(ctx, str);
1432 		str = plain_unshifted_simple_hull_tests[i].hull;
1433 		expected = isl_basic_map_read_from_str(ctx, str);
1434 		hull = isl_map_plain_unshifted_simple_hull(map);
1435 		equal = isl_basic_map_is_equal(hull, expected);
1436 		isl_basic_map_free(hull);
1437 		isl_basic_map_free(expected);
1438 		if (equal < 0)
1439 			return -1;
1440 		if (!equal)
1441 			isl_die(ctx, isl_error_unknown, "unexpected hull",
1442 				return -1);
1443 	}
1444 
1445 	return 0;
1446 }
1447 
1448 /* Pairs of sets and the corresponding expected results of
1449  * isl_set_unshifted_simple_hull.
1450  */
1451 struct {
1452 	const char *set;
1453 	const char *hull;
1454 } unshifted_simple_hull_tests[] = {
1455 	{ "{ [0,x,y] : x <= -1; [1,x,y] : x <= y <= -x; [2,x,y] : x <= 1 }",
1456 	  "{ [t,x,y] : 0 <= t <= 2 and x <= 1 }" },
1457 };
1458 
1459 /* Basic tests for isl_set_unshifted_simple_hull.
1460  */
test_unshifted_simple_hull(isl_ctx * ctx)1461 static int test_unshifted_simple_hull(isl_ctx *ctx)
1462 {
1463 	int i;
1464 	isl_set *set;
1465 	isl_basic_set *hull, *expected;
1466 	isl_bool equal;
1467 
1468 	for (i = 0; i < ARRAY_SIZE(unshifted_simple_hull_tests); ++i) {
1469 		const char *str;
1470 		str = unshifted_simple_hull_tests[i].set;
1471 		set = isl_set_read_from_str(ctx, str);
1472 		str = unshifted_simple_hull_tests[i].hull;
1473 		expected = isl_basic_set_read_from_str(ctx, str);
1474 		hull = isl_set_unshifted_simple_hull(set);
1475 		equal = isl_basic_set_is_equal(hull, expected);
1476 		isl_basic_set_free(hull);
1477 		isl_basic_set_free(expected);
1478 		if (equal < 0)
1479 			return -1;
1480 		if (!equal)
1481 			isl_die(ctx, isl_error_unknown, "unexpected hull",
1482 				return -1);
1483 	}
1484 
1485 	return 0;
1486 }
1487 
test_simple_hull(struct isl_ctx * ctx)1488 static int test_simple_hull(struct isl_ctx *ctx)
1489 {
1490 	const char *str;
1491 	isl_set *set;
1492 	isl_basic_set *bset;
1493 	isl_bool is_empty;
1494 
1495 	str = "{ [x, y] : 3y <= 2x and y >= -2 + 2x and 2y >= 2 - x;"
1496 		"[y, x] : 3y <= 2x and y >= -2 + 2x and 2y >= 2 - x }";
1497 	set = isl_set_read_from_str(ctx, str);
1498 	bset = isl_set_simple_hull(set);
1499 	is_empty = isl_basic_set_is_empty(bset);
1500 	isl_basic_set_free(bset);
1501 
1502 	if (is_empty == isl_bool_error)
1503 		return -1;
1504 
1505 	if (is_empty == isl_bool_false)
1506 		isl_die(ctx, isl_error_unknown, "Empty set should be detected",
1507 			return -1);
1508 
1509 	if (test_plain_unshifted_simple_hull_special(ctx) < 0)
1510 		return -1;
1511 	if (test_plain_unshifted_simple_hull(ctx) < 0)
1512 		return -1;
1513 	if (test_unshifted_simple_hull(ctx) < 0)
1514 		return -1;
1515 
1516 	return 0;
1517 }
1518 
1519 /* Inputs for isl_set_get_simple_fixed_box_hull tests.
1520  * "set" is the input set.
1521  * "offset" is the expected box offset.
1522  * "size" is the expected box size.
1523  */
1524 static struct {
1525 	const char *set;
1526 	const char *offset;
1527 	const char *size;
1528 } box_hull_tests[] = {
1529 	{ "{ S[x, y] : 0 <= x, y < 10 }", "{ S[0, 0] }", "{ S[10, 10] }" },
1530 	{ "[N] -> { S[x, y] : N <= x, y < N + 10 }",
1531 	  "[N] -> { S[N, N] }", "{ S[10, 10] }" },
1532 	{ "{ S[x, y] : 0 <= x + y, x - y < 10 }",
1533 	  "{ S[0, -4] }", "{ S[10, 9] }" },
1534 	{ "{ [i=0:10] : exists (e0, e1: 3e1 >= 1 + 2e0 and "
1535 	    "8e1 <= -1 + 5i - 5e0 and 2e1 >= 1 + 2i - 5e0) }",
1536 	  "{ [3] }", "{ [8] }" },
1537 	{ "[N] -> { [w = 0:17] : exists (e0: w < 2N and "
1538 	    "-1 + w <= e0 <= w and 2e0 >= N + w and w <= 2e0 <= 15 + w) }",
1539 	  "[N] -> { [N] }", "{ [9] }" },
1540 };
1541 
1542 /* Perform basic isl_set_get_simple_fixed_box_hull tests.
1543  */
test_box_hull(struct isl_ctx * ctx)1544 static int test_box_hull(struct isl_ctx *ctx)
1545 {
1546 	int i;
1547 
1548 	for (i = 0; i < ARRAY_SIZE(box_hull_tests); ++i) {
1549 		const char *str;
1550 		isl_stat r;
1551 		isl_set *set;
1552 		isl_multi_aff *offset;
1553 		isl_multi_val *size;
1554 		isl_fixed_box *box;
1555 
1556 		set = isl_set_read_from_str(ctx, box_hull_tests[i].set);
1557 		box = isl_set_get_simple_fixed_box_hull(set);
1558 		offset = isl_fixed_box_get_offset(box);
1559 		size = isl_fixed_box_get_size(box);
1560 		str = box_hull_tests[i].offset;
1561 		r = multi_aff_check_plain_equal(offset, str);
1562 		str = box_hull_tests[i].size;
1563 		if (r >= 0)
1564 			r = multi_val_check_plain_equal(size, str);
1565 		isl_multi_aff_free(offset);
1566 		isl_multi_val_free(size);
1567 		isl_fixed_box_free(box);
1568 		isl_set_free(set);
1569 		if (r < 0)
1570 			return -1;
1571 	}
1572 
1573 	return 0;
1574 }
1575 
test_convex_hull_case(struct isl_ctx * ctx,const char * name)1576 void test_convex_hull_case(struct isl_ctx *ctx, const char *name)
1577 {
1578 	char *filename;
1579 	FILE *input;
1580 	struct isl_basic_set *bset1, *bset2;
1581 	struct isl_set *set;
1582 
1583 	filename = get_filename(ctx, name, "polylib");
1584 	assert(filename);
1585 	input = fopen(filename, "r");
1586 	assert(input);
1587 
1588 	bset1 = isl_basic_set_read_from_file(ctx, input);
1589 	bset2 = isl_basic_set_read_from_file(ctx, input);
1590 
1591 	set = isl_basic_set_union(bset1, bset2);
1592 	bset1 = isl_set_convex_hull(set);
1593 
1594 	bset2 = isl_basic_set_read_from_file(ctx, input);
1595 
1596 	assert(isl_basic_set_is_equal(bset1, bset2) == 1);
1597 
1598 	isl_basic_set_free(bset1);
1599 	isl_basic_set_free(bset2);
1600 	free(filename);
1601 
1602 	fclose(input);
1603 }
1604 
1605 struct {
1606 	const char *set;
1607 	const char *hull;
1608 } convex_hull_tests[] = {
1609 	{ "{ [i0, i1, i2] : (i2 = 1 and i0 = 0 and i1 >= 0) or "
1610 	       "(i0 = 1 and i1 = 0 and i2 = 1) or "
1611 	       "(i0 = 0 and i1 = 0 and i2 = 0) }",
1612 	  "{ [i0, i1, i2] : i0 >= 0 and i2 >= i0 and i2 <= 1 and i1 >= 0 }" },
1613 	{ "[n] -> { [i0, i1, i0] : i0 <= -4 + n; "
1614 	    "[i0, i0, i2] : n = 6 and i0 >= 0 and i2 <= 7 - i0 and "
1615 	    "i2 <= 5 and i2 >= 4; "
1616 	    "[3, i1, 3] : n = 5 and i1 <= 2 and i1 >= 0 }",
1617 	  "[n] -> { [i0, i1, i2] : i2 <= -1 + n and 2i2 <= -6 + 3n - i0 and "
1618 	    "i2 <= 5 + i0 and i2 >= i0 }" },
1619 	{ "{ [x, y] : 3y <= 2x and y >= -2 + 2x and 2y >= 2 - x }",
1620 	    "{ [x, y] : 1 = 0 }" },
1621 	{ "{ [x, y, z] : 0 <= x, y, z <= 10; [x, y, 0] : x >= 0 and y > 0; "
1622 	    "[x, y, 0] : x >= 0 and y < 0 }",
1623 	    "{ [x, y, z] : x >= 0 and 0 <= z <= 10 }" },
1624 	{ "{ [a, b, c] : a <= 1 and -a < b <= 1 and 0 <= c <= 2 - a - b and "
1625 			    "c <= a; "
1626 	    "[0, 2, 0]; [3, 1, 0] }",
1627 	    "{ [a, b, c] : b > -a and 2b >= -1 + a and 0 <= c <= a and "
1628 			    "5c <= 6 - a - 3b }" },
1629 };
1630 
test_convex_hull_algo(isl_ctx * ctx,int convex)1631 static int test_convex_hull_algo(isl_ctx *ctx, int convex)
1632 {
1633 	int i;
1634 	int orig_convex = ctx->opt->convex;
1635 	ctx->opt->convex = convex;
1636 
1637 	test_convex_hull_case(ctx, "convex0");
1638 	test_convex_hull_case(ctx, "convex1");
1639 	test_convex_hull_case(ctx, "convex2");
1640 	test_convex_hull_case(ctx, "convex3");
1641 	test_convex_hull_case(ctx, "convex4");
1642 	test_convex_hull_case(ctx, "convex5");
1643 	test_convex_hull_case(ctx, "convex6");
1644 	test_convex_hull_case(ctx, "convex7");
1645 	test_convex_hull_case(ctx, "convex8");
1646 	test_convex_hull_case(ctx, "convex9");
1647 	test_convex_hull_case(ctx, "convex10");
1648 	test_convex_hull_case(ctx, "convex11");
1649 	test_convex_hull_case(ctx, "convex12");
1650 	test_convex_hull_case(ctx, "convex13");
1651 	test_convex_hull_case(ctx, "convex14");
1652 	test_convex_hull_case(ctx, "convex15");
1653 
1654 	for (i = 0; i < ARRAY_SIZE(convex_hull_tests); ++i) {
1655 		isl_set *set1, *set2;
1656 		int equal;
1657 
1658 		set1 = isl_set_read_from_str(ctx, convex_hull_tests[i].set);
1659 		set2 = isl_set_read_from_str(ctx, convex_hull_tests[i].hull);
1660 		set1 = isl_set_from_basic_set(isl_set_convex_hull(set1));
1661 		equal = isl_set_is_equal(set1, set2);
1662 		isl_set_free(set1);
1663 		isl_set_free(set2);
1664 
1665 		if (equal < 0)
1666 			return -1;
1667 		if (!equal)
1668 			isl_die(ctx, isl_error_unknown,
1669 				"unexpected convex hull", return -1);
1670 	}
1671 
1672 	ctx->opt->convex = orig_convex;
1673 
1674 	return 0;
1675 }
1676 
test_convex_hull(isl_ctx * ctx)1677 static int test_convex_hull(isl_ctx *ctx)
1678 {
1679 	if (test_convex_hull_algo(ctx, ISL_CONVEX_HULL_FM) < 0)
1680 		return -1;
1681 	if (test_convex_hull_algo(ctx, ISL_CONVEX_HULL_WRAP) < 0)
1682 		return -1;
1683 	return 0;
1684 }
1685 
test_gist_case(struct isl_ctx * ctx,const char * name)1686 void test_gist_case(struct isl_ctx *ctx, const char *name)
1687 {
1688 	char *filename;
1689 	FILE *input;
1690 	struct isl_basic_set *bset1, *bset2;
1691 
1692 	filename = get_filename(ctx, name, "polylib");
1693 	assert(filename);
1694 	input = fopen(filename, "r");
1695 	assert(input);
1696 
1697 	bset1 = isl_basic_set_read_from_file(ctx, input);
1698 	bset2 = isl_basic_set_read_from_file(ctx, input);
1699 
1700 	bset1 = isl_basic_set_gist(bset1, bset2);
1701 
1702 	bset2 = isl_basic_set_read_from_file(ctx, input);
1703 
1704 	assert(isl_basic_set_is_equal(bset1, bset2) == 1);
1705 
1706 	isl_basic_set_free(bset1);
1707 	isl_basic_set_free(bset2);
1708 	free(filename);
1709 
1710 	fclose(input);
1711 }
1712 
1713 /* Check that computing the gist of "map" with respect to "context"
1714  * does not make any copy of "map" get marked empty.
1715  * Earlier versions of isl would end up doing that.
1716  */
test_gist_empty_pair(isl_ctx * ctx,const char * map,const char * context)1717 static isl_stat test_gist_empty_pair(isl_ctx *ctx, const char *map,
1718 	const char *context)
1719 {
1720 	isl_map *m1, *m2, *m3;
1721 	isl_bool empty_before, empty_after;
1722 
1723 	m1 = isl_map_read_from_str(ctx, map);
1724 	m2 = isl_map_read_from_str(ctx, context);
1725 	m3 = isl_map_copy(m1);
1726 	empty_before = isl_map_is_empty(m3);
1727 	m1 = isl_map_gist(m1, m2);
1728 	empty_after = isl_map_is_empty(m3);
1729 	isl_map_free(m1);
1730 	isl_map_free(m3);
1731 
1732 	if (empty_before < 0 || empty_after < 0)
1733 		return isl_stat_error;
1734 	if (empty_before)
1735 		isl_die(ctx, isl_error_unknown, "map should not be empty",
1736 			return isl_stat_error);
1737 	if (empty_after)
1738 		isl_die(ctx, isl_error_unknown, "map should still not be empty",
1739 			return isl_stat_error);
1740 
1741 	return isl_stat_ok;
1742 }
1743 
1744 /* Check that computing a gist does not make any copy of the input
1745  * get marked empty.
1746  * Earlier versions of isl would end up doing that on some pairs of inputs.
1747  */
test_gist_empty(isl_ctx * ctx)1748 static isl_stat test_gist_empty(isl_ctx *ctx)
1749 {
1750 	const char *map, *context;
1751 
1752 	map = "{ [] -> [a, b, c] : 2b = 1 + a }";
1753 	context = "{ [] -> [a, b, c] : 2c = 2 + a }";
1754 	if (test_gist_empty_pair(ctx, map, context) < 0)
1755 		return isl_stat_error;
1756 	map = "{ [] -> [0, 0] }";
1757 	context = "{ [] -> [a, b] : a > b }";
1758 	if (test_gist_empty_pair(ctx, map, context) < 0)
1759 		return isl_stat_error;
1760 
1761 	return isl_stat_ok;
1762 }
1763 
1764 /* Inputs to isl_map_plain_gist_basic_map, along with the expected output.
1765  */
1766 struct {
1767 	const char *map;
1768 	const char *context;
1769 	const char *gist;
1770 } plain_gist_tests[] = {
1771 	{ "{ [i] -> [j] : i >= 1 and j >= 1 or i >= 2 and j <= 10 }",
1772 	  "{ [i] -> [j] : i >= 1 }",
1773 	  "{ [i] -> [j] : j >= 1 or i >= 2 and j <= 10 }" },
1774 	{ "{ [n] -> [i,j,k] : (i mod 3 = 2 and j mod 4 = 2) or "
1775 		"(j mod 4 = 2 and k mod 6 = n) }",
1776 	  "{ [n] -> [i,j,k] : j mod 4 = 2 }",
1777 	  "{ [n] -> [i,j,k] : (i mod 3 = 2) or (k mod 6 = n) }" },
1778 	{ "{ [i] -> [j] : i > j and (exists a,b : i <= 2a + 5b <= 2) }",
1779 	  "{ [i] -> [j] : i > j }",
1780 	  "{ [i] -> [j] : exists a,b : i <= 2a + 5b <= 2 }" },
1781 };
1782 
1783 /* Basic tests for isl_map_plain_gist_basic_map.
1784  */
test_plain_gist(isl_ctx * ctx)1785 static int test_plain_gist(isl_ctx *ctx)
1786 {
1787 	int i;
1788 
1789 	for (i = 0; i < ARRAY_SIZE(plain_gist_tests); ++i) {
1790 		const char *str;
1791 		int equal;
1792 		isl_map *map, *gist;
1793 		isl_basic_map *context;
1794 
1795 		map = isl_map_read_from_str(ctx, plain_gist_tests[i].map);
1796 		str = plain_gist_tests[i].context;
1797 		context = isl_basic_map_read_from_str(ctx, str);
1798 		map = isl_map_plain_gist_basic_map(map, context);
1799 		gist = isl_map_read_from_str(ctx, plain_gist_tests[i].gist);
1800 		equal = isl_map_is_equal(map, gist);
1801 		isl_map_free(map);
1802 		isl_map_free(gist);
1803 		if (equal < 0)
1804 			return -1;
1805 		if (!equal)
1806 			isl_die(ctx, isl_error_unknown,
1807 				"incorrect gist result", return -1);
1808 	}
1809 
1810 	return 0;
1811 }
1812 
1813 /* Inputs for isl_basic_set_gist tests that are expected to fail.
1814  */
1815 struct {
1816 	const char *set;
1817 	const char *context;
1818 } gist_fail_tests[] = {
1819 	{ "{ [i] : exists (e0, e1: 3e1 >= 1 + 2e0 and "
1820 	    "8e1 <= -1 + 5i - 5e0 and 2e1 >= 1 + 2i - 5e0) }",
1821 	  "{ [i] : i >= 0 }" },
1822 };
1823 
1824 /* Check that isl_basic_set_gist fails (gracefully) when expected.
1825  * In particular, the user should be able to recover from the failure.
1826  */
test_gist_fail(struct isl_ctx * ctx)1827 static isl_stat test_gist_fail(struct isl_ctx *ctx)
1828 {
1829 	int i, n;
1830 	int on_error;
1831 
1832 	on_error = isl_options_get_on_error(ctx);
1833 	isl_options_set_on_error(ctx, ISL_ON_ERROR_CONTINUE);
1834 	n = ARRAY_SIZE(gist_fail_tests);
1835 	for (i = 0; i < n; ++i) {
1836 		const char *str;
1837 		isl_basic_set *bset, *context;
1838 
1839 		bset = isl_basic_set_read_from_str(ctx, gist_fail_tests[i].set);
1840 		str = gist_fail_tests[i].context;
1841 		context = isl_basic_set_read_from_str(ctx, str);
1842 		bset = isl_basic_set_gist(bset, context);
1843 		isl_basic_set_free(bset);
1844 		if (bset)
1845 			break;
1846 	}
1847 	isl_options_set_on_error(ctx, on_error);
1848 	if (i < n)
1849 		isl_die(ctx, isl_error_unknown,
1850 			"operation not expected to succeed",
1851 			return isl_stat_error);
1852 
1853 	return isl_stat_ok;
1854 }
1855 
1856 struct {
1857 	const char *set;
1858 	const char *context;
1859 	const char *gist;
1860 } gist_tests[] = {
1861 	{ "{ [a, b, c] : a <= 15 and a >= 1 }",
1862 	  "{ [a, b, c] : exists (e0 = floor((-1 + a)/16): a >= 1 and "
1863 			"c <= 30 and 32e0 >= -62 + 2a + 2b - c and b >= 0) }",
1864 	  "{ [a, b, c] : a <= 15 }" },
1865 	{ "{ : }", "{ : 1 = 0 }", "{ : }" },
1866 	{ "{ : 1 = 0 }", "{ : 1 = 0 }", "{ : }" },
1867 	{ "[M] -> { [x] : exists (e0 = floor((-2 + x)/3): 3e0 = -2 + x) }",
1868 	  "[M] -> { [3M] }" , "[M] -> { [x] : 1 = 0 }" },
1869 	{ "{ [m, n, a, b] : a <= 2147 + n }",
1870 	  "{ [m, n, a, b] : (m >= 1 and n >= 1 and a <= 2148 - m and "
1871 			"b <= 2148 - n and b >= 0 and b >= 2149 - n - a) or "
1872 			"(n >= 1 and a >= 0 and b <= 2148 - n - a and "
1873 			"b >= 0) }",
1874 	  "{ [m, n, ku, kl] }" },
1875 	{ "{ [a, a, b] : a >= 10 }",
1876 	  "{ [a, b, c] : c >= a and c <= b and c >= 2 }",
1877 	  "{ [a, a, b] : a >= 10 }" },
1878 	{ "{ [i, j] : i >= 0 and i + j >= 0 }", "{ [i, j] : i <= 0 }",
1879 	  "{ [0, j] : j >= 0 }" },
1880 	/* Check that no constraints on i6 are introduced in the gist */
1881 	{ "[t1] -> { [i4, i6] : exists (e0 = floor((1530 - 4t1 - 5i4)/20): "
1882 		"20e0 <= 1530 - 4t1 - 5i4 and 20e0 >= 1511 - 4t1 - 5i4 and "
1883 		"5e0 <= 381 - t1 and i4 <= 1) }",
1884 	  "[t1] -> { [i4, i6] : exists (e0 = floor((-t1 + i6)/5): "
1885 		"5e0 = -t1 + i6 and i6 <= 6 and i6 >= 3) }",
1886 	  "[t1] -> { [i4, i6] : exists (e0 = floor((1530 - 4t1 - 5i4)/20): "
1887 		"i4 <= 1 and 5e0 <= 381 - t1 and 20e0 <= 1530 - 4t1 - 5i4 and "
1888 		"20e0 >= 1511 - 4t1 - 5i4) }" },
1889 	/* Check that no constraints on i6 are introduced in the gist */
1890 	{ "[t1, t2] -> { [i4, i5, i6] : exists (e0 = floor((1 + i4)/2), "
1891 		"e1 = floor((1530 - 4t1 - 5i4)/20), "
1892 		"e2 = floor((-4t1 - 5i4 + 10*floor((1 + i4)/2))/20), "
1893 		"e3 = floor((-1 + i4)/2): t2 = 0 and 2e3 = -1 + i4 and "
1894 			"20e2 >= -19 - 4t1 - 5i4 + 10e0 and 5e2 <= 1 - t1 and "
1895 			"2e0 <= 1 + i4 and 2e0 >= i4 and "
1896 			"20e1 <= 1530 - 4t1 - 5i4 and "
1897 			"20e1 >= 1511 - 4t1 - 5i4 and i4 <= 1 and "
1898 			"5e1 <= 381 - t1 and 20e2 <= -4t1 - 5i4 + 10e0) }",
1899 	  "[t1, t2] -> { [i4, i5, i6] : exists (e0 = floor((-17 + i4)/2), "
1900 		"e1 = floor((-t1 + i6)/5): 5e1 = -t1 + i6 and "
1901 			"2e0 <= -17 + i4 and 2e0 >= -18 + i4 and "
1902 			"10e0 <= -91 + 5i4 + 4i6 and "
1903 			"10e0 >= -105 + 5i4 + 4i6) }",
1904 	  "[t1, t2] -> { [i4, i5, i6] : exists (e0 = floor((381 - t1)/5), "
1905 		"e1 = floor((-1 + i4)/2): t2 = 0 and 2e1 = -1 + i4 and "
1906 		"i4 <= 1 and 5e0 <= 381 - t1 and 20e0 >= 1511 - 4t1 - 5i4) }" },
1907 	{ "{ [0, 0, q, p] : -5 <= q <= 5 and p >= 0 }",
1908 	  "{ [a, b, q, p] : b >= 1 + a }",
1909 	  "{ [a, b, q, p] : false }" },
1910 	{ "[n] -> { [x] : x = n && x mod 32 = 0 }",
1911 	  "[n] -> { [x] : x mod 32 = 0 }",
1912 	  "[n] -> { [x = n] }" },
1913 	{ "{ [x] : x mod 6 = 0 }", "{ [x] : x mod 3 = 0 }",
1914 	  "{ [x] : x mod 2 = 0 }" },
1915 	{ "{ [x] : x mod 3200 = 0 }", "{ [x] : x mod 10000 = 0 }",
1916 	  "{ [x] : x mod 128 = 0 }" },
1917 	{ "{ [x] : x mod 3200 = 0 }", "{ [x] : x mod 10 = 0 }",
1918 	  "{ [x] : x mod 3200 = 0 }" },
1919 	{ "{ [a, b, c] : a mod 2 = 0 and a = c }",
1920 	  "{ [a, b, c] : b mod 2 = 0 and b = c }",
1921 	  "{ [a, b, c = a] }" },
1922 	{ "{ [a, b, c] : a mod 6 = 0 and a = c }",
1923 	  "{ [a, b, c] : b mod 2 = 0 and b = c }",
1924 	  "{ [a, b, c = a] : a mod 3 = 0 }" },
1925 	{ "{ [x] : 0 <= x <= 4 or 6 <= x <= 9 }",
1926 	  "{ [x] : 1 <= x <= 3 or 7 <= x <= 8 }",
1927 	  "{ [x] }" },
1928 	{ "{ [x,y] : x < 0 and 0 <= y <= 4 or x >= -2 and -x <= y <= 10 + x }",
1929 	  "{ [x,y] : 1 <= y <= 3 }",
1930 	  "{ [x,y] }" },
1931 };
1932 
1933 /* Check that isl_set_gist behaves as expected.
1934  *
1935  * For the test cases in gist_tests, besides checking that the result
1936  * is as expected, also check that applying the gist operation does
1937  * not modify the input set (an earlier version of isl would do that) and
1938  * that the test case is consistent, i.e., that the gist has the same
1939  * intersection with the context as the input set.
1940  */
test_gist(struct isl_ctx * ctx)1941 static int test_gist(struct isl_ctx *ctx)
1942 {
1943 	int i;
1944 	const char *str;
1945 	isl_basic_set *bset1, *bset2;
1946 	isl_map *map1, *map2;
1947 	isl_bool equal;
1948 	isl_size n_div;
1949 
1950 	for (i = 0; i < ARRAY_SIZE(gist_tests); ++i) {
1951 		isl_bool equal_input, equal_intersection;
1952 		isl_set *set1, *set2, *copy, *context;
1953 
1954 		set1 = isl_set_read_from_str(ctx, gist_tests[i].set);
1955 		context = isl_set_read_from_str(ctx, gist_tests[i].context);
1956 		copy = isl_set_copy(set1);
1957 		set1 = isl_set_gist(set1, isl_set_copy(context));
1958 		set2 = isl_set_read_from_str(ctx, gist_tests[i].gist);
1959 		equal = isl_set_is_equal(set1, set2);
1960 		isl_set_free(set1);
1961 		set1 = isl_set_read_from_str(ctx, gist_tests[i].set);
1962 		equal_input = isl_set_is_equal(set1, copy);
1963 		isl_set_free(copy);
1964 		set1 = isl_set_intersect(set1, isl_set_copy(context));
1965 		set2 = isl_set_intersect(set2, context);
1966 		equal_intersection = isl_set_is_equal(set1, set2);
1967 		isl_set_free(set2);
1968 		isl_set_free(set1);
1969 		if (equal < 0 || equal_input < 0 || equal_intersection < 0)
1970 			return -1;
1971 		if (!equal)
1972 			isl_die(ctx, isl_error_unknown,
1973 				"incorrect gist result", return -1);
1974 		if (!equal_input)
1975 			isl_die(ctx, isl_error_unknown,
1976 				"gist modified input", return -1);
1977 		if (!equal_input)
1978 			isl_die(ctx, isl_error_unknown,
1979 				"inconsistent gist test case", return -1);
1980 	}
1981 
1982 	if (test_gist_fail(ctx) < 0)
1983 		return -1;
1984 
1985 	test_gist_case(ctx, "gist1");
1986 
1987 	str = "[p0, p2, p3, p5, p6, p10] -> { [] : "
1988 	    "exists (e0 = [(15 + p0 + 15p6 + 15p10)/16], e1 = [(p5)/8], "
1989 	    "e2 = [(p6)/128], e3 = [(8p2 - p5)/128], "
1990 	    "e4 = [(128p3 - p6)/4096]: 8e1 = p5 and 128e2 = p6 and "
1991 	    "128e3 = 8p2 - p5 and 4096e4 = 128p3 - p6 and p2 >= 0 and "
1992 	    "16e0 >= 16 + 16p6 + 15p10 and  p2 <= 15 and p3 >= 0 and "
1993 	    "p3 <= 31 and  p6 >= 128p3 and p5 >= 8p2 and p10 >= 0 and "
1994 	    "16e0 <= 15 + p0 + 15p6 + 15p10 and 16e0 >= p0 + 15p6 + 15p10 and "
1995 	    "p10 <= 15 and p10 <= -1 + p0 - p6) }";
1996 	bset1 = isl_basic_set_read_from_str(ctx, str);
1997 	str = "[p0, p2, p3, p5, p6, p10] -> { [] : exists (e0 = [(p5)/8], "
1998 	    "e1 = [(p6)/128], e2 = [(8p2 - p5)/128], "
1999 	    "e3 = [(128p3 - p6)/4096]: 8e0 = p5 and 128e1 = p6 and "
2000 	    "128e2 = 8p2 - p5 and 4096e3 = 128p3 - p6 and p5 >= -7 and "
2001 	    "p2 >= 0 and 8p2 <= -1 + p0 and p2 <= 15 and p3 >= 0 and "
2002 	    "p3 <= 31 and 128p3 <= -1 + p0 and p6 >= -127 and "
2003 	    "p5 <= -1 + p0 and p6 <= -1 + p0 and p6 >= 128p3 and "
2004 	    "p0 >= 1 and p5 >= 8p2 and p10 >= 0 and p10 <= 15 ) }";
2005 	bset2 = isl_basic_set_read_from_str(ctx, str);
2006 	bset1 = isl_basic_set_gist(bset1, bset2);
2007 	assert(bset1 && bset1->n_div == 0);
2008 	isl_basic_set_free(bset1);
2009 
2010 	/* Check that the integer divisions of the second disjunct
2011 	 * do not spread to the first disjunct.
2012 	 */
2013 	str = "[t1] -> { S_0[] -> A[o0] : (exists (e0 = [(-t1 + o0)/16]: "
2014 		"16e0 = -t1 + o0 and o0 >= 0 and o0 <= 15 and t1 >= 0)) or "
2015 		"(exists (e0 = [(-1 + t1)/16], "
2016 			"e1 = [(-16 + t1 - 16e0)/4294967296]: "
2017 			"4294967296e1 = -16 + t1 - o0 - 16e0 and "
2018 			"16e0 <= -1 + t1 and 16e0 >= -16 + t1 and o0 >= 0 and "
2019 			"o0 <= 4294967295 and t1 <= -1)) }";
2020 	map1 = isl_map_read_from_str(ctx, str);
2021 	str = "[t1] -> { S_0[] -> A[o0] : t1 >= 0 and t1 <= 4294967295 }";
2022 	map2 = isl_map_read_from_str(ctx, str);
2023 	map1 = isl_map_gist(map1, map2);
2024 	if (!map1)
2025 		return -1;
2026 	if (map1->n != 1)
2027 		isl_die(ctx, isl_error_unknown, "expecting single disjunct",
2028 			isl_map_free(map1); return -1);
2029 	n_div = isl_basic_map_dim(map1->p[0], isl_dim_div);
2030 	isl_map_free(map1);
2031 	if (n_div < 0)
2032 		return -1;
2033 	if (n_div != 1)
2034 		isl_die(ctx, isl_error_unknown, "expecting single div",
2035 			return -1);
2036 
2037 	if (test_gist_empty(ctx) < 0)
2038 		return -1;
2039 	if (test_plain_gist(ctx) < 0)
2040 		return -1;
2041 
2042 	return 0;
2043 }
2044 
test_coalesce_set(isl_ctx * ctx,const char * str,int check_one)2045 int test_coalesce_set(isl_ctx *ctx, const char *str, int check_one)
2046 {
2047 	isl_set *set, *set2;
2048 	int equal;
2049 	int one;
2050 
2051 	set = isl_set_read_from_str(ctx, str);
2052 	set = isl_set_coalesce(set);
2053 	set2 = isl_set_read_from_str(ctx, str);
2054 	equal = isl_set_is_equal(set, set2);
2055 	one = set && set->n == 1;
2056 	isl_set_free(set);
2057 	isl_set_free(set2);
2058 
2059 	if (equal < 0)
2060 		return -1;
2061 	if (!equal)
2062 		isl_die(ctx, isl_error_unknown,
2063 			"coalesced set not equal to input", return -1);
2064 	if (check_one && !one)
2065 		isl_die(ctx, isl_error_unknown,
2066 			"coalesced set should not be a union", return -1);
2067 
2068 	return 0;
2069 }
2070 
2071 /* Inputs for coalescing tests with unbounded wrapping.
2072  * "str" is a string representation of the input set.
2073  * "single_disjunct" is set if we expect the result to consist of
2074  *	a single disjunct.
2075  */
2076 struct {
2077 	int single_disjunct;
2078 	const char *str;
2079 } coalesce_unbounded_tests[] = {
2080 	{ 1, "{ [x,y,z] : y + 2 >= 0 and x - y + 1 >= 0 and "
2081 			"-x - y + 1 >= 0 and -3 <= z <= 3;"
2082 		"[x,y,z] : -x+z + 20 >= 0 and -x-z + 20 >= 0 and "
2083 			"x-z + 20 >= 0 and x+z + 20 >= 0 and "
2084 			"-10 <= y <= 0}" },
2085 	{ 1, "{ [x,y] : 0 <= x,y <= 10; [5,y]: 4 <= y <= 11 }" },
2086 	{ 1, "{ [x,0,0] : -5 <= x <= 5; [0,y,1] : -5 <= y <= 5 }" },
2087 	{ 1, "{ [x,y] : 0 <= x <= 10 and 0 >= y >= -1 and x+y >= 0; [0,1] }" },
2088 	{ 1, "{ [x,y] : (0 <= x,y <= 4) or (2 <= x,y <= 5 and x + y <= 9) }" },
2089 	{ 0, "{ [x, y, z] : 0 <= x,y,z <= 100 and 0 < z <= 2 + 2x + 2y; "
2090 		"[x, y, 0] : x,y <= 100 and y <= 9 + 11x and x <= 9 + 11y }" },
2091 	{ 1, "{ [0:1, 0:1]; [0, 2:3] }" },
2092 	{ 1, "{ [0:1, 0:1]; [0, 2:3]; [1, -2:-1] }" },
2093 	{ 1, "{ [0:3, 0:1]; [1:2, 2:5] }" },
2094 	{ 1, "{ [0:3, 0:1]; [0:2, 2:5] }" },
2095 	{ 1, "{ [0:3, 0:1]; [1:3, 2:5] }" },
2096 	{ 0, "{ [0:3, 0:1]; [1:4, 2:5] }" },
2097 	{ 0, "{ [0:3, 0:1]; [1:5, 2:5] }" },
2098 };
2099 
2100 /* Test the functionality of isl_set_coalesce with the bounded wrapping
2101  * option turned off.
2102  */
test_coalesce_unbounded_wrapping(isl_ctx * ctx)2103 int test_coalesce_unbounded_wrapping(isl_ctx *ctx)
2104 {
2105 	int i;
2106 	int r = 0;
2107 	int bounded;
2108 
2109 	bounded = isl_options_get_coalesce_bounded_wrapping(ctx);
2110 	isl_options_set_coalesce_bounded_wrapping(ctx, 0);
2111 
2112 	for (i = 0; i < ARRAY_SIZE(coalesce_unbounded_tests); ++i) {
2113 		const char *str = coalesce_unbounded_tests[i].str;
2114 		int check_one = coalesce_unbounded_tests[i].single_disjunct;
2115 		if (test_coalesce_set(ctx, str, check_one) >= 0)
2116 			continue;
2117 		r = -1;
2118 		break;
2119 	}
2120 
2121 	isl_options_set_coalesce_bounded_wrapping(ctx, bounded);
2122 
2123 	return r;
2124 }
2125 
2126 /* Inputs for coalescing tests.
2127  * "str" is a string representation of the input set.
2128  * "single_disjunct" is set if we expect the result to consist of
2129  *	a single disjunct.
2130  */
2131 struct {
2132 	int single_disjunct;
2133 	const char *str;
2134 } coalesce_tests[] = {
2135 	{ 1, "{[x,y]: x >= 0 & x <= 10 & y >= 0 & y <= 10 or "
2136 		       "y >= x & x >= 2 & 5 >= y }" },
2137 	{ 1, "{[x,y]: y >= 0 & 2x + y <= 30 & y <= 10 & x >= 0 or "
2138 		       "x + y >= 10 & y <= x & x + y <= 20 & y >= 0}" },
2139 	{ 0, "{[x,y]: y >= 0 & 2x + y <= 30 & y <= 10 & x >= 0 or "
2140 		       "x + y >= 10 & y <= x & x + y <= 19 & y >= 0}" },
2141 	{ 1, "{[x,y]: y >= 0 & x <= 5 & y <= x or "
2142 		       "y >= 0 & x >= 6 & x <= 10 & y <= x}" },
2143 	{ 0, "{[x,y]: y >= 0 & x <= 5 & y <= x or "
2144 		       "y >= 0 & x >= 7 & x <= 10 & y <= x}" },
2145 	{ 0, "{[x,y]: y >= 0 & x <= 5 & y <= x or "
2146 		       "y >= 0 & x >= 6 & x <= 10 & y + 1 <= x}" },
2147 	{ 1, "{[x,y]: y >= 0 & x <= 5 & y <= x or y >= 0 & x = 6 & y <= 6}" },
2148 	{ 0, "{[x,y]: y >= 0 & x <= 5 & y <= x or y >= 0 & x = 7 & y <= 6}" },
2149 	{ 1, "{[x,y]: y >= 0 & x <= 5 & y <= x or y >= 0 & x = 6 & y <= 5}" },
2150 	{ 0, "{[x,y]: y >= 0 & x <= 5 & y <= x or y >= 0 & x = 6 & y <= 7}" },
2151 	{ 1, "[n] -> { [i] : i = 1 and n >= 2 or 2 <= i and i <= n }" },
2152 	{ 0, "{[x,y] : x >= 0 and y >= 0 or 0 <= y and y <= 5 and x = -1}" },
2153 	{ 1, "[n] -> { [i] : 1 <= i and i <= n - 1 or 2 <= i and i <= n }" },
2154 	{ 0, "[n] -> { [[i0] -> [o0]] : exists (e0 = [(i0)/4], e1 = [(o0)/4], "
2155 		"e2 = [(n)/2], e3 = [(-2 + i0)/4], e4 = [(-2 + o0)/4], "
2156 		"e5 = [(-2n + i0)/4]: 2e2 = n and 4e3 = -2 + i0 and "
2157 		"4e4 = -2 + o0 and i0 >= 8 + 2n and o0 >= 2 + i0 and "
2158 		"o0 <= 56 + 2n and o0 <= -12 + 4n and i0 <= 57 + 2n and "
2159 		"i0 <= -11 + 4n and o0 >= 6 + 2n and 4e0 <= i0 and "
2160 		"4e0 >= -3 + i0 and 4e1 <= o0 and 4e1 >= -3 + o0 and "
2161 		"4e5 <= -2n + i0 and 4e5 >= -3 - 2n + i0);"
2162 		"[[i0] -> [o0]] : exists (e0 = [(i0)/4], e1 = [(o0)/4], "
2163 		"e2 = [(n)/2], e3 = [(-2 + i0)/4], e4 = [(-2 + o0)/4], "
2164 		"e5 = [(-2n + i0)/4]: 2e2 = n and 4e3 = -2 + i0 and "
2165 		"4e4 = -2 + o0 and 2e0 >= 3 + n and e0 <= -4 + n and "
2166 		"2e0 <= 27 + n and e1 <= -4 + n and 2e1 <= 27 + n and "
2167 		"2e1 >= 2 + n and e1 >= 1 + e0 and i0 >= 7 + 2n and "
2168 		"i0 <= -11 + 4n and i0 <= 57 + 2n and 4e0 <= -2 + i0 and "
2169 		"4e0 >= -3 + i0 and o0 >= 6 + 2n and o0 <= -11 + 4n and "
2170 		"o0 <= 57 + 2n and 4e1 <= -2 + o0 and 4e1 >= -3 + o0 and "
2171 		"4e5 <= -2n + i0 and 4e5 >= -3 - 2n + i0 ) }" },
2172 	{ 0, "[n, m] -> { [o0, o2, o3] : (o3 = 1 and o0 >= 1 + m and "
2173 	      "o0 <= n + m and o2 <= m and o0 >= 2 + n and o2 >= 3) or "
2174 	      "(o0 >= 2 + n and o0 >= 1 + m and o0 <= n + m and n >= 1 and "
2175 	      "o3 <= -1 + o2 and o3 >= 1 - m + o2 and o3 >= 2 and o3 <= n) }" },
2176 	{ 0, "[M, N] -> { [[i0, i1, i2, i3, i4, i5, i6] -> "
2177 	  "[o0, o1, o2, o3, o4, o5, o6]] : "
2178 	  "(o6 <= -4 + 2M - 2N + i0 + i1 - i2 + i6 - o0 - o1 + o2 and "
2179 	  "o3 <= -2 + i3 and o6 >= 2 + i0 + i3 + i6 - o0 - o3 and "
2180 	  "o6 >= 2 - M + N + i3 + i4 + i6 - o3 - o4 and o0 <= -1 + i0 and "
2181 	  "o4 >= 4 - 3M + 3N - i0 - i1 + i2 + 2i3 + i4 + o0 + o1 - o2 - 2o3 "
2182 	  "and o6 <= -3 + 2M - 2N + i3 + i4 - i5 + i6 - o3 - o4 + o5 and "
2183 	  "2o6 <= -5 + 5M - 5N + 2i0 + i1 - i2 - i5 + 2i6 - 2o0 - o1 + o2 + o5 "
2184 	  "and o6 >= 2i0 + i1 + i6 - 2o0 - o1 and "
2185 	  "3o6 <= -5 + 4M - 4N + 2i0 + i1 - i2 + 2i3 + i4 - i5 + 3i6 "
2186 	  "- 2o0 - o1 + o2 - 2o3 - o4 + o5) or "
2187 	  "(N >= 2 and o3 <= -1 + i3 and o0 <= -1 + i0 and "
2188 	  "o6 >= i3 + i6 - o3 and M >= 0 and "
2189 	  "2o6 >= 1 + i0 + i3 + 2i6 - o0 - o3 and "
2190 	  "o6 >= 1 - M + i0 + i6 - o0 and N >= 2M and o6 >= i0 + i6 - o0) }" },
2191 	{ 0, "[M, N] -> { [o0] : (o0 = 0 and M >= 1 and N >= 2) or "
2192 		"(o0 = 0 and M >= 1 and N >= 2M and N >= 2 + M) or "
2193 		"(o0 = 0 and M >= 2 and N >= 3) or "
2194 		"(M = 0 and o0 = 0 and N >= 3) }" },
2195 	{ 0, "{ [i0, i1, i2, i3] : (i1 = 10i0 and i0 >= 1 and 10i0 <= 100 and "
2196 	    "i3 <= 9 + 10 i2 and i3 >= 1 + 10i2 and i3 >= 0) or "
2197 	    "(i1 <= 9 + 10i0 and i1 >= 1 + 10i0 and i2 >= 0 and "
2198 	    "i0 >= 0 and i1 <= 100 and i3 <= 9 + 10i2 and i3 >= 1 + 10i2) }" },
2199 	{ 0, "[M] -> { [i1] : (i1 >= 2 and i1 <= M) or (i1 = M and M >= 1) }" },
2200 	{ 0, "{[x,y] : x,y >= 0; [x,y] : 10 <= x <= 20 and y >= -1 }" },
2201 	{ 1, "{ [x, y] : (x >= 1 and y >= 1 and x <= 2 and y <= 2) or "
2202 		"(y = 3 and x = 1) }" },
2203 	{ 1, "[M] -> { [i0, i1, i2, i3, i4] : (i1 >= 3 and i4 >= 2 + i2 and "
2204 		"i2 >= 2 and i0 >= 2 and i3 >= 1 + i2 and i0 <= M and "
2205 		"i1 <= M and i3 <= M and i4 <= M) or "
2206 		"(i1 >= 2 and i4 >= 1 + i2 and i2 >= 2 and i0 >= 2 and "
2207 		"i3 >= 1 + i2 and i0 <= M and i1 <= -1 + M and i3 <= M and "
2208 		"i4 <= -1 + M) }" },
2209 	{ 1, "{ [x, y] : (x >= 0 and y >= 0 and x <= 10 and y <= 10) or "
2210 		"(x >= 1 and y >= 1 and x <= 11 and y <= 11) }" },
2211 	{ 0, "{[x,0] : x >= 0; [x,1] : x <= 20}" },
2212 	{ 1, "{ [x, 1 - x] : 0 <= x <= 1; [0,0] }" },
2213 	{ 1, "{ [0,0]; [i,i] : 1 <= i <= 10 }" },
2214 	{ 0, "{ [0,0]; [i,j] : 1 <= i,j <= 10 }" },
2215 	{ 1, "{ [0,0]; [i,2i] : 1 <= i <= 10 }" },
2216 	{ 0, "{ [0,0]; [i,2i] : 2 <= i <= 10 }" },
2217 	{ 0, "{ [1,0]; [i,2i] : 1 <= i <= 10 }" },
2218 	{ 0, "{ [0,1]; [i,2i] : 1 <= i <= 10 }" },
2219 	{ 0, "{ [a, b] : exists e : 2e = a and "
2220 		    "a >= 0 and (a <= 3 or (b <= 0 and b >= -4 + a)) }" },
2221 	{ 0, "{ [i, j, i', j'] : i <= 2 and j <= 2 and "
2222 			"j' >= -1 + 2i + j - 2i' and i' <= -1 + i and "
2223 			"j >= 1 and j' <= i + j - i' and i >= 1; "
2224 		"[1, 1, 1, 1] }" },
2225 	{ 1, "{ [i,j] : exists a,b : i = 2a and j = 3b; "
2226 		 "[i,j] : exists a : j = 3a }" },
2227 	{ 1, "{ [a, b, c] : (c <= 7 - b and b <= 1 and b >= 0 and "
2228 			"c >= 3 + b and b <= 3 + 8a and b >= -26 + 8a and "
2229 			"a >= 3) or "
2230 		    "(b <= 1 and c <= 7 and b >= 0 and c >= 4 + b and "
2231 			"b <= 3 + 8a and b >= -26 + 8a and a >= 3) }" },
2232 	{ 1, "{ [a, 0, c] : c >= 1 and c <= 29 and c >= -1 + 8a and "
2233 				"c <= 6 + 8a and a >= 3; "
2234 		"[a, -1, c] : c >= 1 and c <= 30 and c >= 8a and "
2235 				"c <= 7 + 8a and a >= 3 and a <= 4 }" },
2236 	{ 1, "{ [x,y] : 0 <= x <= 2 and y >= 0 and x + 2y <= 4; "
2237 		"[x,0] : 3 <= x <= 4 }" },
2238 	{ 1, "{ [x,y] : 0 <= x <= 3 and y >= 0 and x + 3y <= 6; "
2239 		"[x,0] : 4 <= x <= 5 }" },
2240 	{ 0, "{ [x,y] : 0 <= x <= 2 and y >= 0 and x + 2y <= 4; "
2241 		"[x,0] : 3 <= x <= 5 }" },
2242 	{ 0, "{ [x,y] : 0 <= x <= 2 and y >= 0 and x + y <= 4; "
2243 		"[x,0] : 3 <= x <= 4 }" },
2244 	{ 1, "{ [i0, i1] : i0 <= 122 and i0 >= 1 and 128i1 >= -249 + i0 and "
2245 			"i1 <= 0; "
2246 		"[i0, 0] : i0 >= 123 and i0 <= 124 }" },
2247 	{ 1, "{ [0,0]; [1,1] }" },
2248 	{ 1, "[n] -> { [k] : 16k <= -1 + n and k >= 1; [0] : n >= 2 }" },
2249 	{ 1, "{ [k, ii, k - ii] : ii >= -6 + k and ii <= 6 and ii >= 1 and "
2250 				"ii <= k;"
2251 		"[k, 0, k] : k <= 6 and k >= 1 }" },
2252 	{ 1, "{ [i,j] : i = 4 j and 0 <= i <= 100;"
2253 		"[i,j] : 1 <= i <= 100 and i >= 4j + 1 and i <= 4j + 2 }" },
2254 	{ 1, "{ [x,y] : x % 2 = 0 and y % 2 = 0; [x,x] : x % 2 = 0 }" },
2255 	{ 1, "[n] -> { [1] : n >= 0;"
2256 		    "[x] : exists (e0 = floor((x)/2): x >= 2 and "
2257 			"2e0 >= -1 + x and 2e0 <= x and 2e0 <= n) }" },
2258 	{ 1, "[n] -> { [x, y] : exists (e0 = floor((x)/2), e1 = floor((y)/3): "
2259 			"3e1 = y and x >= 2 and 2e0 >= -1 + x and "
2260 			"2e0 <= x and 2e0 <= n);"
2261 		    "[1, y] : exists (e0 = floor((y)/3): 3e0 = y and "
2262 			"n >= 0) }" },
2263 	{ 1, "[t1] -> { [i0] : (exists (e0 = floor((63t1)/64): "
2264 				"128e0 >= -134 + 127t1 and t1 >= 2 and "
2265 				"64e0 <= 63t1 and 64e0 >= -63 + 63t1)) or "
2266 				"t1 = 1 }" },
2267 	{ 1, "{ [i, i] : exists (e0 = floor((1 + 2i)/3): 3e0 <= 2i and "
2268 				"3e0 >= -1 + 2i and i <= 9 and i >= 1);"
2269 		"[0, 0] }" },
2270 	{ 1, "{ [t1] : exists (e0 = floor((-11 + t1)/2): 2e0 = -11 + t1 and "
2271 				"t1 >= 13 and t1 <= 16);"
2272 		"[t1] : t1 <= 15 and t1 >= 12 }" },
2273 	{ 1, "{ [x,y] : x = 3y and 0 <= y <= 2; [-3,-1] }" },
2274 	{ 1, "{ [x,y] : 2x = 3y and 0 <= y <= 4; [-3,-2] }" },
2275 	{ 0, "{ [x,y] : 2x = 3y and 0 <= y <= 4; [-2,-2] }" },
2276 	{ 0, "{ [x,y] : 2x = 3y and 0 <= y <= 4; [-3,-1] }" },
2277 	{ 1, "{ [i] : exists j : i = 4 j and 0 <= i <= 100;"
2278 		"[i] : exists j : 1 <= i <= 100 and i >= 4j + 1 and "
2279 				"i <= 4j + 2 }" },
2280 	{ 1, "{ [c0] : (exists (e0 : c0 - 1 <= 3e0 <= c0)) or "
2281 		"(exists (e0 : 3e0 = -2 + c0)) }" },
2282 	{ 0, "[n, b0, t0] -> "
2283 		"{ [i0, i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11, i12] : "
2284 		"(exists (e0 = floor((-32b0 + i4)/1048576), "
2285 		"e1 = floor((i8)/32): 1048576e0 = -32b0 + i4 and 32e1 = i8 and "
2286 		"n <= 2147483647 and b0 <= 32767 and b0 >= 0 and "
2287 		"32b0 <= -2 + n and t0 <= 31 and t0 >= 0 and i0 >= 8 + n and "
2288 		"3i4 <= -96 + 3t0 + i0 and 3i4 >= -95 - n + 3t0 + i0 and "
2289 		"i8 >= -157 + i0 - 4i4 and i8 >= 0 and "
2290 		"i8 <= -33 + i0 - 4i4 and 3i8 <= -91 + 4n - i0)) or "
2291 		"(exists (e0 = floor((-32b0 + i4)/1048576), "
2292 		"e1 = floor((i8)/32): 1048576e0 = -32b0 + i4 and 32e1 = i8 and "
2293 		"n <= 2147483647 and b0 <= 32767 and b0 >= 0 and "
2294 		"32b0 <= -2 + n and t0 <= 31 and t0 >= 0 and i0 <= 7 + n and "
2295 		"4i4 <= -3 + i0 and 3i4 <= -96 + 3t0 + i0 and "
2296 		"3i4 >= -95 - n + 3t0 + i0 and i8 >= -157 + i0 - 4i4 and "
2297 		"i8 >= 0 and i8 <= -4 + i0 - 3i4 and i8 <= -41 + i0));"
2298 		"[i0, i1, i2, i3, 0, i5, i6, i7, i8, i9, i10, i11, i12] : "
2299 		"(exists (e0 = floor((i8)/32): b0 = 0 and 32e0 = i8 and "
2300 		"n <= 2147483647 and t0 <= 31 and t0 >= 0 and i0 >= 11 and "
2301 		"i0 >= 96 - 3t0 and i0 <= 95 + n - 3t0 and i0 <= 7 + n and "
2302 		"i8 >= -40 + i0 and i8 <= -10 + i0)) }" },
2303 	{ 0, "{ [i0, i1, i2] : "
2304 		"(exists (e0, e1 = floor((i0)/32), e2 = floor((i1)/32): "
2305 		"32e1 = i0 and 32e2 = i1 and i1 >= -31 + i0 and "
2306 		"i1 <= 31 + i0 and i2 >= -30 + i0 and i2 >= -30 + i1 and "
2307 		"32e0 >= -30 + i0 and 32e0 >= -30 + i1 and "
2308 		"32e0 >= -31 + i2 and 32e0 <= 30 + i2 and 32e0 <= 31 + i1 and "
2309 		"32e0 <= 31 + i0)) or "
2310 		"i0 >= 0 }" },
2311 	{ 1, "{ [a, b, c] : 2b = 1 + a and 2c = 2 + a; [0, 0, 0] }" },
2312 	{ 1, "{ [a, a, b, c] : 32*floor((a)/32) = a and 2*floor((b)/2) = b and "
2313 				"2*floor((c)/2) = c and 0 <= a <= 192;"
2314 		"[224, 224, b, c] : 2*floor((b)/2) = b and 2*floor((c)/2) = c }"
2315 	},
2316 	{ 1, "[n] -> { [a,b] : (exists e : 1 <= a <= 7e and 9e <= b <= n) or "
2317 				"(0 <= a <= b <= n) }" },
2318 	{ 1, "{ [a, b] : 0 <= a <= 2 and b >= 0 and "
2319 		"((0 < b <= 13) or (2*floor((a + b)/2) >= -5 + a + 2b)) }" },
2320 	{ 1, "{ [a] : (2 <= a <= 5) or (a mod 2 = 1 and 1 <= a <= 5) }" },
2321 	{ 1, "{ [a, b, c] : (b = -1 + a and 0 < a <= 3 and "
2322 				"9*floor((-4a + 2c)/9) <= -3 - 4a + 2c) or "
2323 			"(exists (e0 = floor((-16 + 2c)/9): a = 4 and "
2324 				"b = 3 and 9e0 <= -19 + 2c)) }" },
2325 	{ 1, "{ [a, b, c] : (b = -1 + a and 0 < a <= 3 and "
2326 				"9*floor((-4a + 2c)/9) <= -3 - 4a + 2c) or "
2327 			"(a = 4 and b = 3 and "
2328 				"9*floor((-16 + 2c)/9) <= -19 + 2c) }" },
2329 	{ 0, "{ [a, b, c] : (b <= 2 and b <= -2 + a) or "
2330 			"(b = -1 + a and 0 < a <= 3 and "
2331 				"9*floor((-4a + 2c)/9) <= -3 - 4a + 2c) or "
2332 			"(exists (e0 = floor((-16 + 2c)/9): a = 4 and "
2333 				"b = 3 and 9e0 <= -19 + 2c)) }" },
2334 	{ 1, "{ [y, x] : (x - y) mod 3 = 2 and 2 <= y <= 200 and 0 <= x <= 2;"
2335 		"[1, 0] }" },
2336 	{ 1, "{ [x, y] : (x - y) mod 3 = 2 and 2 <= y <= 200 and 0 <= x <= 2;"
2337 		"[0, 1] }" },
2338 	{ 1, "{ [1, y] : -1 <= y <= 1; [x, -x] : 0 <= x <= 1 }" },
2339 	{ 1, "{ [1, y] : 0 <= y <= 1; [x, -x] : 0 <= x <= 1 }" },
2340 	{ 1, "{ [x, y] : 0 <= x <= 10 and x - 4*floor(x/4) <= 1 and y <= 0; "
2341 	       "[x, y] : 0 <= x <= 10 and x - 4*floor(x/4) > 1 and y <= 0; "
2342 	       "[x, y] : 0 <= x <= 10 and x - 5*floor(x/5) <= 1 and 0 < y; "
2343 	       "[x, y] : 0 <= x <= 10 and x - 5*floor(x/5) > 1 and 0 < y }" },
2344 	{ 1, "{ [x, 0] : 0 <= x <= 10 and x mod 2 = 0; "
2345 	       "[x, 0] : 0 <= x <= 10 and x mod 2 = 1; "
2346 	       "[x, y] : 0 <= x <= 10 and 1 <= y <= 10 }" },
2347 	{ 1, "{ [a] : a <= 8 and "
2348 			"(a mod 10 = 7 or a mod 10 = 8 or a mod 10 = 9) }" },
2349 	{ 1, "{ [x, y] : 2y = -x and x <= 0 or "
2350 			"x <= -1 and 2y <= -x - 1 and 2y >= x - 1 }" },
2351 	{ 0, "{ [x, y] : 2y = -x and x <= 0 or "
2352 			"x <= -2 and 2y <= -x - 1 and 2y >= x - 1 }" },
2353 	{ 1, "{ [a] : (a <= 0 and 3*floor((a)/3) = a) or "
2354 			"(a < 0 and 3*floor((a)/3) < a) }" },
2355 	{ 1, "{ [a] : (a <= 0 and 3*floor((a)/3) = a) or "
2356 			"(a < -1 and 3*floor((a)/3) < a) }" },
2357 	{ 1, "{ [a, b] : a <= 1024 and b >= 0 and "
2358 		"((-31 - a + b <= 32*floor((-1 - a)/32) <= -33 + b and "
2359 		  "32*floor((-1 - a)/32) <= -16 + b + 16*floor((-1 - a)/16))"
2360 		"or (2 <= a <= 15 and b < a)) }" },
2361 	{ 1, "{ [a] : a > 0 and ((16*floor((a)/16) < a and "
2362 			"32*floor((a)/32) < a) or a <= 15) }" },
2363 	{ 1, "{ [a, b, c, d] : (-a + d) mod 64 = 0 and a <= 8 and b <= 1 and "
2364 			"10 - a <= c <= 3 and d >= 5 and 9 - 64b <= d <= 70;"
2365 	    "[a, b = 1, c, d] : (-a + d) mod 64 = 0 and a <= 8 and c >= 4 and "
2366 			"10 - a <= c <= 5 and 5 <= d <= 73 - c }" },
2367 	{ 1, "[n, m] -> { S_0[i] : (-n + i) mod 3 = 0 and m >= 3 + n and "
2368 			    "i >= n and 3*floor((2 + n + 2m)/3) <= n + 3m - i; "
2369 			 "S_0[n] : n <= m <= 2 + n }" },
2370 	{ 1, "{ [a, b] : exists (e0: 0 <= a <= 1 and b >= 0 and "
2371 			"2e0 >= -5 + a + 2b and 2e0 >= -1 + a + b and "
2372 			"2e0 <= a + b); "
2373 		"[a, b] : exists (e0: 0 <= a <= 1 and 2e0 >= -5 + a + 2b and "
2374 			"2e0 >= -1 - a + b and 2e0 <= -a + b and "
2375 			"2e0 < -a + 2b) }" },
2376 	{ 1, "{ [i, j, i - 8j] : 8 <= i <= 63 and -7 + i <= 8j <= i; "
2377 		"[i, 0, i] : 0 <= i <= 7 }" },
2378 	{ 1, "{ [a, b] : a >= 0 and 0 <= b <= 1 - a; [1, 1] }" },
2379 	{ 0, "{ [a, b] : a >= 0 and 0 <= b <= 1 - a; [0, 2] }" },
2380 	{ 0, "{ [a, b] : a >= 0 and 0 <= b <= 1 - a; [-1, 3] }" },
2381 	{ 1, "{ [a, b] : a, b >= 0 and a + 2b <= 2; [1, 1] }" },
2382 	{ 0, "{ [a, b] : a, b >= 0 and a + 2b <= 2; [2, 1] }" },
2383 	{ 0, "{ [a, c] : (2 + a) mod 4 = 0 or "
2384 		"(c = 4 + a and 4 * floor((a)/4) = a and a >= 0 and a <= 4) or "
2385 		"(c = 3 + a and 4 * floor((-1 + a)/4) = -1 + a and "
2386 		    "a > 0 and a <= 5) }" },
2387 	{ 1, "{ [1, 0, 0]; [a, b, c] : -1 <= -a < b <= 0 and 2c > b }" },
2388 	{ 0, "{ [j, a, l] : a mod 2 = 0 and j <= 29 and a >= 2 and "
2389 			"2a <= -5 + j and 32j + 2a + 2 <= 4l < 33j; "
2390 		"[j, 0, l] : 4 <= j <= 29 and -3 + 33j <= 4l <= 33j }" },
2391 	{ 0, "{ [0:1, 0:1]; [0, 2:3] }" },
2392 	{ 1, "{ [a] : (a = 0 or ((1 + a) mod 2 = 0 and 0 < a <= 15) or "
2393 		"((a) mod 2 = 0 and 0 < a <= 15)) }" },
2394 };
2395 
2396 /* A specialized coalescing test case that would result
2397  * in a segmentation fault or a failed assertion in earlier versions of isl.
2398  */
test_coalesce_special(struct isl_ctx * ctx)2399 static int test_coalesce_special(struct isl_ctx *ctx)
2400 {
2401 	const char *str;
2402 	isl_map *map1, *map2;
2403 
2404 	str = "[y] -> { [S_L220_OUT[] -> T7[]] -> "
2405 	    "[[S_L309_IN[] -> T11[]] -> ce_imag2[1, o1]] : "
2406 	    "(y = 201 and o1 <= 239 and o1 >= 212) or "
2407 	    "(exists (e0 = [(y)/3]: 3e0 = y and y <= 198 and y >= 3 and "
2408 		"o1 <= 239 and o1 >= 212)) or "
2409 	    "(exists (e0 = [(y)/3]: 3e0 = y and y <= 201 and y >= 3 and "
2410 		"o1 <= 241 and o1 >= 240));"
2411 	    "[S_L220_OUT[] -> T7[]] -> "
2412 	    "[[S_L309_IN[] -> T11[]] -> ce_imag2[0, o1]] : "
2413 	    "(y = 2 and o1 <= 241 and o1 >= 212) or "
2414 	    "(exists (e0 = [(-2 + y)/3]: 3e0 = -2 + y and y <= 200 and "
2415 		"y >= 5 and o1 <= 241 and o1 >= 212)) }";
2416 	map1 = isl_map_read_from_str(ctx, str);
2417 	map1 = isl_map_align_divs_internal(map1);
2418 	map1 = isl_map_coalesce(map1);
2419 	str = "[y] -> { [S_L220_OUT[] -> T7[]] -> "
2420 	    "[[S_L309_IN[] -> T11[]] -> ce_imag2[o0, o1]] : "
2421 	    "exists (e0 = [(-1 - y + o0)/3]: 3e0 = -1 - y + o0 and "
2422 		"y <= 201 and o0 <= 2 and o1 >= 212 and o1 <= 241 and "
2423 		"o0 >= 3 - y and o0 <= -2 + y and o0 >= 0) }";
2424 	map2 = isl_map_read_from_str(ctx, str);
2425 	map2 = isl_map_union(map2, map1);
2426 	map2 = isl_map_align_divs_internal(map2);
2427 	map2 = isl_map_coalesce(map2);
2428 	isl_map_free(map2);
2429 	if (!map2)
2430 		return -1;
2431 
2432 	return 0;
2433 }
2434 
2435 /* A specialized coalescing test case that would result in an assertion
2436  * in an earlier version of isl.
2437  * The explicit call to isl_basic_set_union prevents the implicit
2438  * equality constraints in the first basic map from being detected prior
2439  * to the call to isl_set_coalesce, at least at the point
2440  * where this test case was introduced.
2441  */
test_coalesce_special2(struct isl_ctx * ctx)2442 static int test_coalesce_special2(struct isl_ctx *ctx)
2443 {
2444 	const char *str;
2445 	isl_basic_set *bset1, *bset2;
2446 	isl_set *set;
2447 
2448 	str = "{ [x, y] : x, y >= 0 and x + 2y <= 1 and 2x + y <= 1 }";
2449 	bset1 = isl_basic_set_read_from_str(ctx, str);
2450 	str = "{ [x,0] : -1 <= x <= 1 and x mod 2 = 1 }" ;
2451 	bset2 = isl_basic_set_read_from_str(ctx, str);
2452 	set = isl_basic_set_union(bset1, bset2);
2453 	set = isl_set_coalesce(set);
2454 	isl_set_free(set);
2455 
2456 	if (!set)
2457 		return -1;
2458 	return 0;
2459 }
2460 
2461 /* Check that calling isl_set_coalesce does not leave other sets
2462  * that may share some information with the input to isl_set_coalesce
2463  * in an inconsistent state.
2464  * In particular, older versions of isl would modify all copies
2465  * of the basic sets in the isl_set_coalesce input in a way
2466  * that could leave them in an inconsistent state.
2467  * The result of printing any other set containing one of these
2468  * basic sets would then result in an invalid set description.
2469  */
test_coalesce_special3(isl_ctx * ctx)2470 static int test_coalesce_special3(isl_ctx *ctx)
2471 {
2472 	const char *str;
2473 	char *s;
2474 	isl_set *set1, *set2;
2475 	isl_printer *p;
2476 
2477 	set1 = isl_set_read_from_str(ctx, "{ [0, 0, 0] }");
2478 	str = "{ [a, b, a + b] : a >= 0 and b >= 0 and 0 < a + b }";
2479 	set2 = isl_set_read_from_str(ctx, str);
2480 	set1 = isl_set_union(set1, isl_set_copy(set2));
2481 	set1 = isl_set_coalesce(set1);
2482 	isl_set_free(set1);
2483 
2484 	p = isl_printer_to_str(ctx);
2485 	p = isl_printer_print_set(p, set2);
2486 	isl_set_free(set2);
2487 	s = isl_printer_get_str(p);
2488 	isl_printer_free(p);
2489 	set1 = isl_set_read_from_str(ctx, s);
2490 	free(s);
2491 	isl_set_free(set1);
2492 
2493 	if (!set1)
2494 		return -1;
2495 
2496 	return 0;
2497 }
2498 
2499 /* Check that calling isl_set_coalesce on the intersection of
2500  * the sets described by "s1" and "s2" does not leave other sets
2501  * that may share some information with the input to isl_set_coalesce
2502  * in an inconsistent state.
2503  * In particular, when isl_set_coalesce detects equality constraints,
2504  * it does not immediately perform Gaussian elimination on them,
2505  * but then it needs to ensure that it is performed at some point.
2506  * The input set has implicit equality constraints in the first disjunct.
2507  * It is constructed as an intersection, because otherwise
2508  * those equality constraints would already be detected during parsing.
2509  */
test_coalesce_intersection(isl_ctx * ctx,const char * s1,const char * s2)2510 static isl_stat test_coalesce_intersection(isl_ctx *ctx,
2511 	const char *s1, const char *s2)
2512 {
2513 	isl_set *set1, *set2;
2514 
2515 	set1 = isl_set_read_from_str(ctx, s1);
2516 	set2 = isl_set_read_from_str(ctx, s2);
2517 	set1 = isl_set_intersect(set1, set2);
2518 	isl_set_free(isl_set_coalesce(isl_set_copy(set1)));
2519 	set1 = isl_set_coalesce(set1);
2520 	isl_set_free(set1);
2521 
2522 	if (!set1)
2523 		return isl_stat_error;
2524 
2525 	return isl_stat_ok;
2526 }
2527 
2528 /* Check that calling isl_set_coalesce does not leave other sets
2529  * that may share some information with the input to isl_set_coalesce
2530  * in an inconsistent state, for the case where one disjunct
2531  * is a subset of the other.
2532  */
test_coalesce_special4(isl_ctx * ctx)2533 static isl_stat test_coalesce_special4(isl_ctx *ctx)
2534 {
2535 	const char *s1, *s2;
2536 
2537 	s1 = "{ [a, b] : b <= 0 or a <= 1 }";
2538 	s2 = "{ [a, b] : -1 <= -a < b }";
2539 	return test_coalesce_intersection(ctx, s1, s2);
2540 }
2541 
2542 /* Check that calling isl_set_coalesce does not leave other sets
2543  * that may share some information with the input to isl_set_coalesce
2544  * in an inconsistent state, for the case where two disjuncts
2545  * can be fused.
2546  */
test_coalesce_special5(isl_ctx * ctx)2547 static isl_stat test_coalesce_special5(isl_ctx *ctx)
2548 {
2549 	const char *s1, *s2;
2550 
2551 	s1 = "{ [a, b, c] : b <= 0 }";
2552 	s2 = "{ [a, b, c] : -1 <= -a < b and (c >= 0 or c < 0) }";
2553 	return test_coalesce_intersection(ctx, s1, s2);
2554 }
2555 
2556 /* Check that calling isl_set_coalesce does not leave other sets
2557  * that may share some information with the input to isl_set_coalesce
2558  * in an inconsistent state, for the case where two disjuncts
2559  * can be fused and where both disjuncts have implicit equality constraints.
2560  */
test_coalesce_special6(isl_ctx * ctx)2561 static isl_stat test_coalesce_special6(isl_ctx *ctx)
2562 {
2563 	const char *s1, *s2;
2564 
2565 	s1 = "{ [a, b, c] : c <= 0 }";
2566 	s2 = "{ [a, b, c] : 0 <= a <= b <= c or (0 <= b <= c and a > 0) }";
2567 	return test_coalesce_intersection(ctx, s1, s2);
2568 }
2569 
2570 /* Test the functionality of isl_set_coalesce.
2571  * That is, check that the output is always equal to the input
2572  * and in some cases that the result consists of a single disjunct.
2573  */
test_coalesce(struct isl_ctx * ctx)2574 static int test_coalesce(struct isl_ctx *ctx)
2575 {
2576 	int i;
2577 
2578 	for (i = 0; i < ARRAY_SIZE(coalesce_tests); ++i) {
2579 		const char *str = coalesce_tests[i].str;
2580 		int check_one = coalesce_tests[i].single_disjunct;
2581 		if (test_coalesce_set(ctx, str, check_one) < 0)
2582 			return -1;
2583 	}
2584 
2585 	if (test_coalesce_unbounded_wrapping(ctx) < 0)
2586 		return -1;
2587 	if (test_coalesce_special(ctx) < 0)
2588 		return -1;
2589 	if (test_coalesce_special2(ctx) < 0)
2590 		return -1;
2591 	if (test_coalesce_special3(ctx) < 0)
2592 		return -1;
2593 	if (test_coalesce_special4(ctx) < 0)
2594 		return -1;
2595 	if (test_coalesce_special5(ctx) < 0)
2596 		return -1;
2597 	if (test_coalesce_special6(ctx) < 0)
2598 		return -1;
2599 
2600 
2601 	return 0;
2602 }
2603 
2604 /* Construct a representation of the graph on the right of Figure 1
2605  * in "Computing the Transitive Closure of a Union of
2606  * Affine Integer Tuple Relations".
2607  */
cocoa_fig_1_right_graph(isl_ctx * ctx)2608 static __isl_give isl_map *cocoa_fig_1_right_graph(isl_ctx *ctx)
2609 {
2610 	isl_set *dom;
2611 	isl_map *up, *right;
2612 
2613 	dom = isl_set_read_from_str(ctx,
2614 		"{ [x,y] : x >= 0 and -2 x + 3 y >= 0 and x <= 3 and "
2615 			"2 x - 3 y + 3 >= 0 }");
2616 	right = isl_map_read_from_str(ctx,
2617 		"{ [x,y] -> [x2,y2] : x2 = x + 1 and y2 = y }");
2618 	up = isl_map_read_from_str(ctx,
2619 		"{ [x,y] -> [x2,y2] : x2 = x and y2 = y + 1 }");
2620 	right = isl_map_intersect_domain(right, isl_set_copy(dom));
2621 	right = isl_map_intersect_range(right, isl_set_copy(dom));
2622 	up = isl_map_intersect_domain(up, isl_set_copy(dom));
2623 	up = isl_map_intersect_range(up, dom);
2624 	return isl_map_union(up, right);
2625 }
2626 
2627 /* Construct a representation of the power of the graph
2628  * on the right of Figure 1 in "Computing the Transitive Closure of
2629  * a Union of Affine Integer Tuple Relations".
2630  */
cocoa_fig_1_right_power(isl_ctx * ctx)2631 static __isl_give isl_map *cocoa_fig_1_right_power(isl_ctx *ctx)
2632 {
2633 	return isl_map_read_from_str(ctx,
2634 		"{ [1] -> [[0,0] -> [0,1]]; [2] -> [[0,0] -> [1,1]]; "
2635 		"  [1] -> [[0,1] -> [1,1]]; [1] -> [[2,2] -> [3,2]]; "
2636 		"  [2] -> [[2,2] -> [3,3]]; [1] -> [[3,2] -> [3,3]] }");
2637 }
2638 
2639 /* Construct a representation of the transitive closure of the graph
2640  * on the right of Figure 1 in "Computing the Transitive Closure of
2641  * a Union of Affine Integer Tuple Relations".
2642  */
cocoa_fig_1_right_tc(isl_ctx * ctx)2643 static __isl_give isl_map *cocoa_fig_1_right_tc(isl_ctx *ctx)
2644 {
2645 	return isl_set_unwrap(isl_map_range(cocoa_fig_1_right_power(ctx)));
2646 }
2647 
test_closure(isl_ctx * ctx)2648 static int test_closure(isl_ctx *ctx)
2649 {
2650 	const char *str;
2651 	isl_map *map, *map2;
2652 	isl_bool exact, equal;
2653 
2654 	/* COCOA example 1 */
2655 	map = isl_map_read_from_str(ctx,
2656 		"[n] -> { [i,j] -> [i2,j2] : i2 = i + 1 and j2 = j + 1 and "
2657 			"1 <= i and i < n and 1 <= j and j < n or "
2658 			"i2 = i + 1 and j2 = j - 1 and "
2659 			"1 <= i and i < n and 2 <= j and j <= n }");
2660 	map = isl_map_power(map, &exact);
2661 	assert(exact);
2662 	isl_map_free(map);
2663 
2664 	/* COCOA example 1 */
2665 	map = isl_map_read_from_str(ctx,
2666 		"[n] -> { [i,j] -> [i2,j2] : i2 = i + 1 and j2 = j + 1 and "
2667 			"1 <= i and i < n and 1 <= j and j < n or "
2668 			"i2 = i + 1 and j2 = j - 1 and "
2669 			"1 <= i and i < n and 2 <= j and j <= n }");
2670 	map = isl_map_transitive_closure(map, &exact);
2671 	assert(exact);
2672 	map2 = isl_map_read_from_str(ctx,
2673 		"[n] -> { [i,j] -> [i2,j2] : exists (k1,k2,k : "
2674 			"1 <= i and i < n and 1 <= j and j <= n and "
2675 			"2 <= i2 and i2 <= n and 1 <= j2 and j2 <= n and "
2676 			"i2 = i + k1 + k2 and j2 = j + k1 - k2 and "
2677 			"k1 >= 0 and k2 >= 0 and k1 + k2 = k and k >= 1 )}");
2678 	assert(isl_map_is_equal(map, map2));
2679 	isl_map_free(map2);
2680 	isl_map_free(map);
2681 
2682 	map = isl_map_read_from_str(ctx,
2683 		"[n] -> { [x] -> [y] : y = x + 1 and 0 <= x and x <= n and "
2684 				     " 0 <= y and y <= n }");
2685 	map = isl_map_transitive_closure(map, &exact);
2686 	map2 = isl_map_read_from_str(ctx,
2687 		"[n] -> { [x] -> [y] : y > x and 0 <= x and x <= n and "
2688 				     " 0 <= y and y <= n }");
2689 	assert(isl_map_is_equal(map, map2));
2690 	isl_map_free(map2);
2691 	isl_map_free(map);
2692 
2693 	/* COCOA example 2 */
2694 	map = isl_map_read_from_str(ctx,
2695 		"[n] -> { [i,j] -> [i2,j2] : i2 = i + 2 and j2 = j + 2 and "
2696 			"1 <= i and i < n - 1 and 1 <= j and j < n - 1 or "
2697 			"i2 = i + 2 and j2 = j - 2 and "
2698 			"1 <= i and i < n - 1 and 3 <= j and j <= n }");
2699 	map = isl_map_transitive_closure(map, &exact);
2700 	assert(exact);
2701 	map2 = isl_map_read_from_str(ctx,
2702 		"[n] -> { [i,j] -> [i2,j2] : exists (k1,k2,k : "
2703 			"1 <= i and i < n - 1 and 1 <= j and j <= n and "
2704 			"3 <= i2 and i2 <= n and 1 <= j2 and j2 <= n and "
2705 			"i2 = i + 2 k1 + 2 k2 and j2 = j + 2 k1 - 2 k2 and "
2706 			"k1 >= 0 and k2 >= 0 and k1 + k2 = k and k >= 1) }");
2707 	assert(isl_map_is_equal(map, map2));
2708 	isl_map_free(map);
2709 	isl_map_free(map2);
2710 
2711 	/* COCOA Fig.2 left */
2712 	map = isl_map_read_from_str(ctx,
2713 		"[n] -> { [i,j] -> [i2,j2] : i2 = i + 2 and j2 = j and "
2714 			"i <= 2 j - 3 and i <= n - 2 and j <= 2 i - 1 and "
2715 			"j <= n or "
2716 			"i2 = i and j2 = j + 2 and i <= 2 j - 1 and i <= n and "
2717 			"j <= 2 i - 3 and j <= n - 2 or "
2718 			"i2 = i + 1 and j2 = j + 1 and i <= 2 j - 1 and "
2719 			"i <= n - 1 and j <= 2 i - 1 and j <= n - 1 }");
2720 	map = isl_map_transitive_closure(map, &exact);
2721 	assert(exact);
2722 	isl_map_free(map);
2723 
2724 	/* COCOA Fig.2 right */
2725 	map = isl_map_read_from_str(ctx,
2726 		"[n] -> { [i,j] -> [i2,j2] : i2 = i + 3 and j2 = j and "
2727 			"i <= 2 j - 4 and i <= n - 3 and j <= 2 i - 1 and "
2728 			"j <= n or "
2729 			"i2 = i and j2 = j + 3 and i <= 2 j - 1 and i <= n and "
2730 			"j <= 2 i - 4 and j <= n - 3 or "
2731 			"i2 = i + 1 and j2 = j + 1 and i <= 2 j - 1 and "
2732 			"i <= n - 1 and j <= 2 i - 1 and j <= n - 1 }");
2733 	map = isl_map_power(map, &exact);
2734 	assert(exact);
2735 	isl_map_free(map);
2736 
2737 	/* COCOA Fig.2 right */
2738 	map = isl_map_read_from_str(ctx,
2739 		"[n] -> { [i,j] -> [i2,j2] : i2 = i + 3 and j2 = j and "
2740 			"i <= 2 j - 4 and i <= n - 3 and j <= 2 i - 1 and "
2741 			"j <= n or "
2742 			"i2 = i and j2 = j + 3 and i <= 2 j - 1 and i <= n and "
2743 			"j <= 2 i - 4 and j <= n - 3 or "
2744 			"i2 = i + 1 and j2 = j + 1 and i <= 2 j - 1 and "
2745 			"i <= n - 1 and j <= 2 i - 1 and j <= n - 1 }");
2746 	map = isl_map_transitive_closure(map, &exact);
2747 	assert(exact);
2748 	map2 = isl_map_read_from_str(ctx,
2749 		"[n] -> { [i,j] -> [i2,j2] : exists (k1,k2,k3,k : "
2750 			"i <= 2 j - 1 and i <= n and j <= 2 i - 1 and "
2751 			"j <= n and 3 + i + 2 j <= 3 n and "
2752 			"3 + 2 i + j <= 3n and i2 <= 2 j2 -1 and i2 <= n and "
2753 			"i2 <= 3 j2 - 4 and j2 <= 2 i2 -1 and j2 <= n and "
2754 			"13 + 4 j2 <= 11 i2 and i2 = i + 3 k1 + k3 and "
2755 			"j2 = j + 3 k2 + k3 and k1 >= 0 and k2 >= 0 and "
2756 			"k3 >= 0 and k1 + k2 + k3 = k and k > 0) }");
2757 	assert(isl_map_is_equal(map, map2));
2758 	isl_map_free(map2);
2759 	isl_map_free(map);
2760 
2761 	map = cocoa_fig_1_right_graph(ctx);
2762 	map = isl_map_transitive_closure(map, &exact);
2763 	assert(exact);
2764 	map2 = cocoa_fig_1_right_tc(ctx);
2765 	assert(isl_map_is_equal(map, map2));
2766 	isl_map_free(map2);
2767 	isl_map_free(map);
2768 
2769 	map = cocoa_fig_1_right_graph(ctx);
2770 	map = isl_map_power(map, &exact);
2771 	map2 = cocoa_fig_1_right_power(ctx);
2772 	equal = isl_map_is_equal(map, map2);
2773 	isl_map_free(map2);
2774 	isl_map_free(map);
2775 	if (equal < 0)
2776 		return -1;
2777 	if (!exact)
2778 		isl_die(ctx, isl_error_unknown, "power not exact", return -1);
2779 	if (!equal)
2780 		isl_die(ctx, isl_error_unknown, "unexpected power", return -1);
2781 
2782 	/* COCOA Theorem 1 counter example */
2783 	map = isl_map_read_from_str(ctx,
2784 		"{ [i,j] -> [i2,j2] : i = 0 and 0 <= j and j <= 1 and "
2785 			"i2 = 1 and j2 = j or "
2786 			"i = 0 and j = 0 and i2 = 0 and j2 = 1 }");
2787 	map = isl_map_transitive_closure(map, &exact);
2788 	assert(exact);
2789 	isl_map_free(map);
2790 
2791 	map = isl_map_read_from_str(ctx,
2792 		"[m,n] -> { [i,j] -> [i2,j2] : i2 = i and j2 = j + 2 and "
2793 			"1 <= i,i2 <= n and 1 <= j,j2 <= m or "
2794 			"i2 = i + 1 and 3 <= j2 - j <= 4 and "
2795 			"1 <= i,i2 <= n and 1 <= j,j2 <= m }");
2796 	map = isl_map_transitive_closure(map, &exact);
2797 	assert(exact);
2798 	isl_map_free(map);
2799 
2800 	/* Kelly et al 1996, fig 12 */
2801 	map = isl_map_read_from_str(ctx,
2802 		"[n] -> { [i,j] -> [i2,j2] : i2 = i and j2 = j + 1 and "
2803 			"1 <= i,j,j+1 <= n or "
2804 			"j = n and j2 = 1 and i2 = i + 1 and "
2805 			"1 <= i,i+1 <= n }");
2806 	map = isl_map_transitive_closure(map, &exact);
2807 	assert(exact);
2808 	map2 = isl_map_read_from_str(ctx,
2809 		"[n] -> { [i,j] -> [i2,j2] : 1 <= j < j2 <= n and "
2810 			"1 <= i <= n and i = i2 or "
2811 			"1 <= i < i2 <= n and 1 <= j <= n and "
2812 			"1 <= j2 <= n }");
2813 	assert(isl_map_is_equal(map, map2));
2814 	isl_map_free(map2);
2815 	isl_map_free(map);
2816 
2817 	/* Omega's closure4 */
2818 	map = isl_map_read_from_str(ctx,
2819 		"[m,n] -> { [x,y] -> [x2,y2] : x2 = x and y2 = y + 1 and "
2820 			"1 <= x,y <= 10 or "
2821 			"x2 = x + 1 and y2 = y and "
2822 			"1 <= x <= 20 && 5 <= y <= 15 }");
2823 	map = isl_map_transitive_closure(map, &exact);
2824 	assert(exact);
2825 	isl_map_free(map);
2826 
2827 	map = isl_map_read_from_str(ctx,
2828 		"[n] -> { [x] -> [y]: 1 <= n <= y - x <= 10 }");
2829 	map = isl_map_transitive_closure(map, &exact);
2830 	assert(!exact);
2831 	map2 = isl_map_read_from_str(ctx,
2832 		"[n] -> { [x] -> [y] : 1 <= n <= 10 and y >= n + x }");
2833 	assert(isl_map_is_equal(map, map2));
2834 	isl_map_free(map);
2835 	isl_map_free(map2);
2836 
2837 	str = "[n, m] -> { [i0, i1, i2, i3] -> [o0, o1, o2, o3] : "
2838 	    "i3 = 1 and o0 = i0 and o1 = -1 + i1 and o2 = -1 + i2 and "
2839 	    "o3 = -2 + i2 and i1 <= -1 + i0 and i1 >= 1 - m + i0 and "
2840 	    "i1 >= 2 and i1 <= n and i2 >= 3 and i2 <= 1 + n and i2 <= m }";
2841 	map = isl_map_read_from_str(ctx, str);
2842 	map = isl_map_transitive_closure(map, &exact);
2843 	assert(exact);
2844 	map2 = isl_map_read_from_str(ctx, str);
2845 	assert(isl_map_is_equal(map, map2));
2846 	isl_map_free(map);
2847 	isl_map_free(map2);
2848 
2849 	str = "{[0] -> [1]; [2] -> [3]}";
2850 	map = isl_map_read_from_str(ctx, str);
2851 	map = isl_map_transitive_closure(map, &exact);
2852 	assert(exact);
2853 	map2 = isl_map_read_from_str(ctx, str);
2854 	assert(isl_map_is_equal(map, map2));
2855 	isl_map_free(map);
2856 	isl_map_free(map2);
2857 
2858 	str = "[n] -> { [[i0, i1, 1, 0, i0] -> [i5, 1]] -> "
2859 	    "[[i0, -1 + i1, 2, 0, i0] -> [-1 + i5, 2]] : "
2860 	    "exists (e0 = [(3 - n)/3]: i5 >= 2 and i1 >= 2 and "
2861 	    "3i0 <= -1 + n and i1 <= -1 + n and i5 <= -1 + n and "
2862 	    "3e0 >= 1 - n and 3e0 <= 2 - n and 3i0 >= -2 + n); "
2863 	    "[[i0, i1, 2, 0, i0] -> [i5, 1]] -> "
2864 	    "[[i0, i1, 1, 0, i0] -> [-1 + i5, 2]] : "
2865 	    "exists (e0 = [(3 - n)/3]: i5 >= 2 and i1 >= 1 and "
2866 	    "3i0 <= -1 + n and i1 <= -1 + n and i5 <= -1 + n and "
2867 	    "3e0 >= 1 - n and 3e0 <= 2 - n and 3i0 >= -2 + n); "
2868 	    "[[i0, i1, 1, 0, i0] -> [i5, 2]] -> "
2869 	    "[[i0, -1 + i1, 2, 0, i0] -> [i5, 1]] : "
2870 	    "exists (e0 = [(3 - n)/3]: i1 >= 2 and i5 >= 1 and "
2871 	    "3i0 <= -1 + n and i1 <= -1 + n and i5 <= -1 + n and "
2872 	    "3e0 >= 1 - n and 3e0 <= 2 - n and 3i0 >= -2 + n); "
2873 	    "[[i0, i1, 2, 0, i0] -> [i5, 2]] -> "
2874 	    "[[i0, i1, 1, 0, i0] -> [i5, 1]] : "
2875 	    "exists (e0 = [(3 - n)/3]: i5 >= 1 and i1 >= 1 and "
2876 	    "3i0 <= -1 + n and i1 <= -1 + n and i5 <= -1 + n and "
2877 	    "3e0 >= 1 - n and 3e0 <= 2 - n and 3i0 >= -2 + n) }";
2878 	map = isl_map_read_from_str(ctx, str);
2879 	map = isl_map_transitive_closure(map, NULL);
2880 	assert(map);
2881 	isl_map_free(map);
2882 
2883 	return 0;
2884 }
2885 
2886 /* Check that the actual result of a boolean operation is equal
2887  * to the expected result.
2888  */
check_bool(isl_ctx * ctx,isl_bool actual,isl_bool expected)2889 static isl_stat check_bool(isl_ctx *ctx, isl_bool actual, isl_bool expected)
2890 {
2891 	if (actual != expected)
2892 		isl_die(ctx, isl_error_unknown,
2893 			"incorrect boolean operation", return isl_stat_error);
2894 	return isl_stat_ok;
2895 }
2896 
2897 /* Test operations on isl_bool values.
2898  *
2899  * This tests:
2900  *
2901  * 	isl_bool_not
2902  * 	isl_bool_ok
2903  */
test_isl_bool(isl_ctx * ctx)2904 static int test_isl_bool(isl_ctx *ctx)
2905 {
2906 	if (check_bool(ctx, isl_bool_not(isl_bool_true), isl_bool_false) < 0)
2907 		return -1;
2908 	if (check_bool(ctx, isl_bool_not(isl_bool_false), isl_bool_true) < 0)
2909 		return -1;
2910 	if (check_bool(ctx, isl_bool_not(isl_bool_error), isl_bool_error) < 0)
2911 		return -1;
2912 	if (check_bool(ctx, isl_bool_ok(0), isl_bool_false) < 0)
2913 		return -1;
2914 	if (check_bool(ctx, isl_bool_ok(1), isl_bool_true) < 0)
2915 		return -1;
2916 	if (check_bool(ctx, isl_bool_ok(-1), isl_bool_true) < 0)
2917 		return -1;
2918 	if (check_bool(ctx, isl_bool_ok(2), isl_bool_true) < 0)
2919 		return -1;
2920 	if (check_bool(ctx, isl_bool_ok(-2), isl_bool_true) < 0)
2921 		return -1;
2922 
2923 	return 0;
2924 }
2925 
test_lex(struct isl_ctx * ctx)2926 static int test_lex(struct isl_ctx *ctx)
2927 {
2928 	isl_space *space;
2929 	isl_map *map;
2930 	int empty;
2931 
2932 	space = isl_space_set_alloc(ctx, 0, 0);
2933 	map = isl_map_lex_le(space);
2934 	empty = isl_map_is_empty(map);
2935 	isl_map_free(map);
2936 
2937 	if (empty < 0)
2938 		return -1;
2939 	if (empty)
2940 		isl_die(ctx, isl_error_unknown,
2941 			"expecting non-empty result", return -1);
2942 
2943 	return 0;
2944 }
2945 
2946 /* Inputs for isl_map_lexmin tests.
2947  * "map" is the input and "lexmin" is the expected result.
2948  */
2949 struct {
2950 	const char *map;
2951 	const char *lexmin;
2952 } lexmin_tests [] = {
2953 	{ "{ [x] -> [y] : x <= y <= 10; [x] -> [5] : -8 <= x <= 8 }",
2954 	  "{ [x] -> [5] : 6 <= x <= 8; "
2955 	    "[x] -> [x] : x <= 5 or (9 <= x <= 10) }" },
2956 	{ "{ [x] -> [y] : 4y = x or 4y = -1 + x or 4y = -2 + x }",
2957 	  "{ [x] -> [y] : 4y = x or 4y = -1 + x or 4y = -2 + x }" },
2958 	{ "{ [x] -> [y] : x = 4y; [x] -> [y] : x = 2y }",
2959 	  "{ [x] -> [y] : (4y = x and x >= 0) or "
2960 		"(exists (e0 = [(x)/4], e1 = [(-2 + x)/4]: 2y = x and "
2961 		"4e1 = -2 + x and 4e0 <= -1 + x and 4e0 >= -3 + x)) or "
2962 		"(exists (e0 = [(x)/4]: 2y = x and 4e0 = x and x <= -4)) }" },
2963 	{ "{ T[a] -> S[b, c] : a = 4b-2c and c >= b }",
2964 	  "{ T[a] -> S[b, c] : 2b = a and 2c = a }" },
2965 	/* Check that empty pieces are properly combined. */
2966 	{ "[K, N] -> { [x, y] -> [a, b] : K+2<=N<=K+4 and x>=4 and "
2967 		"2N-6<=x<K+N and N-1<=a<=K+N-1 and N+b-6<=a<=2N-4 and "
2968 		"b<=2N-3K+a and 3b<=4N-K+1 and b>=N and a>=x+1 }",
2969 	  "[K, N] -> { [x, y] -> [1 + x, N] : x >= -6 + 2N and "
2970 		"x <= -5 + 2N and x >= -1 + 3K - N and x <= -2 + K + N and "
2971 		"x >= 4 }" },
2972 	{ "{ [i, k, j] -> [a, b, c, d] : 8*floor((b)/8) = b and k <= 255 and "
2973 		"a <= 255 and c <= 255 and d <= 255 - j and "
2974 		"255 - j <= 7d <= 7 - i and 240d <= 239 + a and "
2975 		"247d <= 247 + k - j and 247d <= 247 + k - b and "
2976 		"247d <= 247 + i and 248 - b <= 248d <= c and "
2977 		"254d >= i - a + b and 254d >= -a + b and "
2978 		"255d >= -i + a - b and 1792d >= -63736 + 257b }",
2979 	  "{ [i, k, j] -> "
2980 	    "[-127762 + i + 502j, -62992 + 248j, 63240 - 248j, 255 - j] : "
2981 		"k <= 255 and 7j >= 1778 + i and 246j >= 62738 - k and "
2982 		"247j >= 62738 - i and 509j <= 129795 + i and "
2983 		"742j >= 188724 - i; "
2984 	    "[0, k, j] -> [1, 0, 248, 1] : k <= 255 and 248 <= j <= 254, k }" },
2985 	{ "{ [a] -> [b] : 0 <= b <= 255 and -509 + a <= 512b < a and "
2986 			"16*floor((8 + b)/16) <= 7 + b; "
2987 	    "[a] -> [1] }",
2988 	  "{ [a] -> [b = 1] : a >= 510 or a <= 0; "
2989 	    "[a] -> [b = 0] : 0 < a <= 509 }" },
2990 	{ "{ rat: [i] : 1 <= 2i <= 9 }", "{ rat: [i] : 2i = 1 }" },
2991 	{ "{ rat: [i] : 1 <= 2i <= 9 or i >= 10 }", "{ rat: [i] : 2i = 1 }" },
2992 	{ "{ rat: [i] : 21 <= 2i <= 29 or i = 5 }", "{ rat: [5] }" },
2993 };
2994 
test_lexmin(struct isl_ctx * ctx)2995 static int test_lexmin(struct isl_ctx *ctx)
2996 {
2997 	int i;
2998 	int equal;
2999 	const char *str;
3000 	isl_basic_map *bmap;
3001 	isl_map *map, *map2;
3002 	isl_set *set;
3003 	isl_set *set2;
3004 	isl_pw_multi_aff *pma;
3005 
3006 	str = "[p0, p1] -> { [] -> [] : "
3007 	    "exists (e0 = [(2p1)/3], e1, e2, e3 = [(3 - p1 + 3e0)/3], "
3008 	    "e4 = [(p1)/3], e5 = [(p1 + 3e4)/3]: "
3009 	    "3e0 >= -2 + 2p1 and 3e0 >= p1 and 3e3 >= 1 - p1 + 3e0 and "
3010 	    "3e0 <= 2p1 and 3e3 >= -2 + p1 and 3e3 <= -1 + p1 and p1 >= 3 and "
3011 	    "3e5 >= -2 + 2p1 and 3e5 >= p1 and 3e5 <= -1 + p1 + 3e4 and "
3012 	    "3e4 <= p1 and 3e4 >= -2 + p1 and e3 <= -1 + e0 and "
3013 	    "3e4 >= 6 - p1 + 3e1 and 3e1 >= p1 and 3e5 >= -2 + p1 + 3e4 and "
3014 	    "2e4 >= 3 - p1 + 2e1 and e4 <= e1 and 3e3 <= 2 - p1 + 3e0 and "
3015 	    "e5 >= 1 + e1 and 3e4 >= 6 - 2p1 + 3e1 and "
3016 	    "p0 >= 2 and p1 >= p0 and 3e2 >= p1 and 3e4 >= 6 - p1 + 3e2 and "
3017 	    "e2 <= e1 and e3 >= 1 and e4 <= e2) }";
3018 	map = isl_map_read_from_str(ctx, str);
3019 	map = isl_map_lexmin(map);
3020 	isl_map_free(map);
3021 	if (!map)
3022 		return -1;
3023 
3024 	str = "[C] -> { [obj,a,b,c] : obj <= 38 a + 7 b + 10 c and "
3025 	    "a + b <= 1 and c <= 10 b and c <= C and a,b,c,C >= 0 }";
3026 	set = isl_set_read_from_str(ctx, str);
3027 	set = isl_set_lexmax(set);
3028 	str = "[C] -> { [obj,a,b,c] : C = 8 }";
3029 	set2 = isl_set_read_from_str(ctx, str);
3030 	set = isl_set_intersect(set, set2);
3031 	assert(!isl_set_is_empty(set));
3032 	isl_set_free(set);
3033 
3034 	for (i = 0; i < ARRAY_SIZE(lexmin_tests); ++i) {
3035 		map = isl_map_read_from_str(ctx, lexmin_tests[i].map);
3036 		map = isl_map_lexmin(map);
3037 		map2 = isl_map_read_from_str(ctx, lexmin_tests[i].lexmin);
3038 		equal = isl_map_is_equal(map, map2);
3039 		isl_map_free(map);
3040 		isl_map_free(map2);
3041 
3042 		if (equal < 0)
3043 			return -1;
3044 		if (!equal)
3045 			isl_die(ctx, isl_error_unknown,
3046 				"unexpected result", return -1);
3047 	}
3048 
3049 	str = "{ [i] -> [i', j] : j = i - 8i' and i' >= 0 and i' <= 7 and "
3050 				" 8i' <= i and 8i' >= -7 + i }";
3051 	bmap = isl_basic_map_read_from_str(ctx, str);
3052 	pma = isl_basic_map_lexmin_pw_multi_aff(isl_basic_map_copy(bmap));
3053 	map2 = isl_map_from_pw_multi_aff(pma);
3054 	map = isl_map_from_basic_map(bmap);
3055 	assert(isl_map_is_equal(map, map2));
3056 	isl_map_free(map);
3057 	isl_map_free(map2);
3058 
3059 	str = "[i] -> { [i', j] : j = i - 8i' and i' >= 0 and i' <= 7 and "
3060 				" 8i' <= i and 8i' >= -7 + i }";
3061 	set = isl_set_read_from_str(ctx, str);
3062 	pma = isl_set_lexmin_pw_multi_aff(isl_set_copy(set));
3063 	set2 = isl_set_from_pw_multi_aff(pma);
3064 	equal = isl_set_is_equal(set, set2);
3065 	isl_set_free(set);
3066 	isl_set_free(set2);
3067 	if (equal < 0)
3068 		return -1;
3069 	if (!equal)
3070 		isl_die(ctx, isl_error_unknown,
3071 			"unexpected difference between set and "
3072 			"piecewise affine expression", return -1);
3073 
3074 	return 0;
3075 }
3076 
3077 /* Inputs for isl_pw_multi_aff_max_multi_val tests.
3078  * "pma" is the input.
3079  * "res" is the expected result.
3080  */
3081 static struct {
3082 	const char *pma;
3083 	const char *res;
3084 } opt_pw_tests[] = {
3085 	{ "{ [-1] -> [-1]; [1] -> [1] }", "{ [1] }" },
3086 	{ "{ [a, b] -> [floor((b - 2*floor((-a)/4))/5)] : "
3087 	    "0 <= a, b <= 100 and b mod 2 = 0}", "{ [30] }" },
3088 	{ "[N] -> { [i,j] -> A[i, -i, i + j] : 0 <= i,j <= N <= 10 }",
3089 	  "{ A[10, 0, 20] }" },
3090 	{ "[N] -> {A[N, -N, 2N] : 0 <= N }", "{ A[infty, 0, infty] }" },
3091 };
3092 
3093 /* Perform basic isl_pw_multi_aff_max_multi_val tests.
3094  */
test_pw_max(struct isl_ctx * ctx)3095 static isl_stat test_pw_max(struct isl_ctx *ctx)
3096 {
3097 	int i;
3098 	isl_pw_multi_aff *pma;
3099 	isl_multi_val *mv;
3100 	isl_stat r;
3101 
3102 	for (i = 0; i < ARRAY_SIZE(opt_pw_tests); ++i) {
3103 		pma = isl_pw_multi_aff_read_from_str(ctx, opt_pw_tests[i].pma);
3104 		mv = isl_pw_multi_aff_max_multi_val(pma);
3105 		r = multi_val_check_plain_equal(mv, opt_pw_tests[i].res);
3106 		isl_multi_val_free(mv);
3107 
3108 		if (r < 0)
3109 			return isl_stat_error;
3110 	}
3111 
3112 	return isl_stat_ok;
3113 }
3114 
3115 /* A specialized isl_set_min_val test case that would return the wrong result
3116  * in earlier versions of isl.
3117  * The explicit call to isl_basic_set_union prevents the second basic set
3118  * from being determined to be empty prior to the call to isl_set_min_val,
3119  * at least at the point where this test case was introduced.
3120  */
test_min_special(isl_ctx * ctx)3121 static int test_min_special(isl_ctx *ctx)
3122 {
3123 	const char *str;
3124 	isl_basic_set *bset1, *bset2;
3125 	isl_set *set;
3126 	isl_aff *obj;
3127 	isl_val *res;
3128 	int ok;
3129 
3130 	str = "{ [a, b] : a >= 2 and b >= 0 and 14 - a <= b <= 9 }";
3131 	bset1 = isl_basic_set_read_from_str(ctx, str);
3132 	str = "{ [a, b] : 1 <= a, b and a + b <= 1 }";
3133 	bset2 = isl_basic_set_read_from_str(ctx, str);
3134 	set = isl_basic_set_union(bset1, bset2);
3135 	obj = isl_aff_read_from_str(ctx, "{ [a, b] -> [a] }");
3136 
3137 	res = isl_set_min_val(set, obj);
3138 	ok = isl_val_cmp_si(res, 5) == 0;
3139 
3140 	isl_aff_free(obj);
3141 	isl_set_free(set);
3142 	isl_val_free(res);
3143 
3144 	if (!res)
3145 		return -1;
3146 	if (!ok)
3147 		isl_die(ctx, isl_error_unknown, "unexpected minimum",
3148 			return -1);
3149 
3150 	return 0;
3151 }
3152 
3153 /* A specialized isl_set_min_val test case that would return an error
3154  * in earlier versions of isl.
3155  */
test_min_special2(isl_ctx * ctx)3156 static int test_min_special2(isl_ctx *ctx)
3157 {
3158 	const char *str;
3159 	isl_basic_set *bset;
3160 	isl_aff *obj;
3161 	isl_val *res;
3162 
3163 	str = "{ [i, j, k] : 2j = i and 2k = i + 1 and i >= 2 }";
3164 	bset = isl_basic_set_read_from_str(ctx, str);
3165 
3166 	obj = isl_aff_read_from_str(ctx, "{ [i, j, k] -> [i] }");
3167 
3168 	res = isl_basic_set_max_val(bset, obj);
3169 
3170 	isl_basic_set_free(bset);
3171 	isl_aff_free(obj);
3172 	isl_val_free(res);
3173 
3174 	if (!res)
3175 		return -1;
3176 
3177 	return 0;
3178 }
3179 
3180 struct {
3181 	const char *set;
3182 	const char *obj;
3183 	__isl_give isl_val *(*fn)(__isl_keep isl_set *set,
3184 		__isl_keep isl_aff *obj);
3185 	const char *res;
3186 } opt_tests[] = {
3187 	{ "{ [-1]; [1] }", "{ [x] -> [x] }", &isl_set_min_val, "-1" },
3188 	{ "{ [-1]; [1] }", "{ [x] -> [x] }", &isl_set_max_val, "1" },
3189 	{ "{ [a, b] : 0 <= a, b <= 100 and b mod 2 = 0}",
3190 	  "{ [a, b] -> [floor((b - 2*floor((-a)/4))/5)] }",
3191 	  &isl_set_max_val, "30" },
3192 
3193 };
3194 
3195 /* Perform basic isl_set_min_val and isl_set_max_val tests.
3196  * In particular, check the results on non-convex inputs.
3197  */
test_min(struct isl_ctx * ctx)3198 static int test_min(struct isl_ctx *ctx)
3199 {
3200 	int i;
3201 	isl_set *set;
3202 	isl_aff *obj;
3203 	isl_val *val, *res;
3204 	isl_bool ok;
3205 
3206 	for (i = 0; i < ARRAY_SIZE(opt_tests); ++i) {
3207 		set = isl_set_read_from_str(ctx, opt_tests[i].set);
3208 		obj = isl_aff_read_from_str(ctx, opt_tests[i].obj);
3209 		res = isl_val_read_from_str(ctx, opt_tests[i].res);
3210 		val = opt_tests[i].fn(set, obj);
3211 		ok = isl_val_eq(res, val);
3212 		isl_val_free(res);
3213 		isl_val_free(val);
3214 		isl_aff_free(obj);
3215 		isl_set_free(set);
3216 
3217 		if (ok < 0)
3218 			return -1;
3219 		if (!ok)
3220 			isl_die(ctx, isl_error_unknown,
3221 				"unexpected optimum", return -1);
3222 	}
3223 
3224 	if (test_pw_max(ctx) < 0)
3225 		return -1;
3226 	if (test_min_special(ctx) < 0)
3227 		return -1;
3228 	if (test_min_special2(ctx) < 0)
3229 		return -1;
3230 
3231 	return 0;
3232 }
3233 
3234 struct must_may {
3235 	isl_map *must;
3236 	isl_map *may;
3237 };
3238 
collect_must_may(__isl_take isl_map * dep,int must,void * dep_user,void * user)3239 static isl_stat collect_must_may(__isl_take isl_map *dep, int must,
3240 	void *dep_user, void *user)
3241 {
3242 	struct must_may *mm = (struct must_may *)user;
3243 
3244 	if (must)
3245 		mm->must = isl_map_union(mm->must, dep);
3246 	else
3247 		mm->may = isl_map_union(mm->may, dep);
3248 
3249 	return isl_stat_ok;
3250 }
3251 
common_space(void * first,void * second)3252 static int common_space(void *first, void *second)
3253 {
3254 	int depth = *(int *)first;
3255 	return 2 * depth;
3256 }
3257 
map_is_equal(__isl_keep isl_map * map,const char * str)3258 static int map_is_equal(__isl_keep isl_map *map, const char *str)
3259 {
3260 	isl_map *map2;
3261 	int equal;
3262 
3263 	if (!map)
3264 		return -1;
3265 
3266 	map2 = isl_map_read_from_str(map->ctx, str);
3267 	equal = isl_map_is_equal(map, map2);
3268 	isl_map_free(map2);
3269 
3270 	return equal;
3271 }
3272 
map_check_equal(__isl_keep isl_map * map,const char * str)3273 static int map_check_equal(__isl_keep isl_map *map, const char *str)
3274 {
3275 	int equal;
3276 
3277 	equal = map_is_equal(map, str);
3278 	if (equal < 0)
3279 		return -1;
3280 	if (!equal)
3281 		isl_die(isl_map_get_ctx(map), isl_error_unknown,
3282 			"result not as expected", return -1);
3283 	return 0;
3284 }
3285 
3286 /* Is "set" equal to the set described by "str"?
3287  */
set_is_equal(__isl_keep isl_set * set,const char * str)3288 static isl_bool set_is_equal(__isl_keep isl_set *set, const char *str)
3289 {
3290 	isl_set *set2;
3291 	isl_bool equal;
3292 
3293 	if (!set)
3294 		return isl_bool_error;
3295 
3296 	set2 = isl_set_read_from_str(isl_set_get_ctx(set), str);
3297 	equal = isl_set_is_equal(set, set2);
3298 	isl_set_free(set2);
3299 
3300 	return equal;
3301 }
3302 
3303 /* Check that "set" is equal to the set described by "str".
3304  */
set_check_equal(__isl_keep isl_set * set,const char * str)3305 static isl_stat set_check_equal(__isl_keep isl_set *set, const char *str)
3306 {
3307 	isl_bool equal;
3308 
3309 	equal = set_is_equal(set, str);
3310 	if (equal < 0)
3311 		return isl_stat_error;
3312 	if (!equal)
3313 		isl_die(isl_set_get_ctx(set), isl_error_unknown,
3314 			"result not as expected", return isl_stat_error);
3315 	return isl_stat_ok;
3316 }
3317 
3318 /* Is "uset" equal to the union set described by "str"?
3319  */
uset_is_equal(__isl_keep isl_union_set * uset,const char * str)3320 static isl_bool uset_is_equal(__isl_keep isl_union_set *uset, const char *str)
3321 {
3322 	isl_union_set *uset2;
3323 	isl_bool equal;
3324 
3325 	if (!uset)
3326 		return isl_bool_error;
3327 
3328 	uset2 = isl_union_set_read_from_str(isl_union_set_get_ctx(uset), str);
3329 	equal = isl_union_set_is_equal(uset, uset2);
3330 	isl_union_set_free(uset2);
3331 
3332 	return equal;
3333 }
3334 
3335 /* Check that "uset" is equal to the union set described by "str".
3336  */
uset_check_equal(__isl_keep isl_union_set * uset,const char * str)3337 static isl_stat uset_check_equal(__isl_keep isl_union_set *uset,
3338 	const char *str)
3339 {
3340 	isl_bool equal;
3341 
3342 	equal = uset_is_equal(uset, str);
3343 	if (equal < 0)
3344 		return isl_stat_error;
3345 	if (!equal)
3346 		isl_die(isl_union_set_get_ctx(uset), isl_error_unknown,
3347 			"result not as expected", return isl_stat_error);
3348 	return isl_stat_ok;
3349 }
3350 
test_dep(struct isl_ctx * ctx)3351 static int test_dep(struct isl_ctx *ctx)
3352 {
3353 	const char *str;
3354 	isl_space *space;
3355 	isl_map *map;
3356 	isl_access_info *ai;
3357 	isl_flow *flow;
3358 	int depth;
3359 	struct must_may mm;
3360 
3361 	depth = 3;
3362 
3363 	str = "{ [2,i,0] -> [i] : 0 <= i <= 10 }";
3364 	map = isl_map_read_from_str(ctx, str);
3365 	ai = isl_access_info_alloc(map, &depth, &common_space, 2);
3366 
3367 	str = "{ [0,i,0] -> [i] : 0 <= i <= 10 }";
3368 	map = isl_map_read_from_str(ctx, str);
3369 	ai = isl_access_info_add_source(ai, map, 1, &depth);
3370 
3371 	str = "{ [1,i,0] -> [5] : 0 <= i <= 10 }";
3372 	map = isl_map_read_from_str(ctx, str);
3373 	ai = isl_access_info_add_source(ai, map, 1, &depth);
3374 
3375 	flow = isl_access_info_compute_flow(ai);
3376 	space = isl_space_alloc(ctx, 0, 3, 3);
3377 	mm.must = isl_map_empty(isl_space_copy(space));
3378 	mm.may = isl_map_empty(space);
3379 
3380 	isl_flow_foreach(flow, collect_must_may, &mm);
3381 
3382 	str = "{ [0,i,0] -> [2,i,0] : (0 <= i <= 4) or (6 <= i <= 10); "
3383 	      "  [1,10,0] -> [2,5,0] }";
3384 	assert(map_is_equal(mm.must, str));
3385 	str = "{ [i,j,k] -> [l,m,n] : 1 = 0 }";
3386 	assert(map_is_equal(mm.may, str));
3387 
3388 	isl_map_free(mm.must);
3389 	isl_map_free(mm.may);
3390 	isl_flow_free(flow);
3391 
3392 
3393 	str = "{ [2,i,0] -> [i] : 0 <= i <= 10 }";
3394 	map = isl_map_read_from_str(ctx, str);
3395 	ai = isl_access_info_alloc(map, &depth, &common_space, 2);
3396 
3397 	str = "{ [0,i,0] -> [i] : 0 <= i <= 10 }";
3398 	map = isl_map_read_from_str(ctx, str);
3399 	ai = isl_access_info_add_source(ai, map, 1, &depth);
3400 
3401 	str = "{ [1,i,0] -> [5] : 0 <= i <= 10 }";
3402 	map = isl_map_read_from_str(ctx, str);
3403 	ai = isl_access_info_add_source(ai, map, 0, &depth);
3404 
3405 	flow = isl_access_info_compute_flow(ai);
3406 	space = isl_space_alloc(ctx, 0, 3, 3);
3407 	mm.must = isl_map_empty(isl_space_copy(space));
3408 	mm.may = isl_map_empty(space);
3409 
3410 	isl_flow_foreach(flow, collect_must_may, &mm);
3411 
3412 	str = "{ [0,i,0] -> [2,i,0] : (0 <= i <= 4) or (6 <= i <= 10) }";
3413 	assert(map_is_equal(mm.must, str));
3414 	str = "{ [0,5,0] -> [2,5,0]; [1,i,0] -> [2,5,0] : 0 <= i <= 10 }";
3415 	assert(map_is_equal(mm.may, str));
3416 
3417 	isl_map_free(mm.must);
3418 	isl_map_free(mm.may);
3419 	isl_flow_free(flow);
3420 
3421 
3422 	str = "{ [2,i,0] -> [i] : 0 <= i <= 10 }";
3423 	map = isl_map_read_from_str(ctx, str);
3424 	ai = isl_access_info_alloc(map, &depth, &common_space, 2);
3425 
3426 	str = "{ [0,i,0] -> [i] : 0 <= i <= 10 }";
3427 	map = isl_map_read_from_str(ctx, str);
3428 	ai = isl_access_info_add_source(ai, map, 0, &depth);
3429 
3430 	str = "{ [1,i,0] -> [5] : 0 <= i <= 10 }";
3431 	map = isl_map_read_from_str(ctx, str);
3432 	ai = isl_access_info_add_source(ai, map, 0, &depth);
3433 
3434 	flow = isl_access_info_compute_flow(ai);
3435 	space = isl_space_alloc(ctx, 0, 3, 3);
3436 	mm.must = isl_map_empty(isl_space_copy(space));
3437 	mm.may = isl_map_empty(space);
3438 
3439 	isl_flow_foreach(flow, collect_must_may, &mm);
3440 
3441 	str = "{ [0,i,0] -> [2,i,0] : 0 <= i <= 10; "
3442 	      "  [1,i,0] -> [2,5,0] : 0 <= i <= 10 }";
3443 	assert(map_is_equal(mm.may, str));
3444 	str = "{ [i,j,k] -> [l,m,n] : 1 = 0 }";
3445 	assert(map_is_equal(mm.must, str));
3446 
3447 	isl_map_free(mm.must);
3448 	isl_map_free(mm.may);
3449 	isl_flow_free(flow);
3450 
3451 
3452 	str = "{ [0,i,2] -> [i] : 0 <= i <= 10 }";
3453 	map = isl_map_read_from_str(ctx, str);
3454 	ai = isl_access_info_alloc(map, &depth, &common_space, 2);
3455 
3456 	str = "{ [0,i,0] -> [i] : 0 <= i <= 10 }";
3457 	map = isl_map_read_from_str(ctx, str);
3458 	ai = isl_access_info_add_source(ai, map, 0, &depth);
3459 
3460 	str = "{ [0,i,1] -> [5] : 0 <= i <= 10 }";
3461 	map = isl_map_read_from_str(ctx, str);
3462 	ai = isl_access_info_add_source(ai, map, 0, &depth);
3463 
3464 	flow = isl_access_info_compute_flow(ai);
3465 	space = isl_space_alloc(ctx, 0, 3, 3);
3466 	mm.must = isl_map_empty(isl_space_copy(space));
3467 	mm.may = isl_map_empty(space);
3468 
3469 	isl_flow_foreach(flow, collect_must_may, &mm);
3470 
3471 	str = "{ [0,i,0] -> [0,i,2] : 0 <= i <= 10; "
3472 	      "  [0,i,1] -> [0,5,2] : 0 <= i <= 5 }";
3473 	assert(map_is_equal(mm.may, str));
3474 	str = "{ [i,j,k] -> [l,m,n] : 1 = 0 }";
3475 	assert(map_is_equal(mm.must, str));
3476 
3477 	isl_map_free(mm.must);
3478 	isl_map_free(mm.may);
3479 	isl_flow_free(flow);
3480 
3481 
3482 	str = "{ [0,i,1] -> [i] : 0 <= i <= 10 }";
3483 	map = isl_map_read_from_str(ctx, str);
3484 	ai = isl_access_info_alloc(map, &depth, &common_space, 2);
3485 
3486 	str = "{ [0,i,0] -> [i] : 0 <= i <= 10 }";
3487 	map = isl_map_read_from_str(ctx, str);
3488 	ai = isl_access_info_add_source(ai, map, 0, &depth);
3489 
3490 	str = "{ [0,i,2] -> [5] : 0 <= i <= 10 }";
3491 	map = isl_map_read_from_str(ctx, str);
3492 	ai = isl_access_info_add_source(ai, map, 0, &depth);
3493 
3494 	flow = isl_access_info_compute_flow(ai);
3495 	space = isl_space_alloc(ctx, 0, 3, 3);
3496 	mm.must = isl_map_empty(isl_space_copy(space));
3497 	mm.may = isl_map_empty(space);
3498 
3499 	isl_flow_foreach(flow, collect_must_may, &mm);
3500 
3501 	str = "{ [0,i,0] -> [0,i,1] : 0 <= i <= 10; "
3502 	      "  [0,i,2] -> [0,5,1] : 0 <= i <= 4 }";
3503 	assert(map_is_equal(mm.may, str));
3504 	str = "{ [i,j,k] -> [l,m,n] : 1 = 0 }";
3505 	assert(map_is_equal(mm.must, str));
3506 
3507 	isl_map_free(mm.must);
3508 	isl_map_free(mm.may);
3509 	isl_flow_free(flow);
3510 
3511 
3512 	depth = 5;
3513 
3514 	str = "{ [1,i,0,0,0] -> [i,j] : 0 <= i <= 10 and 0 <= j <= 10 }";
3515 	map = isl_map_read_from_str(ctx, str);
3516 	ai = isl_access_info_alloc(map, &depth, &common_space, 1);
3517 
3518 	str = "{ [0,i,0,j,0] -> [i,j] : 0 <= i <= 10 and 0 <= j <= 10 }";
3519 	map = isl_map_read_from_str(ctx, str);
3520 	ai = isl_access_info_add_source(ai, map, 1, &depth);
3521 
3522 	flow = isl_access_info_compute_flow(ai);
3523 	space = isl_space_alloc(ctx, 0, 5, 5);
3524 	mm.must = isl_map_empty(isl_space_copy(space));
3525 	mm.may = isl_map_empty(space);
3526 
3527 	isl_flow_foreach(flow, collect_must_may, &mm);
3528 
3529 	str = "{ [0,i,0,j,0] -> [1,i,0,0,0] : 0 <= i,j <= 10 }";
3530 	assert(map_is_equal(mm.must, str));
3531 	str = "{ [0,0,0,0,0] -> [0,0,0,0,0] : 1 = 0 }";
3532 	assert(map_is_equal(mm.may, str));
3533 
3534 	isl_map_free(mm.must);
3535 	isl_map_free(mm.may);
3536 	isl_flow_free(flow);
3537 
3538 	return 0;
3539 }
3540 
3541 /* Check that the dependence analysis proceeds without errors.
3542  * Earlier versions of isl would break down during the analysis
3543  * due to the use of the wrong spaces.
3544  */
test_flow(isl_ctx * ctx)3545 static int test_flow(isl_ctx *ctx)
3546 {
3547 	const char *str;
3548 	isl_union_map *access, *schedule;
3549 	isl_union_map *must_dep, *may_dep;
3550 	int r;
3551 
3552 	str = "{ S0[j] -> i[]; S1[j,i] -> i[]; S2[] -> i[]; S3[] -> i[] }";
3553 	access = isl_union_map_read_from_str(ctx, str);
3554 	str = "{ S0[j] -> [0,j,0,0] : 0 <= j < 10; "
3555 		"S1[j,i] -> [0,j,1,i] : 0 <= j < i < 10; "
3556 		"S2[] -> [1,0,0,0]; "
3557 		"S3[] -> [-1,0,0,0] }";
3558 	schedule = isl_union_map_read_from_str(ctx, str);
3559 	r = isl_union_map_compute_flow(access, isl_union_map_copy(access),
3560 					isl_union_map_copy(access), schedule,
3561 					&must_dep, &may_dep, NULL, NULL);
3562 	isl_union_map_free(may_dep);
3563 	isl_union_map_free(must_dep);
3564 
3565 	return r;
3566 }
3567 
3568 struct {
3569 	const char *map;
3570 	int sv;
3571 } sv_tests[] = {
3572 	{ "[N] -> { [i] -> [f] : 0 <= i <= N and 0 <= i - 10 f <= 9 }", 1 },
3573 	{ "[N] -> { [i] -> [f] : 0 <= i <= N and 0 <= i - 10 f <= 10 }", 0 },
3574 	{ "{ [i] -> [3*floor(i/2) + 5*floor(i/3)] }", 1 },
3575 	{ "{ S1[i] -> [i] : 0 <= i <= 9; S2[i] -> [i] : 0 <= i <= 9 }", 1 },
3576 	{ "{ [i] -> S1[i] : 0 <= i <= 9; [i] -> S2[i] : 0 <= i <= 9 }", 0 },
3577 	{ "{ A[i] -> [i]; B[i] -> [i]; B[i] -> [i + 1] }", 0 },
3578 	{ "{ A[i] -> [i]; B[i] -> [i] : i < 0; B[i] -> [i + 1] : i > 0 }", 1 },
3579 	{ "{ A[i] -> [i]; B[i] -> A[i] : i < 0; B[i] -> [i + 1] : i > 0 }", 1 },
3580 	{ "{ A[i] -> [i]; B[i] -> [j] : i - 1 <= j <= i }", 0 },
3581 };
3582 
test_sv(isl_ctx * ctx)3583 int test_sv(isl_ctx *ctx)
3584 {
3585 	isl_union_map *umap;
3586 	int i;
3587 	int sv;
3588 
3589 	for (i = 0; i < ARRAY_SIZE(sv_tests); ++i) {
3590 		umap = isl_union_map_read_from_str(ctx, sv_tests[i].map);
3591 		sv = isl_union_map_is_single_valued(umap);
3592 		isl_union_map_free(umap);
3593 		if (sv < 0)
3594 			return -1;
3595 		if (sv_tests[i].sv && !sv)
3596 			isl_die(ctx, isl_error_internal,
3597 				"map not detected as single valued", return -1);
3598 		if (!sv_tests[i].sv && sv)
3599 			isl_die(ctx, isl_error_internal,
3600 				"map detected as single valued", return -1);
3601 	}
3602 
3603 	return 0;
3604 }
3605 
3606 struct {
3607 	const char *str;
3608 	int bijective;
3609 } bijective_tests[] = {
3610 	{ "[N,M]->{[i,j] -> [i]}", 0 },
3611 	{ "[N,M]->{[i,j] -> [i] : j=i}", 1 },
3612 	{ "[N,M]->{[i,j] -> [i] : j=0}", 1 },
3613 	{ "[N,M]->{[i,j] -> [i] : j=N}", 1 },
3614 	{ "[N,M]->{[i,j] -> [j,i]}", 1 },
3615 	{ "[N,M]->{[i,j] -> [i+j]}", 0 },
3616 	{ "[N,M]->{[i,j] -> []}", 0 },
3617 	{ "[N,M]->{[i,j] -> [i,j,N]}", 1 },
3618 	{ "[N,M]->{[i,j] -> [2i]}", 0 },
3619 	{ "[N,M]->{[i,j] -> [i,i]}", 0 },
3620 	{ "[N,M]->{[i,j] -> [2i,i]}", 0 },
3621 	{ "[N,M]->{[i,j] -> [2i,j]}", 1 },
3622 	{ "[N,M]->{[i,j] -> [x,y] : 2x=i & y =j}", 1 },
3623 };
3624 
test_bijective(struct isl_ctx * ctx)3625 static int test_bijective(struct isl_ctx *ctx)
3626 {
3627 	isl_map *map;
3628 	int i;
3629 	int bijective;
3630 
3631 	for (i = 0; i < ARRAY_SIZE(bijective_tests); ++i) {
3632 		map = isl_map_read_from_str(ctx, bijective_tests[i].str);
3633 		bijective = isl_map_is_bijective(map);
3634 		isl_map_free(map);
3635 		if (bijective < 0)
3636 			return -1;
3637 		if (bijective_tests[i].bijective && !bijective)
3638 			isl_die(ctx, isl_error_internal,
3639 				"map not detected as bijective", return -1);
3640 		if (!bijective_tests[i].bijective && bijective)
3641 			isl_die(ctx, isl_error_internal,
3642 				"map detected as bijective", return -1);
3643 	}
3644 
3645 	return 0;
3646 }
3647 
3648 /* Inputs for isl_pw_qpolynomial_gist tests.
3649  * "pwqp" is the input, "set" is the context and "gist" is the expected result.
3650  */
3651 struct {
3652 	const char *pwqp;
3653 	const char *set;
3654 	const char *gist;
3655 } pwqp_gist_tests[] = {
3656 	{ "{ [i] -> i }", "{ [k] : exists a : k = 2a }", "{ [i] -> i }" },
3657 	{ "{ [i] -> i + [ (i + [i/3])/2 ] }", "{ [10] }", "{ [i] -> 16 }" },
3658 	{ "{ [i] -> ([(i)/2]) }", "{ [k] : exists a : k = 2a+1 }",
3659 	  "{ [i] -> -1/2 + 1/2 * i }" },
3660 	{ "{ [i] -> i^2 : i != 0 }", "{ [i] : i != 0 }", "{ [i] -> i^2 }" },
3661 };
3662 
3663 /* Perform some basic isl_pw_qpolynomial_gist tests.
3664  */
test_pwqp_gist(isl_ctx * ctx)3665 static isl_stat test_pwqp_gist(isl_ctx *ctx)
3666 {
3667 	int i;
3668 	const char *str;
3669 	isl_set *set;
3670 	isl_pw_qpolynomial *pwqp1, *pwqp2;
3671 	isl_bool equal;
3672 
3673 	for (i = 0; i < ARRAY_SIZE(pwqp_gist_tests); ++i) {
3674 		str = pwqp_gist_tests[i].pwqp;
3675 		pwqp1 = isl_pw_qpolynomial_read_from_str(ctx, str);
3676 		str = pwqp_gist_tests[i].set;
3677 		set = isl_set_read_from_str(ctx, str);
3678 		pwqp1 = isl_pw_qpolynomial_gist(pwqp1, set);
3679 		str = pwqp_gist_tests[i].gist;
3680 		pwqp2 = isl_pw_qpolynomial_read_from_str(ctx, str);
3681 		pwqp1 = isl_pw_qpolynomial_sub(pwqp1, pwqp2);
3682 		equal = isl_pw_qpolynomial_is_zero(pwqp1);
3683 		isl_pw_qpolynomial_free(pwqp1);
3684 
3685 		if (equal < 0)
3686 			return isl_stat_error;
3687 		if (!equal)
3688 			isl_die(ctx, isl_error_unknown,
3689 				"unexpected result", return isl_stat_error);
3690 	}
3691 
3692 	return isl_stat_ok;
3693 }
3694 
3695 /* Perform a basic isl_pw_qpolynomial_max test.
3696  */
test_pwqp_max(isl_ctx * ctx)3697 static isl_stat test_pwqp_max(isl_ctx *ctx)
3698 {
3699 	const char *str;
3700 	isl_pw_qpolynomial *pwqp;
3701 	isl_val *v;
3702 	int ok;
3703 
3704 	str = "{ [x=2:9, y] -> floor((x + 1)/4)^3 - floor((2x)/3)^2 }";
3705 	pwqp = isl_pw_qpolynomial_read_from_str(ctx, str);
3706 	v = isl_pw_qpolynomial_max(pwqp);
3707 	ok = isl_val_cmp_si(v, -1) == 0;
3708 	isl_val_free(v);
3709 
3710 	if (!v)
3711 		return isl_stat_error;
3712 	if (!ok)
3713 		isl_die(ctx, isl_error_unknown, "unexpected maximum",
3714 			return isl_stat_error);
3715 
3716 	return isl_stat_ok;
3717 }
3718 
test_pwqp(struct isl_ctx * ctx)3719 static int test_pwqp(struct isl_ctx *ctx)
3720 {
3721 	const char *str;
3722 	isl_set *set;
3723 	isl_pw_qpolynomial *pwqp1, *pwqp2;
3724 	int equal;
3725 
3726 	str = "{ [i,j,k] -> 1 + 9 * [i/5] + 7 * [j/11] + 4 * [k/13] }";
3727 	pwqp1 = isl_pw_qpolynomial_read_from_str(ctx, str);
3728 
3729 	pwqp1 = isl_pw_qpolynomial_move_dims(pwqp1, isl_dim_param, 0,
3730 						isl_dim_in, 1, 1);
3731 
3732 	str = "[j] -> { [i,k] -> 1 + 9 * [i/5] + 7 * [j/11] + 4 * [k/13] }";
3733 	pwqp2 = isl_pw_qpolynomial_read_from_str(ctx, str);
3734 
3735 	pwqp1 = isl_pw_qpolynomial_sub(pwqp1, pwqp2);
3736 
3737 	assert(isl_pw_qpolynomial_is_zero(pwqp1));
3738 
3739 	isl_pw_qpolynomial_free(pwqp1);
3740 
3741 	if (test_pwqp_gist(ctx) < 0)
3742 		return -1;
3743 
3744 	str = "{ [i] -> ([([i/2] + [i/2])/5]) }";
3745 	pwqp1 = isl_pw_qpolynomial_read_from_str(ctx, str);
3746 	str = "{ [i] -> ([(2 * [i/2])/5]) }";
3747 	pwqp2 = isl_pw_qpolynomial_read_from_str(ctx, str);
3748 
3749 	pwqp1 = isl_pw_qpolynomial_sub(pwqp1, pwqp2);
3750 
3751 	assert(isl_pw_qpolynomial_is_zero(pwqp1));
3752 
3753 	isl_pw_qpolynomial_free(pwqp1);
3754 
3755 	str = "{ [x] -> ([x/2] + [(x+1)/2]) }";
3756 	pwqp1 = isl_pw_qpolynomial_read_from_str(ctx, str);
3757 	str = "{ [x] -> x }";
3758 	pwqp2 = isl_pw_qpolynomial_read_from_str(ctx, str);
3759 
3760 	pwqp1 = isl_pw_qpolynomial_sub(pwqp1, pwqp2);
3761 
3762 	assert(isl_pw_qpolynomial_is_zero(pwqp1));
3763 
3764 	isl_pw_qpolynomial_free(pwqp1);
3765 
3766 	str = "{ [i] -> ([i/2]) : i >= 0; [i] -> ([i/3]) : i < 0 }";
3767 	pwqp1 = isl_pw_qpolynomial_read_from_str(ctx, str);
3768 	pwqp2 = isl_pw_qpolynomial_read_from_str(ctx, str);
3769 	pwqp1 = isl_pw_qpolynomial_coalesce(pwqp1);
3770 	pwqp1 = isl_pw_qpolynomial_sub(pwqp1, pwqp2);
3771 	assert(isl_pw_qpolynomial_is_zero(pwqp1));
3772 	isl_pw_qpolynomial_free(pwqp1);
3773 
3774 	str = "{ [a,b,a] -> (([(2*[a/3]+b)/5]) * ([(2*[a/3]+b)/5])) }";
3775 	pwqp2 = isl_pw_qpolynomial_read_from_str(ctx, str);
3776 	str = "{ [a,b,c] -> (([(2*[a/3]+b)/5]) * ([(2*[c/3]+b)/5])) }";
3777 	pwqp1 = isl_pw_qpolynomial_read_from_str(ctx, str);
3778 	set = isl_set_read_from_str(ctx, "{ [a,b,a] }");
3779 	pwqp1 = isl_pw_qpolynomial_intersect_domain(pwqp1, set);
3780 	equal = isl_pw_qpolynomial_plain_is_equal(pwqp1, pwqp2);
3781 	isl_pw_qpolynomial_free(pwqp1);
3782 	isl_pw_qpolynomial_free(pwqp2);
3783 	if (equal < 0)
3784 		return -1;
3785 	if (!equal)
3786 		isl_die(ctx, isl_error_unknown, "unexpected result", return -1);
3787 
3788 	str = "{ [a,b,c] -> (([(2*[a/3]+1)/5]) * ([(2*[c/3]+1)/5])) : b = 1 }";
3789 	pwqp2 = isl_pw_qpolynomial_read_from_str(ctx, str);
3790 	str = "{ [a,b,c] -> (([(2*[a/3]+b)/5]) * ([(2*[c/3]+b)/5])) }";
3791 	pwqp1 = isl_pw_qpolynomial_read_from_str(ctx, str);
3792 	pwqp1 = isl_pw_qpolynomial_fix_val(pwqp1, isl_dim_set, 1,
3793 						isl_val_one(ctx));
3794 	equal = isl_pw_qpolynomial_plain_is_equal(pwqp1, pwqp2);
3795 	isl_pw_qpolynomial_free(pwqp1);
3796 	isl_pw_qpolynomial_free(pwqp2);
3797 	if (equal < 0)
3798 		return -1;
3799 	if (!equal)
3800 		isl_die(ctx, isl_error_unknown, "unexpected result", return -1);
3801 
3802 	if (test_pwqp_max(ctx) < 0)
3803 		return -1;
3804 
3805 	return 0;
3806 }
3807 
test_split_periods(isl_ctx * ctx)3808 static int test_split_periods(isl_ctx *ctx)
3809 {
3810 	const char *str;
3811 	isl_pw_qpolynomial *pwqp;
3812 
3813 	str = "{ [U,V] -> 1/3 * U + 2/3 * V - [(U + 2V)/3] + [U/2] : "
3814 		"U + 2V + 3 >= 0 and - U -2V  >= 0 and - U + 10 >= 0 and "
3815 		"U  >= 0; [U,V] -> U^2 : U >= 100 }";
3816 	pwqp = isl_pw_qpolynomial_read_from_str(ctx, str);
3817 
3818 	pwqp = isl_pw_qpolynomial_split_periods(pwqp, 2);
3819 
3820 	isl_pw_qpolynomial_free(pwqp);
3821 
3822 	if (!pwqp)
3823 		return -1;
3824 
3825 	return 0;
3826 }
3827 
test_union(isl_ctx * ctx)3828 static int test_union(isl_ctx *ctx)
3829 {
3830 	const char *str;
3831 	isl_union_set *uset1, *uset2;
3832 	isl_union_map *umap1, *umap2;
3833 	int equal;
3834 
3835 	str = "{ [i] : 0 <= i <= 1 }";
3836 	uset1 = isl_union_set_read_from_str(ctx, str);
3837 	str = "{ [1] -> [0] }";
3838 	umap1 = isl_union_map_read_from_str(ctx, str);
3839 
3840 	umap2 = isl_union_set_lex_gt_union_set(isl_union_set_copy(uset1), uset1);
3841 	equal = isl_union_map_is_equal(umap1, umap2);
3842 
3843 	isl_union_map_free(umap1);
3844 	isl_union_map_free(umap2);
3845 
3846 	if (equal < 0)
3847 		return -1;
3848 	if (!equal)
3849 		isl_die(ctx, isl_error_unknown, "union maps not equal",
3850 			return -1);
3851 
3852 	str = "{ A[i] -> B[i]; B[i] -> C[i]; A[0] -> C[1] }";
3853 	umap1 = isl_union_map_read_from_str(ctx, str);
3854 	str = "{ A[i]; B[i] }";
3855 	uset1 = isl_union_set_read_from_str(ctx, str);
3856 
3857 	uset2 = isl_union_map_domain(umap1);
3858 
3859 	equal = isl_union_set_is_equal(uset1, uset2);
3860 
3861 	isl_union_set_free(uset1);
3862 	isl_union_set_free(uset2);
3863 
3864 	if (equal < 0)
3865 		return -1;
3866 	if (!equal)
3867 		isl_die(ctx, isl_error_unknown, "union sets not equal",
3868 			return -1);
3869 
3870 	return 0;
3871 }
3872 
3873 /* Check that computing a bound of a non-zero polynomial over an unbounded
3874  * domain does not produce a rational value.
3875  * In particular, check that the upper bound is infinity.
3876  */
test_bound_unbounded_domain(isl_ctx * ctx)3877 static int test_bound_unbounded_domain(isl_ctx *ctx)
3878 {
3879 	const char *str;
3880 	isl_pw_qpolynomial *pwqp;
3881 	isl_pw_qpolynomial_fold *pwf, *pwf2;
3882 	isl_bool equal;
3883 
3884 	str = "{ [m,n] -> -m * n }";
3885 	pwqp = isl_pw_qpolynomial_read_from_str(ctx, str);
3886 	pwf = isl_pw_qpolynomial_bound(pwqp, isl_fold_max, NULL);
3887 	str = "{ infty }";
3888 	pwqp = isl_pw_qpolynomial_read_from_str(ctx, str);
3889 	pwf2 = isl_pw_qpolynomial_bound(pwqp, isl_fold_max, NULL);
3890 	equal = isl_pw_qpolynomial_fold_plain_is_equal(pwf, pwf2);
3891 	isl_pw_qpolynomial_fold_free(pwf);
3892 	isl_pw_qpolynomial_fold_free(pwf2);
3893 
3894 	if (equal < 0)
3895 		return -1;
3896 	if (!equal)
3897 		isl_die(ctx, isl_error_unknown,
3898 			"expecting infinite polynomial bound", return -1);
3899 
3900 	return 0;
3901 }
3902 
test_bound(isl_ctx * ctx)3903 static int test_bound(isl_ctx *ctx)
3904 {
3905 	const char *str;
3906 	isl_size dim;
3907 	isl_pw_qpolynomial *pwqp;
3908 	isl_pw_qpolynomial_fold *pwf;
3909 
3910 	if (test_bound_unbounded_domain(ctx) < 0)
3911 		return -1;
3912 
3913 	str = "{ [[a, b, c, d] -> [e]] -> 0 }";
3914 	pwqp = isl_pw_qpolynomial_read_from_str(ctx, str);
3915 	pwf = isl_pw_qpolynomial_bound(pwqp, isl_fold_max, NULL);
3916 	dim = isl_pw_qpolynomial_fold_dim(pwf, isl_dim_in);
3917 	isl_pw_qpolynomial_fold_free(pwf);
3918 	if (dim < 0)
3919 		return -1;
3920 	if (dim != 4)
3921 		isl_die(ctx, isl_error_unknown, "unexpected input dimension",
3922 			return -1);
3923 
3924 	str = "{ [[x]->[x]] -> 1 : exists a : x = 2 a }";
3925 	pwqp = isl_pw_qpolynomial_read_from_str(ctx, str);
3926 	pwf = isl_pw_qpolynomial_bound(pwqp, isl_fold_max, NULL);
3927 	dim = isl_pw_qpolynomial_fold_dim(pwf, isl_dim_in);
3928 	isl_pw_qpolynomial_fold_free(pwf);
3929 	if (dim < 0)
3930 		return -1;
3931 	if (dim != 1)
3932 		isl_die(ctx, isl_error_unknown, "unexpected input dimension",
3933 			return -1);
3934 
3935 	return 0;
3936 }
3937 
3938 /* isl_set is defined to isl_map internally, so the corresponding elements
3939  * are isl_basic_map objects.
3940  */
3941 #undef EL_BASE
3942 #undef SET_BASE
3943 #define EL_BASE		basic_map
3944 #define SET_BASE	set
3945 #include "isl_test_list_templ.c"
3946 
3947 #undef EL_BASE
3948 #undef SET_BASE
3949 #define EL_BASE		basic_set
3950 #define SET_BASE	union_set
3951 #include "isl_test_list_templ.c"
3952 
3953 #undef EL_BASE
3954 #undef SET_BASE
3955 #define EL_BASE		set
3956 #define SET_BASE	union_set
3957 #include "isl_test_list_templ.c"
3958 
3959 #undef EL_BASE
3960 #undef SET_BASE
3961 #define EL_BASE		basic_map
3962 #define SET_BASE	map
3963 #include "isl_test_list_templ.c"
3964 
3965 #undef EL_BASE
3966 #undef SET_BASE
3967 #define EL_BASE		map
3968 #define SET_BASE	union_map
3969 #include "isl_test_list_templ.c"
3970 
3971 /* Check that the conversion from isl objects to lists works as expected.
3972  */
test_get_list(isl_ctx * ctx)3973 static int test_get_list(isl_ctx *ctx)
3974 {
3975 	if (test_get_list_basic_map_from_set(ctx, "{ [0]; [2]; [3] }"))
3976 		return -1;
3977 	if (test_get_list_basic_set_from_union_set(ctx, "{ A[0]; B[2]; B[3] }"))
3978 		return -1;
3979 	if (test_get_list_set_from_union_set(ctx, "{ A[0]; A[2]; B[3] }"))
3980 		return -1;
3981 	if (test_get_list_basic_map_from_map(ctx,
3982 				"{ [0] -> [0]; [2] -> [0]; [3] -> [0] }"))
3983 		return -1;
3984 	if (test_get_list_map_from_union_map(ctx,
3985 				"{ A[0] -> [0]; A[2] -> [0]; B[3] -> [0] }"))
3986 		return -1;
3987 
3988 	return 0;
3989 }
3990 
test_lift(isl_ctx * ctx)3991 static int test_lift(isl_ctx *ctx)
3992 {
3993 	const char *str;
3994 	isl_basic_map *bmap;
3995 	isl_basic_set *bset;
3996 
3997 	str = "{ [i0] : exists e0 : i0 = 4e0 }";
3998 	bset = isl_basic_set_read_from_str(ctx, str);
3999 	bset = isl_basic_set_lift(bset);
4000 	bmap = isl_basic_map_from_range(bset);
4001 	bset = isl_basic_map_domain(bmap);
4002 	isl_basic_set_free(bset);
4003 
4004 	return 0;
4005 }
4006 
4007 /* Check that isl_set_is_subset is not confused by identical
4008  * integer divisions.
4009  * The call to isl_set_normalize ensures that the equality constraints
4010  * a = b = 0 are discovered, turning e0 and e1 into identical
4011  * integer divisions.  Any further simplification would remove
4012  * the duplicate integer divisions.
4013  */
test_subset_duplicate_integer_divisions(isl_ctx * ctx)4014 static isl_stat test_subset_duplicate_integer_divisions(isl_ctx *ctx)
4015 {
4016 	const char *str;
4017 	isl_bool is_subset;
4018 	isl_set *set1, *set2;
4019 
4020 	str = "{ [a, b, c, d] : "
4021 	    "exists (e0 = floor((a + d)/4), e1 = floor((d)/4), "
4022 		    "e2 = floor((-a - d + 4 *floor((a + d)/4))/10), "
4023 		    "e3 = floor((-d + 4*floor((d)/4))/10): "
4024 		"10e2 = -a - 2c - d + 4e0 and 10e3 = -2c - d + 4e1 and "
4025 		"b >= 0 and a <= 0 and b <= a) }";
4026 	set1 = isl_set_read_from_str(ctx, str);
4027 	set2 = isl_set_read_from_str(ctx, str);
4028 	set2 = isl_set_normalize(set2);
4029 
4030 	is_subset = isl_set_is_subset(set1, set2);
4031 
4032 	isl_set_free(set1);
4033 	isl_set_free(set2);
4034 
4035 	if (is_subset < 0)
4036 		return isl_stat_error;
4037 	if (!is_subset)
4038 		isl_die(ctx, isl_error_unknown,
4039 			"set is not considered to be a subset of itself",
4040 			return isl_stat_error);
4041 
4042 	return isl_stat_ok;
4043 }
4044 
4045 struct {
4046 	const char *set1;
4047 	const char *set2;
4048 	int subset;
4049 } subset_tests[] = {
4050 	{ "{ [112, 0] }",
4051 	  "{ [i0, i1] : exists (e0 = [(i0 - i1)/16], e1: "
4052 		"16e0 <= i0 - i1 and 16e0 >= -15 + i0 - i1 and "
4053 		"16e1 <= i1 and 16e0 >= -i1 and 16e1 >= -i0 + i1) }", 1 },
4054 	{ "{ [65] }",
4055 	  "{ [i] : exists (e0 = [(255i)/256], e1 = [(127i + 65e0)/191], "
4056 		"e2 = [(3i + 61e1)/65], e3 = [(52i + 12e2)/61], "
4057 		"e4 = [(2i + e3)/3], e5 = [(4i + e3)/4], e6 = [(8i + e3)/12]: "
4058 		    "3e4 = 2i + e3 and 4e5 = 4i + e3 and 12e6 = 8i + e3 and "
4059 		    "i <= 255 and 64e3 >= -45 + 67i and i >= 0 and "
4060 		    "256e0 <= 255i and 256e0 >= -255 + 255i and "
4061 		    "191e1 <= 127i + 65e0 and 191e1 >= -190 + 127i + 65e0 and "
4062 		    "65e2 <= 3i + 61e1 and 65e2 >= -64 + 3i + 61e1 and "
4063 		    "61e3 <= 52i + 12e2 and 61e3 >= -60 + 52i + 12e2) }", 1 },
4064 	{ "{ [i] : 0 <= i <= 10 }", "{ rat: [i] : 0 <= i <= 10 }", 1 },
4065 	{ "{ rat: [i] : 0 <= i <= 10 }", "{ [i] : 0 <= i <= 10 }", 0 },
4066 	{ "{ rat: [0] }", "{ [i] : 0 <= i <= 10 }", 1 },
4067 	{ "{ rat: [(1)/2] }", "{ [i] : 0 <= i <= 10 }", 0 },
4068 	{ "{ [t, i] : (exists (e0 = [(2 + t)/4]: 4e0 <= 2 + t and "
4069 			"4e0 >= -1 + t and i >= 57 and i <= 62 and "
4070 			"4e0 <= 62 + t - i and 4e0 >= -61 + t + i and "
4071 			"t >= 0 and t <= 511 and 4e0 <= -57 + t + i and "
4072 			"4e0 >= 58 + t - i and i >= 58 + t and i >= 62 - t)) }",
4073 	  "{ [i0, i1] : (exists (e0 = [(4 + i0)/4]: 4e0 <= 62 + i0 - i1 and "
4074 			"4e0 >= 1 + i0 and i0 >= 0 and i0 <= 511 and "
4075 			"4e0 <= -57 + i0 + i1)) or "
4076 		"(exists (e0 = [(2 + i0)/4]: 4e0 <= i0 and "
4077 			"4e0 >= 58 + i0 - i1 and i0 >= 2 and i0 <= 511 and "
4078 			"4e0 >= -61 + i0 + i1)) or "
4079 		"(i1 <= 66 - i0 and i0 >= 2 and i1 >= 59 + i0) }", 1 },
4080 	{ "[a, b] -> { : a = 0 and b = -1 }", "[b, a] -> { : b >= -10 }", 1 },
4081 };
4082 
test_subset(isl_ctx * ctx)4083 static int test_subset(isl_ctx *ctx)
4084 {
4085 	int i;
4086 	isl_set *set1, *set2;
4087 	int subset;
4088 
4089 	if (test_subset_duplicate_integer_divisions(ctx) < 0)
4090 		return -1;
4091 
4092 	for (i = 0; i < ARRAY_SIZE(subset_tests); ++i) {
4093 		set1 = isl_set_read_from_str(ctx, subset_tests[i].set1);
4094 		set2 = isl_set_read_from_str(ctx, subset_tests[i].set2);
4095 		subset = isl_set_is_subset(set1, set2);
4096 		isl_set_free(set1);
4097 		isl_set_free(set2);
4098 		if (subset < 0)
4099 			return -1;
4100 		if (subset != subset_tests[i].subset)
4101 			isl_die(ctx, isl_error_unknown,
4102 				"incorrect subset result", return -1);
4103 	}
4104 
4105 	return 0;
4106 }
4107 
4108 /* Perform a set subtraction with a set that has a non-obviously empty disjunct.
4109  * Older versions of isl would fail on such cases.
4110  */
test_subtract_empty(isl_ctx * ctx)4111 static isl_stat test_subtract_empty(isl_ctx *ctx)
4112 {
4113 	const char *str;
4114 	isl_set *s1, *s2;
4115 
4116 	s1 = isl_set_read_from_str(ctx, "{ [0] }");
4117 	str = "{ [a] : (exists (e0, e1, e2: 1056e1 <= 32 + a - 33e0 and "
4118 			"1089e1 >= a - 33e0 and 1089e1 <= 1 + a - 33e0 and "
4119 			"33e2 >= -a + 33e0 + 1056e1 and "
4120 			"33e2 < -2a + 66e0 + 2112e1)) or a = 0 }";
4121 	s2 = isl_set_read_from_str(ctx, str);
4122 	s1 = isl_set_subtract(s1, s2);
4123 	isl_set_free(s1);
4124 
4125 	return isl_stat_non_null(s1);
4126 }
4127 
4128 struct {
4129 	const char *minuend;
4130 	const char *subtrahend;
4131 	const char *difference;
4132 } subtract_domain_tests[] = {
4133 	{ "{ A[i] -> B[i] }", "{ A[i] }", "{ }" },
4134 	{ "{ A[i] -> B[i] }", "{ B[i] }", "{ A[i] -> B[i] }" },
4135 	{ "{ A[i] -> B[i] }", "{ A[i] : i > 0 }", "{ A[i] -> B[i] : i <= 0 }" },
4136 };
4137 
test_subtract(isl_ctx * ctx)4138 static int test_subtract(isl_ctx *ctx)
4139 {
4140 	int i;
4141 	isl_union_map *umap1, *umap2;
4142 	isl_union_pw_multi_aff *upma1, *upma2;
4143 	isl_union_set *uset;
4144 	int equal;
4145 
4146 	if (test_subtract_empty(ctx) < 0)
4147 		return -1;
4148 
4149 	for (i = 0; i < ARRAY_SIZE(subtract_domain_tests); ++i) {
4150 		umap1 = isl_union_map_read_from_str(ctx,
4151 				subtract_domain_tests[i].minuend);
4152 		uset = isl_union_set_read_from_str(ctx,
4153 				subtract_domain_tests[i].subtrahend);
4154 		umap2 = isl_union_map_read_from_str(ctx,
4155 				subtract_domain_tests[i].difference);
4156 		umap1 = isl_union_map_subtract_domain(umap1, uset);
4157 		equal = isl_union_map_is_equal(umap1, umap2);
4158 		isl_union_map_free(umap1);
4159 		isl_union_map_free(umap2);
4160 		if (equal < 0)
4161 			return -1;
4162 		if (!equal)
4163 			isl_die(ctx, isl_error_unknown,
4164 				"incorrect subtract domain result", return -1);
4165 	}
4166 
4167 	for (i = 0; i < ARRAY_SIZE(subtract_domain_tests); ++i) {
4168 		upma1 = isl_union_pw_multi_aff_read_from_str(ctx,
4169 				subtract_domain_tests[i].minuend);
4170 		uset = isl_union_set_read_from_str(ctx,
4171 				subtract_domain_tests[i].subtrahend);
4172 		upma2 = isl_union_pw_multi_aff_read_from_str(ctx,
4173 				subtract_domain_tests[i].difference);
4174 		upma1 = isl_union_pw_multi_aff_subtract_domain(upma1, uset);
4175 		equal = isl_union_pw_multi_aff_plain_is_equal(upma1, upma2);
4176 		isl_union_pw_multi_aff_free(upma1);
4177 		isl_union_pw_multi_aff_free(upma2);
4178 		if (equal < 0)
4179 			return -1;
4180 		if (!equal)
4181 			isl_die(ctx, isl_error_unknown,
4182 				"incorrect subtract domain result", return -1);
4183 	}
4184 
4185 	return 0;
4186 }
4187 
4188 /* Check that intersecting the empty basic set with another basic set
4189  * does not increase the number of constraints.  In particular,
4190  * the empty basic set should maintain its canonical representation.
4191  */
test_intersect_1(isl_ctx * ctx)4192 static int test_intersect_1(isl_ctx *ctx)
4193 {
4194 	isl_size n1, n2;
4195 	isl_basic_set *bset1, *bset2;
4196 
4197 	bset1 = isl_basic_set_read_from_str(ctx, "{ [a,b,c] : 1 = 0 }");
4198 	bset2 = isl_basic_set_read_from_str(ctx, "{ [1,2,3] }");
4199 	n1 = isl_basic_set_n_constraint(bset1);
4200 	bset1 = isl_basic_set_intersect(bset1, bset2);
4201 	n2 = isl_basic_set_n_constraint(bset1);
4202 	isl_basic_set_free(bset1);
4203 	if (n1 < 0 || n2 < 0)
4204 		return -1;
4205 	if (n1 != n2)
4206 		isl_die(ctx, isl_error_unknown,
4207 			"number of constraints of empty set changed",
4208 			return -1);
4209 
4210 	return 0;
4211 }
4212 
4213 /* Check that intersecting a set with itself does not cause
4214  * an explosion in the number of disjuncts.
4215  */
test_intersect_2(isl_ctx * ctx)4216 static isl_stat test_intersect_2(isl_ctx *ctx)
4217 {
4218 	int i;
4219 	isl_set *set;
4220 
4221 	set = isl_set_read_from_str(ctx, "{ [x,y] : x >= 0 or y >= 0 }");
4222 	for (i = 0; i < 100; ++i)
4223 		set = isl_set_intersect(set, isl_set_copy(set));
4224 	isl_set_free(set);
4225 	if (!set)
4226 		return isl_stat_error;
4227 	return isl_stat_ok;
4228 }
4229 
4230 /* Perform some intersection tests.
4231  */
test_intersect(isl_ctx * ctx)4232 static int test_intersect(isl_ctx *ctx)
4233 {
4234 	if (test_intersect_1(ctx) < 0)
4235 		return -1;
4236 	if (test_intersect_2(ctx) < 0)
4237 		return -1;
4238 
4239 	return 0;
4240 }
4241 
test_factorize(isl_ctx * ctx)4242 int test_factorize(isl_ctx *ctx)
4243 {
4244 	const char *str;
4245 	isl_basic_set *bset;
4246 	isl_factorizer *f;
4247 
4248 	str = "{ [i0, i1, i2, i3, i4, i5, i6, i7] : 3i5 <= 2 - 2i0 and "
4249 	    "i0 >= -2 and i6 >= 1 + i3 and i7 >= 0 and 3i5 >= -2i0 and "
4250 	    "2i4 <= i2 and i6 >= 1 + 2i0 + 3i1 and i4 <= -1 and "
4251 	    "i6 >= 1 + 2i0 + 3i5 and i6 <= 2 + 2i0 + 3i5 and "
4252 	    "3i5 <= 2 - 2i0 - i2 + 3i4 and i6 <= 2 + 2i0 + 3i1 and "
4253 	    "i0 <= -1 and i7 <= i2 + i3 - 3i4 - i6 and "
4254 	    "3i5 >= -2i0 - i2 + 3i4 }";
4255 	bset = isl_basic_set_read_from_str(ctx, str);
4256 	f = isl_basic_set_factorizer(bset);
4257 	isl_basic_set_free(bset);
4258 	isl_factorizer_free(f);
4259 	if (!f)
4260 		isl_die(ctx, isl_error_unknown,
4261 			"failed to construct factorizer", return -1);
4262 
4263 	str = "{ [i0, i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11, i12] : "
4264 	    "i12 <= 2 + i0 - i11 and 2i8 >= -i4 and i11 >= i1 and "
4265 	    "3i5 <= -i2 and 2i11 >= -i4 - 2i7 and i11 <= 3 + i0 + 3i9 and "
4266 	    "i11 <= -i4 - 2i7 and i12 >= -i10 and i2 >= -2 and "
4267 	    "i11 >= i1 + 3i10 and i11 >= 1 + i0 + 3i9 and "
4268 	    "i11 <= 1 - i4 - 2i8 and 6i6 <= 6 - i2 and 3i6 >= 1 - i2 and "
4269 	    "i11 <= 2 + i1 and i12 <= i4 + i11 and i12 >= i0 - i11 and "
4270 	    "3i5 >= -2 - i2 and i12 >= -1 + i4 + i11 and 3i3 <= 3 - i2 and "
4271 	    "9i6 <= 11 - i2 + 6i5 and 3i3 >= 1 - i2 and "
4272 	    "9i6 <= 5 - i2 + 6i3 and i12 <= -1 and i2 <= 0 }";
4273 	bset = isl_basic_set_read_from_str(ctx, str);
4274 	f = isl_basic_set_factorizer(bset);
4275 	isl_basic_set_free(bset);
4276 	isl_factorizer_free(f);
4277 	if (!f)
4278 		isl_die(ctx, isl_error_unknown,
4279 			"failed to construct factorizer", return -1);
4280 
4281 	return 0;
4282 }
4283 
check_injective(__isl_take isl_map * map,void * user)4284 static isl_stat check_injective(__isl_take isl_map *map, void *user)
4285 {
4286 	int *injective = user;
4287 
4288 	*injective = isl_map_is_injective(map);
4289 	isl_map_free(map);
4290 
4291 	if (*injective < 0 || !*injective)
4292 		return isl_stat_error;
4293 
4294 	return isl_stat_ok;
4295 }
4296 
test_one_schedule(isl_ctx * ctx,const char * d,const char * w,const char * r,const char * s,int tilable,int parallel)4297 int test_one_schedule(isl_ctx *ctx, const char *d, const char *w,
4298 	const char *r, const char *s, int tilable, int parallel)
4299 {
4300 	int i;
4301 	isl_union_set *D;
4302 	isl_union_map *W, *R, *S;
4303 	isl_union_map *empty;
4304 	isl_union_map *dep_raw, *dep_war, *dep_waw, *dep;
4305 	isl_union_map *validity, *proximity, *coincidence;
4306 	isl_union_map *schedule;
4307 	isl_union_map *test;
4308 	isl_union_set *delta;
4309 	isl_union_set *domain;
4310 	isl_set *delta_set;
4311 	isl_set *slice;
4312 	isl_set *origin;
4313 	isl_schedule_constraints *sc;
4314 	isl_schedule *sched;
4315 	int is_nonneg, is_parallel, is_tilable, is_injection, is_complete;
4316 	isl_size n;
4317 
4318 	D = isl_union_set_read_from_str(ctx, d);
4319 	W = isl_union_map_read_from_str(ctx, w);
4320 	R = isl_union_map_read_from_str(ctx, r);
4321 	S = isl_union_map_read_from_str(ctx, s);
4322 
4323 	W = isl_union_map_intersect_domain(W, isl_union_set_copy(D));
4324 	R = isl_union_map_intersect_domain(R, isl_union_set_copy(D));
4325 
4326 	empty = isl_union_map_empty(isl_union_map_get_space(S));
4327         isl_union_map_compute_flow(isl_union_map_copy(R),
4328 				   isl_union_map_copy(W), empty,
4329 				   isl_union_map_copy(S),
4330 				   &dep_raw, NULL, NULL, NULL);
4331         isl_union_map_compute_flow(isl_union_map_copy(W),
4332 				   isl_union_map_copy(W),
4333 				   isl_union_map_copy(R),
4334 				   isl_union_map_copy(S),
4335 				   &dep_waw, &dep_war, NULL, NULL);
4336 
4337 	dep = isl_union_map_union(dep_waw, dep_war);
4338 	dep = isl_union_map_union(dep, dep_raw);
4339 	validity = isl_union_map_copy(dep);
4340 	coincidence = isl_union_map_copy(dep);
4341 	proximity = isl_union_map_copy(dep);
4342 
4343 	sc = isl_schedule_constraints_on_domain(isl_union_set_copy(D));
4344 	sc = isl_schedule_constraints_set_validity(sc, validity);
4345 	sc = isl_schedule_constraints_set_coincidence(sc, coincidence);
4346 	sc = isl_schedule_constraints_set_proximity(sc, proximity);
4347 	sched = isl_schedule_constraints_compute_schedule(sc);
4348 	schedule = isl_schedule_get_map(sched);
4349 	isl_schedule_free(sched);
4350 	isl_union_map_free(W);
4351 	isl_union_map_free(R);
4352 	isl_union_map_free(S);
4353 
4354 	is_injection = 1;
4355 	isl_union_map_foreach_map(schedule, &check_injective, &is_injection);
4356 
4357 	domain = isl_union_map_domain(isl_union_map_copy(schedule));
4358 	is_complete = isl_union_set_is_subset(D, domain);
4359 	isl_union_set_free(D);
4360 	isl_union_set_free(domain);
4361 
4362 	test = isl_union_map_reverse(isl_union_map_copy(schedule));
4363 	test = isl_union_map_apply_range(test, dep);
4364 	test = isl_union_map_apply_range(test, schedule);
4365 
4366 	delta = isl_union_map_deltas(test);
4367 	n = isl_union_set_n_set(delta);
4368 	if (n < 0) {
4369 		isl_union_set_free(delta);
4370 		return -1;
4371 	}
4372 	if (n == 0) {
4373 		is_tilable = 1;
4374 		is_parallel = 1;
4375 		is_nonneg = 1;
4376 		isl_union_set_free(delta);
4377 	} else {
4378 		isl_size dim;
4379 
4380 		delta_set = isl_set_from_union_set(delta);
4381 
4382 		slice = isl_set_universe(isl_set_get_space(delta_set));
4383 		for (i = 0; i < tilable; ++i)
4384 			slice = isl_set_lower_bound_si(slice, isl_dim_set, i, 0);
4385 		is_tilable = isl_set_is_subset(delta_set, slice);
4386 		isl_set_free(slice);
4387 
4388 		slice = isl_set_universe(isl_set_get_space(delta_set));
4389 		for (i = 0; i < parallel; ++i)
4390 			slice = isl_set_fix_si(slice, isl_dim_set, i, 0);
4391 		is_parallel = isl_set_is_subset(delta_set, slice);
4392 		isl_set_free(slice);
4393 
4394 		origin = isl_set_universe(isl_set_get_space(delta_set));
4395 		dim = isl_set_dim(origin, isl_dim_set);
4396 		if (dim < 0)
4397 			origin = isl_set_free(origin);
4398 		for (i = 0; i < dim; ++i)
4399 			origin = isl_set_fix_si(origin, isl_dim_set, i, 0);
4400 
4401 		delta_set = isl_set_union(delta_set, isl_set_copy(origin));
4402 		delta_set = isl_set_lexmin(delta_set);
4403 
4404 		is_nonneg = isl_set_is_equal(delta_set, origin);
4405 
4406 		isl_set_free(origin);
4407 		isl_set_free(delta_set);
4408 	}
4409 
4410 	if (is_nonneg < 0 || is_parallel < 0 || is_tilable < 0 ||
4411 	    is_injection < 0 || is_complete < 0)
4412 		return -1;
4413 	if (!is_complete)
4414 		isl_die(ctx, isl_error_unknown,
4415 			"generated schedule incomplete", return -1);
4416 	if (!is_injection)
4417 		isl_die(ctx, isl_error_unknown,
4418 			"generated schedule not injective on each statement",
4419 			return -1);
4420 	if (!is_nonneg)
4421 		isl_die(ctx, isl_error_unknown,
4422 			"negative dependences in generated schedule",
4423 			return -1);
4424 	if (!is_tilable)
4425 		isl_die(ctx, isl_error_unknown,
4426 			"generated schedule not as tilable as expected",
4427 			return -1);
4428 	if (!is_parallel)
4429 		isl_die(ctx, isl_error_unknown,
4430 			"generated schedule not as parallel as expected",
4431 			return -1);
4432 
4433 	return 0;
4434 }
4435 
4436 /* Compute a schedule for the given instance set, validity constraints,
4437  * proximity constraints and context and return a corresponding union map
4438  * representation.
4439  */
compute_schedule_with_context(isl_ctx * ctx,const char * domain,const char * validity,const char * proximity,const char * context)4440 static __isl_give isl_union_map *compute_schedule_with_context(isl_ctx *ctx,
4441 	const char *domain, const char *validity, const char *proximity,
4442 	const char *context)
4443 {
4444 	isl_set *con;
4445 	isl_union_set *dom;
4446 	isl_union_map *dep;
4447 	isl_union_map *prox;
4448 	isl_schedule_constraints *sc;
4449 	isl_schedule *schedule;
4450 	isl_union_map *sched;
4451 
4452 	con = isl_set_read_from_str(ctx, context);
4453 	dom = isl_union_set_read_from_str(ctx, domain);
4454 	dep = isl_union_map_read_from_str(ctx, validity);
4455 	prox = isl_union_map_read_from_str(ctx, proximity);
4456 	sc = isl_schedule_constraints_on_domain(dom);
4457 	sc = isl_schedule_constraints_set_context(sc, con);
4458 	sc = isl_schedule_constraints_set_validity(sc, dep);
4459 	sc = isl_schedule_constraints_set_proximity(sc, prox);
4460 	schedule = isl_schedule_constraints_compute_schedule(sc);
4461 	sched = isl_schedule_get_map(schedule);
4462 	isl_schedule_free(schedule);
4463 
4464 	return sched;
4465 }
4466 
4467 /* Compute a schedule for the given instance set, validity constraints and
4468  * proximity constraints and return a corresponding union map representation.
4469  */
compute_schedule(isl_ctx * ctx,const char * domain,const char * validity,const char * proximity)4470 static __isl_give isl_union_map *compute_schedule(isl_ctx *ctx,
4471 	const char *domain, const char *validity, const char *proximity)
4472 {
4473 	return compute_schedule_with_context(ctx, domain, validity, proximity,
4474 						"{ : }");
4475 }
4476 
4477 /* Check that a schedule can be constructed on the given domain
4478  * with the given validity and proximity constraints.
4479  */
test_has_schedule(isl_ctx * ctx,const char * domain,const char * validity,const char * proximity)4480 static int test_has_schedule(isl_ctx *ctx, const char *domain,
4481 	const char *validity, const char *proximity)
4482 {
4483 	isl_union_map *sched;
4484 
4485 	sched = compute_schedule(ctx, domain, validity, proximity);
4486 	if (!sched)
4487 		return -1;
4488 
4489 	isl_union_map_free(sched);
4490 	return 0;
4491 }
4492 
test_special_schedule(isl_ctx * ctx,const char * domain,const char * validity,const char * proximity,const char * expected_sched)4493 int test_special_schedule(isl_ctx *ctx, const char *domain,
4494 	const char *validity, const char *proximity, const char *expected_sched)
4495 {
4496 	isl_union_map *sched1, *sched2;
4497 	int equal;
4498 
4499 	sched1 = compute_schedule(ctx, domain, validity, proximity);
4500 	sched2 = isl_union_map_read_from_str(ctx, expected_sched);
4501 
4502 	equal = isl_union_map_is_equal(sched1, sched2);
4503 	isl_union_map_free(sched1);
4504 	isl_union_map_free(sched2);
4505 
4506 	if (equal < 0)
4507 		return -1;
4508 	if (!equal)
4509 		isl_die(ctx, isl_error_unknown, "unexpected schedule",
4510 			return -1);
4511 
4512 	return 0;
4513 }
4514 
4515 /* Check that the schedule map is properly padded, i.e., that the range
4516  * lives in a single space.
4517  */
test_padded_schedule(isl_ctx * ctx)4518 static int test_padded_schedule(isl_ctx *ctx)
4519 {
4520 	const char *str;
4521 	isl_union_set *D;
4522 	isl_union_map *validity, *proximity;
4523 	isl_schedule_constraints *sc;
4524 	isl_schedule *sched;
4525 	isl_union_map *umap;
4526 	isl_union_set *range;
4527 	isl_set *set;
4528 
4529 	str = "[N] -> { S0[i] : 0 <= i <= N; S1[i, j] : 0 <= i, j <= N }";
4530 	D = isl_union_set_read_from_str(ctx, str);
4531 	validity = isl_union_map_empty(isl_union_set_get_space(D));
4532 	proximity = isl_union_map_copy(validity);
4533 	sc = isl_schedule_constraints_on_domain(D);
4534 	sc = isl_schedule_constraints_set_validity(sc, validity);
4535 	sc = isl_schedule_constraints_set_proximity(sc, proximity);
4536 	sched = isl_schedule_constraints_compute_schedule(sc);
4537 	umap = isl_schedule_get_map(sched);
4538 	isl_schedule_free(sched);
4539 	range = isl_union_map_range(umap);
4540 	set = isl_set_from_union_set(range);
4541 	isl_set_free(set);
4542 
4543 	if (!set)
4544 		return -1;
4545 
4546 	return 0;
4547 }
4548 
4549 /* Check that conditional validity constraints are also taken into
4550  * account across bands.
4551  * In particular, try to make sure that live ranges D[1,0]->C[2,1] and
4552  * D[2,0]->C[3,0] are not local in the outer band of the generated schedule
4553  * and then check that the adjacent order constraint C[2,1]->D[2,0]
4554  * is enforced by the rest of the schedule.
4555  */
test_special_conditional_schedule_constraints(isl_ctx * ctx)4556 static int test_special_conditional_schedule_constraints(isl_ctx *ctx)
4557 {
4558 	const char *str;
4559 	isl_union_set *domain;
4560 	isl_union_map *validity, *proximity, *condition;
4561 	isl_union_map *sink, *source, *dep;
4562 	isl_schedule_constraints *sc;
4563 	isl_schedule *schedule;
4564 	isl_union_access_info *access;
4565 	isl_union_flow *flow;
4566 	int empty;
4567 
4568 	str = "[n] -> { C[k, i] : k <= -1 + n and i >= 0 and i <= -1 + k; "
4569 	    "A[k] : k >= 1 and k <= -1 + n; "
4570 	    "B[k, i] : k <= -1 + n and i >= 0 and i <= -1 + k; "
4571 	    "D[k, i] : k <= -1 + n and i >= 0 and i <= -1 + k }";
4572 	domain = isl_union_set_read_from_str(ctx, str);
4573 	sc = isl_schedule_constraints_on_domain(domain);
4574 	str = "[n] -> { D[k, i] -> C[1 + k, k - i] : "
4575 		"k <= -2 + n and i >= 1 and i <= -1 + k; "
4576 		"D[k, i] -> C[1 + k, i] : "
4577 		"k <= -2 + n and i >= 1 and i <= -1 + k; "
4578 		"D[k, 0] -> C[1 + k, k] : k >= 1 and k <= -2 + n; "
4579 		"D[k, 0] -> C[1 + k, 0] : k >= 1 and k <= -2 + n }";
4580 	validity = isl_union_map_read_from_str(ctx, str);
4581 	sc = isl_schedule_constraints_set_validity(sc, validity);
4582 	str = "[n] -> { C[k, i] -> D[k, i] : "
4583 		"0 <= i <= -1 + k and k <= -1 + n }";
4584 	proximity = isl_union_map_read_from_str(ctx, str);
4585 	sc = isl_schedule_constraints_set_proximity(sc, proximity);
4586 	str = "[n] -> { [D[k, i] -> a[]] -> [C[1 + k, k - i] -> b[]] : "
4587 		"i <= -1 + k and i >= 1 and k <= -2 + n; "
4588 		"[B[k, i] -> c[]] -> [B[k, 1 + i] -> c[]] : "
4589 		"k <= -1 + n and i >= 0 and i <= -2 + k }";
4590 	condition = isl_union_map_read_from_str(ctx, str);
4591 	str = "[n] -> { [B[k, i] -> e[]] -> [D[k, i] -> a[]] : "
4592 		"i >= 0 and i <= -1 + k and k <= -1 + n; "
4593 		"[C[k, i] -> b[]] -> [D[k', -1 + k - i] -> a[]] : "
4594 		"i >= 0 and i <= -1 + k and k <= -1 + n and "
4595 		"k' <= -1 + n and k' >= k - i and k' >= 1 + k; "
4596 		"[C[k, i] -> b[]] -> [D[k, -1 + k - i] -> a[]] : "
4597 		"i >= 0 and i <= -1 + k and k <= -1 + n; "
4598 		"[B[k, i] -> c[]] -> [A[k'] -> d[]] : "
4599 		"k <= -1 + n and i >= 0 and i <= -1 + k and "
4600 		"k' >= 1 and k' <= -1 + n and k' >= 1 + k }";
4601 	validity = isl_union_map_read_from_str(ctx, str);
4602 	sc = isl_schedule_constraints_set_conditional_validity(sc, condition,
4603 								validity);
4604 	schedule = isl_schedule_constraints_compute_schedule(sc);
4605 	str = "{ D[2,0] -> [] }";
4606 	sink = isl_union_map_read_from_str(ctx, str);
4607 	access = isl_union_access_info_from_sink(sink);
4608 	str = "{ C[2,1] -> [] }";
4609 	source = isl_union_map_read_from_str(ctx, str);
4610 	access = isl_union_access_info_set_must_source(access, source);
4611 	access = isl_union_access_info_set_schedule(access, schedule);
4612 	flow = isl_union_access_info_compute_flow(access);
4613 	dep = isl_union_flow_get_must_dependence(flow);
4614 	isl_union_flow_free(flow);
4615 	empty = isl_union_map_is_empty(dep);
4616 	isl_union_map_free(dep);
4617 
4618 	if (empty < 0)
4619 		return -1;
4620 	if (empty)
4621 		isl_die(ctx, isl_error_unknown,
4622 			"conditional validity not respected", return -1);
4623 
4624 	return 0;
4625 }
4626 
4627 /* Check that the test for violated conditional validity constraints
4628  * is not confused by domain compression.
4629  * In particular, earlier versions of isl would apply
4630  * a schedule on the compressed domains to the original domains,
4631  * resulting in a failure to detect that the default schedule
4632  * violates the conditional validity constraints.
4633  */
test_special_conditional_schedule_constraints_2(isl_ctx * ctx)4634 static int test_special_conditional_schedule_constraints_2(isl_ctx *ctx)
4635 {
4636 	const char *str;
4637 	isl_bool empty;
4638 	isl_union_set *domain;
4639 	isl_union_map *validity, *condition;
4640 	isl_schedule_constraints *sc;
4641 	isl_schedule *schedule;
4642 	isl_union_map *umap;
4643 	isl_map *map, *ge;
4644 
4645 	str = "{ A[0, i] : 0 <= i <= 10; B[1, i] : 0 <= i <= 10 }";
4646 	domain = isl_union_set_read_from_str(ctx, str);
4647 	sc = isl_schedule_constraints_on_domain(domain);
4648 	str = "{ B[1, i] -> A[0, i + 1] }";
4649 	condition = isl_union_map_read_from_str(ctx, str);
4650 	str = "{ A[0, i] -> B[1, i - 1] }";
4651 	validity = isl_union_map_read_from_str(ctx, str);
4652 	sc = isl_schedule_constraints_set_conditional_validity(sc, condition,
4653 						isl_union_map_copy(validity));
4654 	schedule = isl_schedule_constraints_compute_schedule(sc);
4655 	umap = isl_schedule_get_map(schedule);
4656 	isl_schedule_free(schedule);
4657 	validity = isl_union_map_apply_domain(validity,
4658 						isl_union_map_copy(umap));
4659 	validity = isl_union_map_apply_range(validity, umap);
4660 	map = isl_map_from_union_map(validity);
4661 	ge = isl_map_lex_ge(isl_space_domain(isl_map_get_space(map)));
4662 	map = isl_map_intersect(map, ge);
4663 	empty = isl_map_is_empty(map);
4664 	isl_map_free(map);
4665 
4666 	if (empty < 0)
4667 		return -1;
4668 	if (!empty)
4669 		isl_die(ctx, isl_error_unknown,
4670 			"conditional validity constraints not satisfied",
4671 			return -1);
4672 
4673 	return 0;
4674 }
4675 
4676 /* Input for testing of schedule construction based on
4677  * conditional constraints.
4678  *
4679  * domain is the iteration domain
4680  * flow are the flow dependences, which determine the validity and
4681  * 	proximity constraints
4682  * condition are the conditions on the conditional validity constraints
4683  * conditional_validity are the conditional validity constraints
4684  * outer_band_n is the expected number of members in the outer band
4685  */
4686 struct {
4687 	const char *domain;
4688 	const char *flow;
4689 	const char *condition;
4690 	const char *conditional_validity;
4691 	int outer_band_n;
4692 } live_range_tests[] = {
4693 	/* Contrived example that illustrates that we need to keep
4694 	 * track of tagged condition dependences and
4695 	 * tagged conditional validity dependences
4696 	 * in isl_sched_edge separately.
4697 	 * In particular, the conditional validity constraints on A
4698 	 * cannot be satisfied,
4699 	 * but they can be ignored because there are no corresponding
4700 	 * condition constraints.  However, we do have an additional
4701 	 * conditional validity constraint that maps to the same
4702 	 * dependence relation
4703 	 * as the condition constraint on B.  If we did not make a distinction
4704 	 * between tagged condition and tagged conditional validity
4705 	 * dependences, then we
4706 	 * could end up treating this shared dependence as an condition
4707 	 * constraint on A, forcing a localization of the conditions,
4708 	 * which is impossible.
4709 	 */
4710 	{ "{ S[i] : 0 <= 1 < 100; T[i] : 0 <= 1 < 100 }",
4711 	  "{ S[i] -> S[i+1] : 0 <= i < 99 }",
4712 	  "{ [S[i] -> B[]] -> [S[i+1] -> B[]] : 0 <= i < 99 }",
4713 	  "{ [S[i] -> A[]] -> [T[i'] -> A[]] : 0 <= i', i < 100 and i != i';"
4714 	    "[T[i] -> A[]] -> [S[i'] -> A[]] : 0 <= i', i < 100 and i != i';"
4715 	    "[S[i] -> A[]] -> [S[i+1] -> A[]] : 0 <= i < 99 }",
4716 	  1
4717 	},
4718 	/* TACO 2013 Fig. 7 */
4719 	{ "[n] -> { S1[i,j] : 0 <= i,j < n; S2[i,j] : 0 <= i,j < n }",
4720 	  "[n] -> { S1[i,j] -> S2[i,j] : 0 <= i,j < n;"
4721 		   "S2[i,j] -> S2[i,j+1] : 0 <= i < n and 0 <= j < n - 1 }",
4722 	  "[n] -> { [S1[i,j] -> t[]] -> [S2[i,j] -> t[]] : 0 <= i,j < n;"
4723 		   "[S2[i,j] -> x1[]] -> [S2[i,j+1] -> x1[]] : "
4724 				"0 <= i < n and 0 <= j < n - 1 }",
4725 	  "[n] -> { [S2[i,j] -> t[]] -> [S1[i,j'] -> t[]] : "
4726 				"0 <= i < n and 0 <= j < j' < n;"
4727 		   "[S2[i,j] -> t[]] -> [S1[i',j'] -> t[]] : "
4728 				"0 <= i < i' < n and 0 <= j,j' < n;"
4729 		   "[S2[i,j] -> x1[]] -> [S2[i,j'] -> x1[]] : "
4730 				"0 <= i,j,j' < n and j < j' }",
4731 	    2
4732 	},
4733 	/* TACO 2013 Fig. 7, without tags */
4734 	{ "[n] -> { S1[i,j] : 0 <= i,j < n; S2[i,j] : 0 <= i,j < n }",
4735 	  "[n] -> { S1[i,j] -> S2[i,j] : 0 <= i,j < n;"
4736 		   "S2[i,j] -> S2[i,j+1] : 0 <= i < n and 0 <= j < n - 1 }",
4737 	  "[n] -> { S1[i,j] -> S2[i,j] : 0 <= i,j < n;"
4738 		   "S2[i,j] -> S2[i,j+1] : 0 <= i < n and 0 <= j < n - 1 }",
4739 	  "[n] -> { S2[i,j] -> S1[i,j'] : 0 <= i < n and 0 <= j < j' < n;"
4740 		   "S2[i,j] -> S1[i',j'] : 0 <= i < i' < n and 0 <= j,j' < n;"
4741 		   "S2[i,j] -> S2[i,j'] : 0 <= i,j,j' < n and j < j' }",
4742 	   1
4743 	},
4744 	/* TACO 2013 Fig. 12 */
4745 	{ "{ S1[i,0] : 0 <= i <= 1; S2[i,j] : 0 <= i <= 1 and 1 <= j <= 2;"
4746 	    "S3[i,3] : 0 <= i <= 1 }",
4747 	  "{ S1[i,0] -> S2[i,1] : 0 <= i <= 1;"
4748 	    "S2[i,1] -> S2[i,2] : 0 <= i <= 1;"
4749 	    "S2[i,2] -> S3[i,3] : 0 <= i <= 1 }",
4750 	  "{ [S1[i,0]->t[]] -> [S2[i,1]->t[]] : 0 <= i <= 1;"
4751 	    "[S2[i,1]->t[]] -> [S2[i,2]->t[]] : 0 <= i <= 1;"
4752 	    "[S2[i,2]->t[]] -> [S3[i,3]->t[]] : 0 <= i <= 1 }",
4753 	  "{ [S2[i,1]->t[]] -> [S2[i,2]->t[]] : 0 <= i <= 1;"
4754 	    "[S2[0,j]->t[]] -> [S2[1,j']->t[]] : 1 <= j,j' <= 2;"
4755 	    "[S2[0,j]->t[]] -> [S1[1,0]->t[]] : 1 <= j <= 2;"
4756 	    "[S3[0,3]->t[]] -> [S2[1,j]->t[]] : 1 <= j <= 2;"
4757 	    "[S3[0,3]->t[]] -> [S1[1,0]->t[]] }",
4758 	   1
4759 	}
4760 };
4761 
4762 /* Test schedule construction based on conditional constraints.
4763  * In particular, check the number of members in the outer band node
4764  * as an indication of whether tiling is possible or not.
4765  */
test_conditional_schedule_constraints(isl_ctx * ctx)4766 static int test_conditional_schedule_constraints(isl_ctx *ctx)
4767 {
4768 	int i;
4769 	isl_union_set *domain;
4770 	isl_union_map *condition;
4771 	isl_union_map *flow;
4772 	isl_union_map *validity;
4773 	isl_schedule_constraints *sc;
4774 	isl_schedule *schedule;
4775 	isl_schedule_node *node;
4776 	isl_size n_member;
4777 
4778 	if (test_special_conditional_schedule_constraints(ctx) < 0)
4779 		return -1;
4780 	if (test_special_conditional_schedule_constraints_2(ctx) < 0)
4781 		return -1;
4782 
4783 	for (i = 0; i < ARRAY_SIZE(live_range_tests); ++i) {
4784 		domain = isl_union_set_read_from_str(ctx,
4785 				live_range_tests[i].domain);
4786 		flow = isl_union_map_read_from_str(ctx,
4787 				live_range_tests[i].flow);
4788 		condition = isl_union_map_read_from_str(ctx,
4789 				live_range_tests[i].condition);
4790 		validity = isl_union_map_read_from_str(ctx,
4791 				live_range_tests[i].conditional_validity);
4792 		sc = isl_schedule_constraints_on_domain(domain);
4793 		sc = isl_schedule_constraints_set_validity(sc,
4794 				isl_union_map_copy(flow));
4795 		sc = isl_schedule_constraints_set_proximity(sc, flow);
4796 		sc = isl_schedule_constraints_set_conditional_validity(sc,
4797 				condition, validity);
4798 		schedule = isl_schedule_constraints_compute_schedule(sc);
4799 		node = isl_schedule_get_root(schedule);
4800 		while (node &&
4801 		    isl_schedule_node_get_type(node) != isl_schedule_node_band)
4802 			node = isl_schedule_node_first_child(node);
4803 		n_member = isl_schedule_node_band_n_member(node);
4804 		isl_schedule_node_free(node);
4805 		isl_schedule_free(schedule);
4806 
4807 		if (!schedule || n_member < 0)
4808 			return -1;
4809 		if (n_member != live_range_tests[i].outer_band_n)
4810 			isl_die(ctx, isl_error_unknown,
4811 				"unexpected number of members in outer band",
4812 				return -1);
4813 	}
4814 	return 0;
4815 }
4816 
4817 /* Check that the schedule computed for the given instance set and
4818  * dependence relation strongly satisfies the dependences.
4819  * In particular, check that no instance is scheduled before
4820  * or together with an instance on which it depends.
4821  * Earlier versions of isl would produce a schedule that
4822  * only weakly satisfies the dependences.
4823  */
test_strongly_satisfying_schedule(isl_ctx * ctx)4824 static int test_strongly_satisfying_schedule(isl_ctx *ctx)
4825 {
4826 	const char *domain, *dep;
4827 	isl_union_map *D, *schedule;
4828 	isl_map *map, *ge;
4829 	int empty;
4830 
4831 	domain = "{ B[i0, i1] : 0 <= i0 <= 1 and 0 <= i1 <= 11; "
4832 		    "A[i0] : 0 <= i0 <= 1 }";
4833 	dep = "{ B[i0, i1] -> B[i0, 1 + i1] : 0 <= i0 <= 1 and 0 <= i1 <= 10; "
4834 		"B[0, 11] -> A[1]; A[i0] -> B[i0, 0] : 0 <= i0 <= 1 }";
4835 	schedule = compute_schedule(ctx, domain, dep, dep);
4836 	D = isl_union_map_read_from_str(ctx, dep);
4837 	D = isl_union_map_apply_domain(D, isl_union_map_copy(schedule));
4838 	D = isl_union_map_apply_range(D, schedule);
4839 	map = isl_map_from_union_map(D);
4840 	ge = isl_map_lex_ge(isl_space_domain(isl_map_get_space(map)));
4841 	map = isl_map_intersect(map, ge);
4842 	empty = isl_map_is_empty(map);
4843 	isl_map_free(map);
4844 
4845 	if (empty < 0)
4846 		return -1;
4847 	if (!empty)
4848 		isl_die(ctx, isl_error_unknown,
4849 			"dependences not strongly satisfied", return -1);
4850 
4851 	return 0;
4852 }
4853 
4854 /* Compute a schedule for input where the instance set constraints
4855  * conflict with the context constraints.
4856  * Earlier versions of isl did not properly handle this situation.
4857  */
test_conflicting_context_schedule(isl_ctx * ctx)4858 static int test_conflicting_context_schedule(isl_ctx *ctx)
4859 {
4860 	isl_union_map *schedule;
4861 	const char *domain, *context;
4862 
4863 	domain = "[n] -> { A[] : n >= 0 }";
4864 	context = "[n] -> { : n < 0 }";
4865 	schedule = compute_schedule_with_context(ctx,
4866 						domain, "{}", "{}", context);
4867 	isl_union_map_free(schedule);
4868 
4869 	if (!schedule)
4870 		return -1;
4871 
4872 	return 0;
4873 }
4874 
4875 /* Check that a set of schedule constraints that only allow for
4876  * a coalescing schedule still produces a schedule even if the user
4877  * request a non-coalescing schedule.  Earlier versions of isl
4878  * would not handle this case correctly.
4879  */
test_coalescing_schedule(isl_ctx * ctx)4880 static int test_coalescing_schedule(isl_ctx *ctx)
4881 {
4882 	const char *domain, *dep;
4883 	isl_union_set *I;
4884 	isl_union_map *D;
4885 	isl_schedule_constraints *sc;
4886 	isl_schedule *schedule;
4887 	int treat_coalescing;
4888 
4889 	domain = "{ S[a, b] : 0 <= a <= 1 and 0 <= b <= 1 }";
4890 	dep = "{ S[a, b] -> S[a + b, 1 - b] }";
4891 	I = isl_union_set_read_from_str(ctx, domain);
4892 	D = isl_union_map_read_from_str(ctx, dep);
4893 	sc = isl_schedule_constraints_on_domain(I);
4894 	sc = isl_schedule_constraints_set_validity(sc, D);
4895 	treat_coalescing = isl_options_get_schedule_treat_coalescing(ctx);
4896 	isl_options_set_schedule_treat_coalescing(ctx, 1);
4897 	schedule = isl_schedule_constraints_compute_schedule(sc);
4898 	isl_options_set_schedule_treat_coalescing(ctx, treat_coalescing);
4899 	isl_schedule_free(schedule);
4900 	if (!schedule)
4901 		return -1;
4902 	return 0;
4903 }
4904 
4905 /* Check that the scheduler does not perform any needless
4906  * compound skewing.  Earlier versions of isl would compute
4907  * schedules in terms of transformed schedule coefficients and
4908  * would not accurately keep track of the sum of the original
4909  * schedule coefficients.  It could then produce the schedule
4910  * S[t,i,j,k] -> [t, 2t + i, 2t + i + j, 2t + i + j + k]
4911  * for the input below instead of the schedule below.
4912  */
test_skewing_schedule(isl_ctx * ctx)4913 static int test_skewing_schedule(isl_ctx *ctx)
4914 {
4915 	const char *D, *V, *P, *S;
4916 
4917 	D = "[n] -> { S[t,i,j,k] : 0 <= t,i,j,k < n }";
4918 	V = "[n] -> { S[t,i,j,k] -> S[t+1,a,b,c] : 0 <= t,i,j,k,a,b,c < n and "
4919 		"-2 <= a-i <= 2 and -1 <= a-i + b-j <= 1 and "
4920 		"-1 <= a-i + b-j + c-k <= 1 }";
4921 	P = "{ }";
4922 	S = "{ S[t,i,j,k] -> [t, 2t + i, t + i + j, 2t + k] }";
4923 
4924 	return test_special_schedule(ctx, D, V, P, S);
4925 }
4926 
test_schedule(isl_ctx * ctx)4927 int test_schedule(isl_ctx *ctx)
4928 {
4929 	const char *D, *W, *R, *V, *P, *S;
4930 	int max_coincidence;
4931 	int treat_coalescing;
4932 
4933 	/* Handle resulting schedule with zero bands. */
4934 	if (test_one_schedule(ctx, "{[]}", "{}", "{}", "{[] -> []}", 0, 0) < 0)
4935 		return -1;
4936 
4937 	/* Jacobi */
4938 	D = "[T,N] -> { S1[t,i] : 1 <= t <= T and 2 <= i <= N - 1 }";
4939 	W = "{ S1[t,i] -> a[t,i] }";
4940 	R = "{ S1[t,i] -> a[t-1,i]; S1[t,i] -> a[t-1,i-1]; "
4941 	    	"S1[t,i] -> a[t-1,i+1] }";
4942 	S = "{ S1[t,i] -> [t,i] }";
4943 	if (test_one_schedule(ctx, D, W, R, S, 2, 0) < 0)
4944 		return -1;
4945 
4946 	/* Fig. 5 of CC2008 */
4947 	D = "[N] -> { S_0[i, j] : i >= 0 and i <= -1 + N and j >= 2 and "
4948 				"j <= -1 + N }";
4949 	W = "[N] -> { S_0[i, j] -> a[i, j] : i >= 0 and i <= -1 + N and "
4950 				"j >= 2 and j <= -1 + N }";
4951 	R = "[N] -> { S_0[i, j] -> a[j, i] : i >= 0 and i <= -1 + N and "
4952 				"j >= 2 and j <= -1 + N; "
4953 		    "S_0[i, j] -> a[i, -1 + j] : i >= 0 and i <= -1 + N and "
4954 				"j >= 2 and j <= -1 + N }";
4955 	S = "[N] -> { S_0[i, j] -> [0, i, 0, j, 0] }";
4956 	if (test_one_schedule(ctx, D, W, R, S, 2, 0) < 0)
4957 		return -1;
4958 
4959 	D = "{ S1[i] : 0 <= i <= 10; S2[i] : 0 <= i <= 9 }";
4960 	W = "{ S1[i] -> a[i] }";
4961 	R = "{ S2[i] -> a[i+1] }";
4962 	S = "{ S1[i] -> [0,i]; S2[i] -> [1,i] }";
4963 	if (test_one_schedule(ctx, D, W, R, S, 1, 1) < 0)
4964 		return -1;
4965 
4966 	D = "{ S1[i] : 0 <= i < 10; S2[i] : 0 <= i < 10 }";
4967 	W = "{ S1[i] -> a[i] }";
4968 	R = "{ S2[i] -> a[9-i] }";
4969 	S = "{ S1[i] -> [0,i]; S2[i] -> [1,i] }";
4970 	if (test_one_schedule(ctx, D, W, R, S, 1, 1) < 0)
4971 		return -1;
4972 
4973 	D = "[N] -> { S1[i] : 0 <= i < N; S2[i] : 0 <= i < N }";
4974 	W = "{ S1[i] -> a[i] }";
4975 	R = "[N] -> { S2[i] -> a[N-1-i] }";
4976 	S = "{ S1[i] -> [0,i]; S2[i] -> [1,i] }";
4977 	if (test_one_schedule(ctx, D, W, R, S, 1, 1) < 0)
4978 		return -1;
4979 
4980 	D = "{ S1[i] : 0 < i < 10; S2[i] : 0 <= i < 10 }";
4981 	W = "{ S1[i] -> a[i]; S2[i] -> b[i] }";
4982 	R = "{ S2[i] -> a[i]; S1[i] -> b[i-1] }";
4983 	S = "{ S1[i] -> [i,0]; S2[i] -> [i,1] }";
4984 	if (test_one_schedule(ctx, D, W, R, S, 0, 0) < 0)
4985 		return -1;
4986 
4987 	D = "[N] -> { S1[i] : 1 <= i <= N; S2[i,j] : 1 <= i,j <= N }";
4988 	W = "{ S1[i] -> a[0,i]; S2[i,j] -> a[i,j] }";
4989 	R = "{ S2[i,j] -> a[i-1,j] }";
4990 	S = "{ S1[i] -> [0,i,0]; S2[i,j] -> [1,i,j] }";
4991 	if (test_one_schedule(ctx, D, W, R, S, 2, 1) < 0)
4992 		return -1;
4993 
4994 	D = "[N] -> { S1[i] : 1 <= i <= N; S2[i,j] : 1 <= i,j <= N }";
4995 	W = "{ S1[i] -> a[i,0]; S2[i,j] -> a[i,j] }";
4996 	R = "{ S2[i,j] -> a[i,j-1] }";
4997 	S = "{ S1[i] -> [0,i,0]; S2[i,j] -> [1,i,j] }";
4998 	if (test_one_schedule(ctx, D, W, R, S, 2, 1) < 0)
4999 		return -1;
5000 
5001 	D = "[N] -> { S_0[]; S_1[i] : i >= 0 and i <= -1 + N; S_2[] }";
5002 	W = "[N] -> { S_0[] -> a[0]; S_2[] -> b[0]; "
5003 		    "S_1[i] -> a[1 + i] : i >= 0 and i <= -1 + N }";
5004 	R = "[N] -> { S_2[] -> a[N]; S_1[i] -> a[i] : i >= 0 and i <= -1 + N }";
5005 	S = "[N] -> { S_1[i] -> [1, i, 0]; S_2[] -> [2, 0, 1]; "
5006 		    "S_0[] -> [0, 0, 0] }";
5007 	if (test_one_schedule(ctx, D, W, R, S, 1, 0) < 0)
5008 		return -1;
5009 	ctx->opt->schedule_parametric = 0;
5010 	if (test_one_schedule(ctx, D, W, R, S, 0, 0) < 0)
5011 		return -1;
5012 	ctx->opt->schedule_parametric = 1;
5013 
5014 	D = "[N] -> { S1[i] : 1 <= i <= N; S2[i] : 1 <= i <= N; "
5015 		    "S3[i,j] : 1 <= i,j <= N; S4[i] : 1 <= i <= N }";
5016 	W = "{ S1[i] -> a[i,0]; S2[i] -> a[0,i]; S3[i,j] -> a[i,j] }";
5017 	R = "[N] -> { S3[i,j] -> a[i-1,j]; S3[i,j] -> a[i,j-1]; "
5018 		    "S4[i] -> a[i,N] }";
5019 	S = "{ S1[i] -> [0,i,0]; S2[i] -> [1,i,0]; S3[i,j] -> [2,i,j]; "
5020 		"S4[i] -> [4,i,0] }";
5021 	max_coincidence = isl_options_get_schedule_maximize_coincidence(ctx);
5022 	isl_options_set_schedule_maximize_coincidence(ctx, 0);
5023 	if (test_one_schedule(ctx, D, W, R, S, 2, 0) < 0)
5024 		return -1;
5025 	isl_options_set_schedule_maximize_coincidence(ctx, max_coincidence);
5026 
5027 	D = "[N] -> { S_0[i, j] : i >= 1 and i <= N and j >= 1 and j <= N }";
5028 	W = "[N] -> { S_0[i, j] -> s[0] : i >= 1 and i <= N and j >= 1 and "
5029 					"j <= N }";
5030 	R = "[N] -> { S_0[i, j] -> s[0] : i >= 1 and i <= N and j >= 1 and "
5031 					"j <= N; "
5032 		    "S_0[i, j] -> a[i, j] : i >= 1 and i <= N and j >= 1 and "
5033 					"j <= N }";
5034 	S = "[N] -> { S_0[i, j] -> [0, i, 0, j, 0] }";
5035 	if (test_one_schedule(ctx, D, W, R, S, 0, 0) < 0)
5036 		return -1;
5037 
5038 	D = "[N] -> { S_0[t] : t >= 0 and t <= -1 + N; "
5039 		    " S_2[t] : t >= 0 and t <= -1 + N; "
5040 		    " S_1[t, i] : t >= 0 and t <= -1 + N and i >= 0 and "
5041 				"i <= -1 + N }";
5042 	W = "[N] -> { S_0[t] -> a[t, 0] : t >= 0 and t <= -1 + N; "
5043 		    " S_2[t] -> b[t] : t >= 0 and t <= -1 + N; "
5044 		    " S_1[t, i] -> a[t, 1 + i] : t >= 0 and t <= -1 + N and "
5045 						"i >= 0 and i <= -1 + N }";
5046 	R = "[N] -> { S_1[t, i] -> a[t, i] : t >= 0 and t <= -1 + N and "
5047 					    "i >= 0 and i <= -1 + N; "
5048 		    " S_2[t] -> a[t, N] : t >= 0 and t <= -1 + N }";
5049 	S = "[N] -> { S_2[t] -> [0, t, 2]; S_1[t, i] -> [0, t, 1, i, 0]; "
5050 		    " S_0[t] -> [0, t, 0] }";
5051 
5052 	if (test_one_schedule(ctx, D, W, R, S, 2, 1) < 0)
5053 		return -1;
5054 	ctx->opt->schedule_parametric = 0;
5055 	if (test_one_schedule(ctx, D, W, R, S, 0, 0) < 0)
5056 		return -1;
5057 	ctx->opt->schedule_parametric = 1;
5058 
5059 	D = "[N] -> { S1[i,j] : 0 <= i,j < N; S2[i,j] : 0 <= i,j < N }";
5060 	S = "{ S1[i,j] -> [0,i,j]; S2[i,j] -> [1,i,j] }";
5061 	if (test_one_schedule(ctx, D, "{}", "{}", S, 2, 2) < 0)
5062 		return -1;
5063 
5064 	D = "[M, N] -> { S_1[i] : i >= 0 and i <= -1 + M; "
5065 	    "S_0[i, j] : i >= 0 and i <= -1 + M and j >= 0 and j <= -1 + N }";
5066 	W = "[M, N] -> { S_0[i, j] -> a[j] : i >= 0 and i <= -1 + M and "
5067 					    "j >= 0 and j <= -1 + N; "
5068 			"S_1[i] -> b[0] : i >= 0 and i <= -1 + M }";
5069 	R = "[M, N] -> { S_0[i, j] -> a[0] : i >= 0 and i <= -1 + M and "
5070 					    "j >= 0 and j <= -1 + N; "
5071 			"S_1[i] -> b[0] : i >= 0 and i <= -1 + M }";
5072 	S = "[M, N] -> { S_1[i] -> [1, i, 0]; S_0[i, j] -> [0, i, 0, j, 0] }";
5073 	if (test_one_schedule(ctx, D, W, R, S, 0, 0) < 0)
5074 		return -1;
5075 
5076 	D = "{ S_0[i] : i >= 0 }";
5077 	W = "{ S_0[i] -> a[i] : i >= 0 }";
5078 	R = "{ S_0[i] -> a[0] : i >= 0 }";
5079 	S = "{ S_0[i] -> [0, i, 0] }";
5080 	if (test_one_schedule(ctx, D, W, R, S, 0, 0) < 0)
5081 		return -1;
5082 
5083 	D = "{ S_0[i] : i >= 0; S_1[i] : i >= 0 }";
5084 	W = "{ S_0[i] -> a[i] : i >= 0; S_1[i] -> b[i] : i >= 0 }";
5085 	R = "{ S_0[i] -> b[0] : i >= 0; S_1[i] -> a[i] : i >= 0 }";
5086 	S = "{ S_1[i] -> [0, i, 1]; S_0[i] -> [0, i, 0] }";
5087 	if (test_one_schedule(ctx, D, W, R, S, 0, 0) < 0)
5088 		return -1;
5089 
5090 	D = "[n] -> { S_0[j, k] : j <= -1 + n and j >= 0 and "
5091 				"k <= -1 + n and k >= 0 }";
5092 	W = "[n] -> { S_0[j, k] -> B[j] : j <= -1 + n and j >= 0 and "							"k <= -1 + n and k >= 0 }";
5093 	R = "[n] -> { S_0[j, k] -> B[j] : j <= -1 + n and j >= 0 and "
5094 					"k <= -1 + n and k >= 0; "
5095 		    "S_0[j, k] -> B[k] : j <= -1 + n and j >= 0 and "
5096 					"k <= -1 + n and k >= 0; "
5097 		    "S_0[j, k] -> A[k] : j <= -1 + n and j >= 0 and "
5098 					"k <= -1 + n and k >= 0 }";
5099 	S = "[n] -> { S_0[j, k] -> [2, j, k] }";
5100 	ctx->opt->schedule_outer_coincidence = 1;
5101 	if (test_one_schedule(ctx, D, W, R, S, 0, 0) < 0)
5102 		return -1;
5103 	ctx->opt->schedule_outer_coincidence = 0;
5104 
5105 	D = "{Stmt_for_body24[i0, i1, i2, i3]:"
5106 		"i0 >= 0 and i0 <= 1 and i1 >= 0 and i1 <= 6 and i2 >= 2 and "
5107 		"i2 <= 6 - i1 and i3 >= 0 and i3 <= -1 + i2;"
5108 	     "Stmt_for_body24[i0, i1, 1, 0]:"
5109 		"i0 >= 0 and i0 <= 1 and i1 >= 0 and i1 <= 5;"
5110 	     "Stmt_for_body7[i0, i1, i2]:"
5111 		"i0 >= 0 and i0 <= 1 and i1 >= 0 and i1 <= 7 and i2 >= 0 and "
5112 		"i2 <= 7 }";
5113 
5114 	V = "{Stmt_for_body24[0, i1, i2, i3] -> "
5115 		"Stmt_for_body24[1, i1, i2, i3]:"
5116 		"i3 >= 0 and i3 <= -1 + i2 and i1 >= 0 and i2 <= 6 - i1 and "
5117 		"i2 >= 1;"
5118 	     "Stmt_for_body24[0, i1, i2, i3] -> "
5119 		"Stmt_for_body7[1, 1 + i1 + i3, 1 + i1 + i2]:"
5120 		"i3 <= -1 + i2 and i2 <= 6 - i1 and i2 >= 1 and i1 >= 0 and "
5121 		"i3 >= 0;"
5122 	      "Stmt_for_body24[0, i1, i2, i3] ->"
5123 		"Stmt_for_body7[1, i1, 1 + i1 + i3]:"
5124 		"i3 >= 0 and i2 <= 6 - i1 and i1 >= 0 and i3 <= -1 + i2;"
5125 	      "Stmt_for_body7[0, i1, i2] -> Stmt_for_body7[1, i1, i2]:"
5126 		"(i2 >= 1 + i1 and i2 <= 6 and i1 >= 0 and i1 <= 4) or "
5127 		"(i2 >= 3 and i2 <= 7 and i1 >= 1 and i2 >= 1 + i1) or "
5128 		"(i2 >= 0 and i2 <= i1 and i2 >= -7 + i1 and i1 <= 7);"
5129 	      "Stmt_for_body7[0, i1, 1 + i1] -> Stmt_for_body7[1, i1, 1 + i1]:"
5130 		"i1 <= 6 and i1 >= 0;"
5131 	      "Stmt_for_body7[0, 0, 7] -> Stmt_for_body7[1, 0, 7];"
5132 	      "Stmt_for_body7[i0, i1, i2] -> "
5133 		"Stmt_for_body24[i0, o1, -1 + i2 - o1, -1 + i1 - o1]:"
5134 		"i0 >= 0 and i0 <= 1 and o1 >= 0 and i2 >= 1 + i1 and "
5135 		"o1 <= -2 + i2 and i2 <= 7 and o1 <= -1 + i1;"
5136 	      "Stmt_for_body7[i0, i1, i2] -> "
5137 		"Stmt_for_body24[i0, i1, o2, -1 - i1 + i2]:"
5138 		"i0 >= 0 and i0 <= 1 and i1 >= 0 and o2 >= -i1 + i2 and "
5139 		"o2 >= 1 and o2 <= 6 - i1 and i2 >= 1 + i1 }";
5140 	P = V;
5141 
5142 	treat_coalescing = isl_options_get_schedule_treat_coalescing(ctx);
5143 	isl_options_set_schedule_treat_coalescing(ctx, 0);
5144 	if (test_has_schedule(ctx, D, V, P) < 0)
5145 		return -1;
5146 	isl_options_set_schedule_treat_coalescing(ctx, treat_coalescing);
5147 
5148 	D = "{ S_0[i, j] : i >= 1 and i <= 10 and j >= 1 and j <= 8 }";
5149 	V = "{ S_0[i, j] -> S_0[i, 1 + j] : i >= 1 and i <= 10 and "
5150 					   "j >= 1 and j <= 7;"
5151 		"S_0[i, j] -> S_0[1 + i, j] : i >= 1 and i <= 9 and "
5152 					     "j >= 1 and j <= 8 }";
5153 	P = "{ }";
5154 	S = "{ S_0[i, j] -> [i + j, i] }";
5155 	ctx->opt->schedule_algorithm = ISL_SCHEDULE_ALGORITHM_FEAUTRIER;
5156 	if (test_special_schedule(ctx, D, V, P, S) < 0)
5157 		return -1;
5158 	ctx->opt->schedule_algorithm = ISL_SCHEDULE_ALGORITHM_ISL;
5159 
5160 	/* Fig. 1 from Feautrier's "Some Efficient Solutions..." pt. 2, 1992 */
5161 	D = "[N] -> { S_0[i, j] : i >= 0 and i <= -1 + N and "
5162 				 "j >= 0 and j <= -1 + i }";
5163 	V = "[N] -> { S_0[i, j] -> S_0[i, 1 + j] : j <= -2 + i and "
5164 					"i <= -1 + N and j >= 0;"
5165 		     "S_0[i, -1 + i] -> S_0[1 + i, 0] : i >= 1 and "
5166 					"i <= -2 + N }";
5167 	P = "{ }";
5168 	S = "{ S_0[i, j] -> [i, j] }";
5169 	ctx->opt->schedule_algorithm = ISL_SCHEDULE_ALGORITHM_FEAUTRIER;
5170 	if (test_special_schedule(ctx, D, V, P, S) < 0)
5171 		return -1;
5172 	ctx->opt->schedule_algorithm = ISL_SCHEDULE_ALGORITHM_ISL;
5173 
5174 	/* Test both algorithms on a case with only proximity dependences. */
5175 	D = "{ S[i,j] : 0 <= i <= 10 }";
5176 	V = "{ }";
5177 	P = "{ S[i,j] -> S[i+1,j] : 0 <= i,j <= 10 }";
5178 	S = "{ S[i, j] -> [j, i] }";
5179 	ctx->opt->schedule_algorithm = ISL_SCHEDULE_ALGORITHM_FEAUTRIER;
5180 	if (test_special_schedule(ctx, D, V, P, S) < 0)
5181 		return -1;
5182 	ctx->opt->schedule_algorithm = ISL_SCHEDULE_ALGORITHM_ISL;
5183 	if (test_special_schedule(ctx, D, V, P, S) < 0)
5184 		return -1;
5185 
5186 	D = "{ A[a]; B[] }";
5187 	V = "{}";
5188 	P = "{ A[a] -> B[] }";
5189 	if (test_has_schedule(ctx, D, V, P) < 0)
5190 		return -1;
5191 
5192 	if (test_padded_schedule(ctx) < 0)
5193 		return -1;
5194 
5195 	/* Check that check for progress is not confused by rational
5196 	 * solution.
5197 	 */
5198 	D = "[N] -> { S0[i, j] : i >= 0 and i <= N and j >= 0 and j <= N }";
5199 	V = "[N] -> { S0[i0, -1 + N] -> S0[2 + i0, 0] : i0 >= 0 and "
5200 							"i0 <= -2 + N; "
5201 			"S0[i0, i1] -> S0[i0, 1 + i1] : i0 >= 0 and "
5202 				"i0 <= N and i1 >= 0 and i1 <= -1 + N }";
5203 	P = "{}";
5204 	ctx->opt->schedule_algorithm = ISL_SCHEDULE_ALGORITHM_FEAUTRIER;
5205 	if (test_has_schedule(ctx, D, V, P) < 0)
5206 		return -1;
5207 	ctx->opt->schedule_algorithm = ISL_SCHEDULE_ALGORITHM_ISL;
5208 
5209 	/* Check that we allow schedule rows that are only non-trivial
5210 	 * on some full-dimensional domains.
5211 	 */
5212 	D = "{ S1[j] : 0 <= j <= 1; S0[]; S2[k] : 0 <= k <= 1 }";
5213 	V = "{ S0[] -> S1[j] : 0 <= j <= 1; S2[0] -> S0[];"
5214 		"S1[j] -> S2[1] : 0 <= j <= 1 }";
5215 	P = "{}";
5216 	ctx->opt->schedule_algorithm = ISL_SCHEDULE_ALGORITHM_FEAUTRIER;
5217 	if (test_has_schedule(ctx, D, V, P) < 0)
5218 		return -1;
5219 	ctx->opt->schedule_algorithm = ISL_SCHEDULE_ALGORITHM_ISL;
5220 
5221 	if (test_conditional_schedule_constraints(ctx) < 0)
5222 		return -1;
5223 
5224 	if (test_strongly_satisfying_schedule(ctx) < 0)
5225 		return -1;
5226 
5227 	if (test_conflicting_context_schedule(ctx) < 0)
5228 		return -1;
5229 
5230 	if (test_coalescing_schedule(ctx) < 0)
5231 		return -1;
5232 	if (test_skewing_schedule(ctx) < 0)
5233 		return -1;
5234 
5235 	return 0;
5236 }
5237 
5238 /* Perform scheduling tests using the whole component scheduler.
5239  */
test_schedule_whole(isl_ctx * ctx)5240 static int test_schedule_whole(isl_ctx *ctx)
5241 {
5242 	int whole;
5243 	int r;
5244 
5245 	whole = isl_options_get_schedule_whole_component(ctx);
5246 	isl_options_set_schedule_whole_component(ctx, 1);
5247 	r = test_schedule(ctx);
5248 	isl_options_set_schedule_whole_component(ctx, whole);
5249 
5250 	return r;
5251 }
5252 
5253 /* Perform scheduling tests using the incremental scheduler.
5254  */
test_schedule_incremental(isl_ctx * ctx)5255 static int test_schedule_incremental(isl_ctx *ctx)
5256 {
5257 	int whole;
5258 	int r;
5259 
5260 	whole = isl_options_get_schedule_whole_component(ctx);
5261 	isl_options_set_schedule_whole_component(ctx, 0);
5262 	r = test_schedule(ctx);
5263 	isl_options_set_schedule_whole_component(ctx, whole);
5264 
5265 	return r;
5266 }
5267 
test_plain_injective(isl_ctx * ctx,const char * str,int injective)5268 int test_plain_injective(isl_ctx *ctx, const char *str, int injective)
5269 {
5270 	isl_union_map *umap;
5271 	int test;
5272 
5273 	umap = isl_union_map_read_from_str(ctx, str);
5274 	test = isl_union_map_plain_is_injective(umap);
5275 	isl_union_map_free(umap);
5276 	if (test < 0)
5277 		return -1;
5278 	if (test == injective)
5279 		return 0;
5280 	if (injective)
5281 		isl_die(ctx, isl_error_unknown,
5282 			"map not detected as injective", return -1);
5283 	else
5284 		isl_die(ctx, isl_error_unknown,
5285 			"map detected as injective", return -1);
5286 }
5287 
test_injective(isl_ctx * ctx)5288 int test_injective(isl_ctx *ctx)
5289 {
5290 	const char *str;
5291 
5292 	if (test_plain_injective(ctx, "{S[i,j] -> A[0]; T[i,j] -> B[1]}", 0))
5293 		return -1;
5294 	if (test_plain_injective(ctx, "{S[] -> A[0]; T[] -> B[0]}", 1))
5295 		return -1;
5296 	if (test_plain_injective(ctx, "{S[] -> A[0]; T[] -> A[1]}", 1))
5297 		return -1;
5298 	if (test_plain_injective(ctx, "{S[] -> A[0]; T[] -> A[0]}", 0))
5299 		return -1;
5300 	if (test_plain_injective(ctx, "{S[i] -> A[i,0]; T[i] -> A[i,1]}", 1))
5301 		return -1;
5302 	if (test_plain_injective(ctx, "{S[i] -> A[i]; T[i] -> A[i]}", 0))
5303 		return -1;
5304 	if (test_plain_injective(ctx, "{S[] -> A[0,0]; T[] -> A[0,1]}", 1))
5305 		return -1;
5306 	if (test_plain_injective(ctx, "{S[] -> A[0,0]; T[] -> A[1,0]}", 1))
5307 		return -1;
5308 
5309 	str = "{S[] -> A[0,0]; T[] -> A[0,1]; U[] -> A[1,0]}";
5310 	if (test_plain_injective(ctx, str, 1))
5311 		return -1;
5312 	str = "{S[] -> A[0,0]; T[] -> A[0,1]; U[] -> A[0,0]}";
5313 	if (test_plain_injective(ctx, str, 0))
5314 		return -1;
5315 
5316 	return 0;
5317 }
5318 
5319 #undef BASE
5320 #define BASE	aff
5321 #include "isl_test_plain_equal_templ.c"
5322 
5323 #undef BASE
5324 #define BASE	pw_multi_aff
5325 #include "isl_test_plain_equal_templ.c"
5326 
5327 #undef BASE
5328 #define BASE	union_pw_aff
5329 #include "isl_test_plain_equal_templ.c"
5330 
5331 /* Basic tests on isl_union_pw_aff.
5332  *
5333  * In particular, check that isl_union_pw_aff_aff_on_domain
5334  * aligns the parameters of the input objects and
5335  * that isl_union_pw_aff_param_on_domain_id properly
5336  * introduces the parameter.
5337  */
test_upa(isl_ctx * ctx)5338 static int test_upa(isl_ctx *ctx)
5339 {
5340 	const char *str;
5341 	isl_id *id;
5342 	isl_aff *aff;
5343 	isl_union_set *domain;
5344 	isl_union_pw_aff *upa;
5345 	isl_stat ok;
5346 
5347 	aff = isl_aff_read_from_str(ctx, "[N] -> { [N] }");
5348 	str = "[M] -> { A[i] : 0 <= i < M; B[] }";
5349 	domain = isl_union_set_read_from_str(ctx, str);
5350 	upa = isl_union_pw_aff_aff_on_domain(domain, aff);
5351 	str = "[N, M] -> { A[i] -> [N] : 0 <= i < M; B[] -> [N] }";
5352 	ok = union_pw_aff_check_plain_equal(upa, str);
5353 	isl_union_pw_aff_free(upa);
5354 	if (ok < 0)
5355 		return -1;
5356 
5357 	id = isl_id_alloc(ctx, "N", NULL);
5358 	str = "[M] -> { A[i] : 0 <= i < M; B[] }";
5359 	domain = isl_union_set_read_from_str(ctx, str);
5360 	upa = isl_union_pw_aff_param_on_domain_id(domain, id);
5361 	str = "[N, M] -> { A[i] -> [N] : 0 <= i < M; B[] -> [N] }";
5362 	ok = union_pw_aff_check_plain_equal(upa, str);
5363 	isl_union_pw_aff_free(upa);
5364 	if (ok < 0)
5365 		return -1;
5366 
5367 	return 0;
5368 }
5369 
5370 struct {
5371 	__isl_give isl_aff *(*fn)(__isl_take isl_aff *aff1,
5372 				__isl_take isl_aff *aff2);
5373 } aff_bin_op[] = {
5374 	['+'] = { &isl_aff_add },
5375 	['-'] = { &isl_aff_sub },
5376 	['*'] = { &isl_aff_mul },
5377 	['/'] = { &isl_aff_div },
5378 };
5379 
5380 struct {
5381 	const char *arg1;
5382 	unsigned char op;
5383 	const char *arg2;
5384 	const char *res;
5385 } aff_bin_tests[] = {
5386 	{ "{ [i] -> [i] }", '+', "{ [i] -> [i] }",
5387 	  "{ [i] -> [2i] }" },
5388 	{ "{ [i] -> [i] }", '-', "{ [i] -> [i] }",
5389 	  "{ [i] -> [0] }" },
5390 	{ "{ [i] -> [i] }", '*', "{ [i] -> [2] }",
5391 	  "{ [i] -> [2i] }" },
5392 	{ "{ [i] -> [2] }", '*', "{ [i] -> [i] }",
5393 	  "{ [i] -> [2i] }" },
5394 	{ "{ [i] -> [i] }", '/', "{ [i] -> [2] }",
5395 	  "{ [i] -> [i/2] }" },
5396 	{ "{ [i] -> [2i] }", '/', "{ [i] -> [2] }",
5397 	  "{ [i] -> [i] }" },
5398 	{ "{ [i] -> [i] }", '+', "{ [i] -> [NaN] }",
5399 	  "{ [i] -> [NaN] }" },
5400 	{ "{ [i] -> [i] }", '-', "{ [i] -> [NaN] }",
5401 	  "{ [i] -> [NaN] }" },
5402 	{ "{ [i] -> [i] }", '*', "{ [i] -> [NaN] }",
5403 	  "{ [i] -> [NaN] }" },
5404 	{ "{ [i] -> [2] }", '*', "{ [i] -> [NaN] }",
5405 	  "{ [i] -> [NaN] }" },
5406 	{ "{ [i] -> [i] }", '/', "{ [i] -> [NaN] }",
5407 	  "{ [i] -> [NaN] }" },
5408 	{ "{ [i] -> [2] }", '/', "{ [i] -> [NaN] }",
5409 	  "{ [i] -> [NaN] }" },
5410 	{ "{ [i] -> [NaN] }", '+', "{ [i] -> [i] }",
5411 	  "{ [i] -> [NaN] }" },
5412 	{ "{ [i] -> [NaN] }", '-', "{ [i] -> [i] }",
5413 	  "{ [i] -> [NaN] }" },
5414 	{ "{ [i] -> [NaN] }", '*', "{ [i] -> [2] }",
5415 	  "{ [i] -> [NaN] }" },
5416 	{ "{ [i] -> [NaN] }", '*', "{ [i] -> [i] }",
5417 	  "{ [i] -> [NaN] }" },
5418 	{ "{ [i] -> [NaN] }", '/', "{ [i] -> [2] }",
5419 	  "{ [i] -> [NaN] }" },
5420 	{ "{ [i] -> [NaN] }", '/', "{ [i] -> [i] }",
5421 	  "{ [i] -> [NaN] }" },
5422 	{ "{ [i] -> [i] }", '/', "{ [i] -> [0] }",
5423 	  "{ [i] -> [NaN] }" },
5424 };
5425 
5426 /* Perform some basic tests of binary operations on isl_aff objects.
5427  */
test_bin_aff(isl_ctx * ctx)5428 static int test_bin_aff(isl_ctx *ctx)
5429 {
5430 	int i;
5431 	isl_aff *aff1, *aff2, *res;
5432 	__isl_give isl_aff *(*fn)(__isl_take isl_aff *aff1,
5433 				__isl_take isl_aff *aff2);
5434 	int ok;
5435 
5436 	for (i = 0; i < ARRAY_SIZE(aff_bin_tests); ++i) {
5437 		aff1 = isl_aff_read_from_str(ctx, aff_bin_tests[i].arg1);
5438 		aff2 = isl_aff_read_from_str(ctx, aff_bin_tests[i].arg2);
5439 		res = isl_aff_read_from_str(ctx, aff_bin_tests[i].res);
5440 		fn = aff_bin_op[aff_bin_tests[i].op].fn;
5441 		aff1 = fn(aff1, aff2);
5442 		if (isl_aff_is_nan(res))
5443 			ok = isl_aff_is_nan(aff1);
5444 		else
5445 			ok = isl_aff_plain_is_equal(aff1, res);
5446 		isl_aff_free(aff1);
5447 		isl_aff_free(res);
5448 		if (ok < 0)
5449 			return -1;
5450 		if (!ok)
5451 			isl_die(ctx, isl_error_unknown,
5452 				"unexpected result", return -1);
5453 	}
5454 
5455 	return 0;
5456 }
5457 
5458 struct {
5459 	__isl_give isl_pw_aff *(*fn)(__isl_take isl_pw_aff *pa1,
5460 				     __isl_take isl_pw_aff *pa2);
5461 } pw_aff_bin_op[] = {
5462 	['m'] = { &isl_pw_aff_min },
5463 	['M'] = { &isl_pw_aff_max },
5464 };
5465 
5466 /* Inputs for binary isl_pw_aff operation tests.
5467  * "arg1" and "arg2" are the two arguments, "op" identifies the operation
5468  * defined by pw_aff_bin_op, and "res" is the expected result.
5469  */
5470 struct {
5471 	const char *arg1;
5472 	unsigned char op;
5473 	const char *arg2;
5474 	const char *res;
5475 } pw_aff_bin_tests[] = {
5476 	{ "{ [i] -> [i] }", 'm', "{ [i] -> [i] }",
5477 	  "{ [i] -> [i] }" },
5478 	{ "{ [i] -> [i] }", 'M', "{ [i] -> [i] }",
5479 	  "{ [i] -> [i] }" },
5480 	{ "{ [i] -> [i] }", 'm', "{ [i] -> [0] }",
5481 	  "{ [i] -> [i] : i <= 0; [i] -> [0] : i > 0 }" },
5482 	{ "{ [i] -> [i] }", 'M', "{ [i] -> [0] }",
5483 	  "{ [i] -> [i] : i >= 0; [i] -> [0] : i < 0 }" },
5484 	{ "{ [i] -> [i] }", 'm', "{ [i] -> [NaN] }",
5485 	  "{ [i] -> [NaN] }" },
5486 	{ "{ [i] -> [NaN] }", 'm', "{ [i] -> [i] }",
5487 	  "{ [i] -> [NaN] }" },
5488 };
5489 
5490 /* Perform some basic tests of binary operations on isl_pw_aff objects.
5491  */
test_bin_pw_aff(isl_ctx * ctx)5492 static int test_bin_pw_aff(isl_ctx *ctx)
5493 {
5494 	int i;
5495 	isl_bool ok;
5496 	isl_pw_aff *pa1, *pa2, *res;
5497 
5498 	for (i = 0; i < ARRAY_SIZE(pw_aff_bin_tests); ++i) {
5499 		pa1 = isl_pw_aff_read_from_str(ctx, pw_aff_bin_tests[i].arg1);
5500 		pa2 = isl_pw_aff_read_from_str(ctx, pw_aff_bin_tests[i].arg2);
5501 		res = isl_pw_aff_read_from_str(ctx, pw_aff_bin_tests[i].res);
5502 		pa1 = pw_aff_bin_op[pw_aff_bin_tests[i].op].fn(pa1, pa2);
5503 		if (isl_pw_aff_involves_nan(res))
5504 			ok = isl_pw_aff_involves_nan(pa1);
5505 		else
5506 			ok = isl_pw_aff_plain_is_equal(pa1, res);
5507 		isl_pw_aff_free(pa1);
5508 		isl_pw_aff_free(res);
5509 		if (ok < 0)
5510 			return -1;
5511 		if (!ok)
5512 			isl_die(ctx, isl_error_unknown,
5513 				"unexpected result", return -1);
5514 	}
5515 
5516 	return 0;
5517 }
5518 
5519 /* Inputs for basic tests of test operations on
5520  * isl_union_pw_multi_aff objects.
5521  * "fn" is the function that is being tested.
5522  * "arg" is a string description of the input.
5523  * "res" is the expected result.
5524  */
5525 static struct {
5526 	isl_bool (*fn)(__isl_keep isl_union_pw_multi_aff *upma1);
5527 	const char *arg;
5528 	isl_bool res;
5529 } upma_test_tests[] = {
5530 	{ &isl_union_pw_multi_aff_involves_nan, "{ A[] -> [0]; B[0] -> [1] }",
5531 	  isl_bool_false },
5532 	{ &isl_union_pw_multi_aff_involves_nan, "{ A[] -> [NaN]; B[0] -> [1] }",
5533 	  isl_bool_true },
5534 	{ &isl_union_pw_multi_aff_involves_nan, "{ A[] -> [0]; B[0] -> [NaN] }",
5535 	  isl_bool_true },
5536 	{ &isl_union_pw_multi_aff_involves_nan,
5537 	  "{ A[] -> [0]; B[0] -> [1, NaN, 5] }",
5538 	  isl_bool_true },
5539 	{ &isl_union_pw_multi_aff_involves_locals,
5540 	  "{ A[] -> [0]; B[0] -> [1] }",
5541 	  isl_bool_false },
5542 	{ &isl_union_pw_multi_aff_involves_locals,
5543 	  "{ A[] -> [0]; B[x] -> [1] : x mod 2 = 0 }",
5544 	  isl_bool_true },
5545 	{ &isl_union_pw_multi_aff_involves_locals,
5546 	  "{ A[] -> [0]; B[x] -> [x // 2] }",
5547 	  isl_bool_true },
5548 	{ &isl_union_pw_multi_aff_involves_locals,
5549 	  "{ A[i] -> [i // 2]; B[0] -> [1] }",
5550 	  isl_bool_true },
5551 };
5552 
5553 /* Perform some basic tests of test operations on
5554  * isl_union_pw_multi_aff objects.
5555  */
test_upma_test(isl_ctx * ctx)5556 static isl_stat test_upma_test(isl_ctx *ctx)
5557 {
5558 	int i;
5559 	isl_union_pw_multi_aff *upma;
5560 	isl_bool res;
5561 
5562 	for (i = 0; i < ARRAY_SIZE(upma_test_tests); ++i) {
5563 		const char *str;
5564 
5565 		str = upma_test_tests[i].arg;
5566 		upma = isl_union_pw_multi_aff_read_from_str(ctx, str);
5567 		res = upma_test_tests[i].fn(upma);
5568 		isl_union_pw_multi_aff_free(upma);
5569 		if (res < 0)
5570 			return isl_stat_error;
5571 		if (res != upma_test_tests[i].res)
5572 			isl_die(ctx, isl_error_unknown,
5573 				"unexpected result", return isl_stat_error);
5574 	}
5575 
5576 	return isl_stat_ok;
5577 }
5578 
5579 struct {
5580 	__isl_give isl_union_pw_multi_aff *(*fn)(
5581 		__isl_take isl_union_pw_multi_aff *upma1,
5582 		__isl_take isl_union_pw_multi_aff *upma2);
5583 	const char *arg1;
5584 	const char *arg2;
5585 	const char *res;
5586 } upma_bin_tests[] = {
5587 	{ &isl_union_pw_multi_aff_add, "{ A[] -> [0]; B[0] -> [1] }",
5588 	  "{ B[x] -> [2] : x >= 0 }", "{ B[0] -> [3] }" },
5589 	{ &isl_union_pw_multi_aff_union_add, "{ A[] -> [0]; B[0] -> [1] }",
5590 	  "{ B[x] -> [2] : x >= 0 }",
5591 	  "{ A[] -> [0]; B[0] -> [3]; B[x] -> [2] : x >= 1 }" },
5592 	{ &isl_union_pw_multi_aff_pullback_union_pw_multi_aff,
5593 	  "{ A[] -> B[0]; C[x] -> B[1] : x < 10; C[y] -> B[2] : y >= 10 }",
5594 	  "{ D[i] -> A[] : i < 0; D[i] -> C[i + 5] : i >= 0 }",
5595 	  "{ D[i] -> B[0] : i < 0; D[i] -> B[1] : 0 <= i < 5; "
5596 	    "D[i] -> B[2] : i >= 5 }" },
5597 	{ &isl_union_pw_multi_aff_union_add, "{ B[x] -> A[1] : x <= 0 }",
5598 	  "{ B[x] -> C[2] : x > 0 }",
5599 	  "{ B[x] -> A[1] : x <= 0; B[x] -> C[2] : x > 0 }" },
5600 	{ &isl_union_pw_multi_aff_union_add, "{ B[x] -> A[1] : x <= 0 }",
5601 	  "{ B[x] -> A[2] : x >= 0 }",
5602 	  "{ B[x] -> A[1] : x < 0; B[x] -> A[2] : x > 0; B[0] -> A[3] }" },
5603 };
5604 
5605 /* Perform some basic tests of binary operations on
5606  * isl_union_pw_multi_aff objects.
5607  */
test_bin_upma(isl_ctx * ctx)5608 static int test_bin_upma(isl_ctx *ctx)
5609 {
5610 	int i;
5611 	isl_union_pw_multi_aff *upma1, *upma2, *res;
5612 	int ok;
5613 
5614 	for (i = 0; i < ARRAY_SIZE(upma_bin_tests); ++i) {
5615 		upma1 = isl_union_pw_multi_aff_read_from_str(ctx,
5616 							upma_bin_tests[i].arg1);
5617 		upma2 = isl_union_pw_multi_aff_read_from_str(ctx,
5618 							upma_bin_tests[i].arg2);
5619 		res = isl_union_pw_multi_aff_read_from_str(ctx,
5620 							upma_bin_tests[i].res);
5621 		upma1 = upma_bin_tests[i].fn(upma1, upma2);
5622 		ok = isl_union_pw_multi_aff_plain_is_equal(upma1, res);
5623 		isl_union_pw_multi_aff_free(upma1);
5624 		isl_union_pw_multi_aff_free(res);
5625 		if (ok < 0)
5626 			return -1;
5627 		if (!ok)
5628 			isl_die(ctx, isl_error_unknown,
5629 				"unexpected result", return -1);
5630 	}
5631 
5632 	return 0;
5633 }
5634 
5635 struct {
5636 	__isl_give isl_union_pw_multi_aff *(*fn)(
5637 		__isl_take isl_union_pw_multi_aff *upma1,
5638 		__isl_take isl_union_pw_multi_aff *upma2);
5639 	const char *arg1;
5640 	const char *arg2;
5641 } upma_bin_fail_tests[] = {
5642 	{ &isl_union_pw_multi_aff_union_add, "{ B[x] -> A[1] : x <= 0 }",
5643 	  "{ B[x] -> C[2] : x >= 0 }" },
5644 };
5645 
5646 /* Perform some basic tests of binary operations on
5647  * isl_union_pw_multi_aff objects that are expected to fail.
5648  */
test_bin_upma_fail(isl_ctx * ctx)5649 static int test_bin_upma_fail(isl_ctx *ctx)
5650 {
5651 	int i, n;
5652 	isl_union_pw_multi_aff *upma1, *upma2;
5653 	int on_error;
5654 
5655 	on_error = isl_options_get_on_error(ctx);
5656 	isl_options_set_on_error(ctx, ISL_ON_ERROR_CONTINUE);
5657 	n = ARRAY_SIZE(upma_bin_fail_tests);
5658 	for (i = 0; i < n; ++i) {
5659 		upma1 = isl_union_pw_multi_aff_read_from_str(ctx,
5660 						upma_bin_fail_tests[i].arg1);
5661 		upma2 = isl_union_pw_multi_aff_read_from_str(ctx,
5662 						upma_bin_fail_tests[i].arg2);
5663 		upma1 = upma_bin_fail_tests[i].fn(upma1, upma2);
5664 		isl_union_pw_multi_aff_free(upma1);
5665 		if (upma1)
5666 			break;
5667 	}
5668 	isl_options_set_on_error(ctx, on_error);
5669 	if (i < n)
5670 		isl_die(ctx, isl_error_unknown,
5671 			"operation not expected to succeed", return -1);
5672 
5673 	return 0;
5674 }
5675 
5676 /* Inputs for basic tests of binary operations on
5677  * pairs of isl_union_pw_multi_aff and isl_union_set objects.
5678  * "fn" is the function that is being tested.
5679  * "arg1" and "arg2" are string descriptions of the inputs.
5680  * "res" is a string description of the expected result.
5681  */
5682 struct {
5683 	__isl_give isl_union_pw_multi_aff *(*fn)(
5684 		__isl_take isl_union_pw_multi_aff *upma,
5685 		__isl_take isl_union_set *uset);
5686 	const char *arg1;
5687 	const char *arg2;
5688 	const char *res;
5689 } upma_uset_tests[] = {
5690 	{ &isl_union_pw_multi_aff_intersect_domain_wrapped_range,
5691 	  "{ A[i] -> B[i] }", "{ B[0] }",
5692 	  "{ }" },
5693 	{ &isl_union_pw_multi_aff_intersect_domain_wrapped_domain,
5694 	  "{ [A[i] -> B[i]] -> C[i + 1] }", "{ A[1]; B[0] }",
5695 	  "{ [A[1] -> B[1]] -> C[2] }" },
5696 	{ &isl_union_pw_multi_aff_intersect_domain_wrapped_range,
5697 	  "{ [A[i] -> B[i]] -> C[i + 1] }", "{ A[1]; B[0] }",
5698 	  "{ [A[0] -> B[0]] -> C[1] }" },
5699 	{ &isl_union_pw_multi_aff_intersect_domain_wrapped_range,
5700 	  "{ [A[i] -> B[i]] -> C[i + 1] }", "[N] -> { B[N] }",
5701 	  "[N] -> { [A[N] -> B[N]] -> C[N + 1] }" },
5702 	{ &isl_union_pw_multi_aff_intersect_domain_wrapped_range,
5703 	  "[M] -> { [A[M] -> B[M]] -> C[M + 1] }", "[N] -> { B[N] }",
5704 	  "[N, M] -> { [A[N] -> B[N]] -> C[N + 1] : N = M }" },
5705 	{ &isl_union_pw_multi_aff_intersect_domain_wrapped_range,
5706 	  "{ [A[] -> B[]] -> C[]; N[A[] -> B[]] -> D[]; [B[] -> A[]] -> E[] }",
5707 	  "{ B[] }",
5708 	  "{ [A[] -> B[]] -> C[]; N[A[] -> B[]] -> D[] }" },
5709 };
5710 
5711 /* Perform some basic tests of binary operations on
5712  * pairs of isl_union_pw_multi_aff and isl_union_set objects.
5713  */
test_upma_uset(isl_ctx * ctx)5714 static isl_stat test_upma_uset(isl_ctx *ctx)
5715 {
5716 	int i;
5717 	isl_bool ok;
5718 	isl_union_pw_multi_aff *upma, *res;
5719 	isl_union_set *uset;
5720 
5721 	for (i = 0; i < ARRAY_SIZE(upma_uset_tests); ++i) {
5722 		upma = isl_union_pw_multi_aff_read_from_str(ctx,
5723 						    upma_uset_tests[i].arg1);
5724 		uset = isl_union_set_read_from_str(ctx,
5725 						    upma_uset_tests[i].arg2);
5726 		res = isl_union_pw_multi_aff_read_from_str(ctx,
5727 						    upma_uset_tests[i].res);
5728 		upma = upma_uset_tests[i].fn(upma, uset);
5729 		ok = isl_union_pw_multi_aff_plain_is_equal(upma, res);
5730 		isl_union_pw_multi_aff_free(upma);
5731 		isl_union_pw_multi_aff_free(res);
5732 		if (ok < 0)
5733 			return isl_stat_error;
5734 		if (!ok)
5735 			isl_die(ctx, isl_error_unknown,
5736 				"unexpected result", return isl_stat_error);
5737 	}
5738 
5739 	return isl_stat_ok;
5740 }
5741 
5742 /* Inputs for basic tests of unary operations on isl_multi_pw_aff objects.
5743  * "fn" is the function that is tested.
5744  * "arg" is a string description of the input.
5745  * "res" is a string description of the expected result.
5746  */
5747 struct {
5748 	__isl_give isl_multi_pw_aff *(*fn)(__isl_take isl_multi_pw_aff *mpa);
5749 	const char *arg;
5750 	const char *res;
5751 } mpa_un_tests[] = {
5752 	{ &isl_multi_pw_aff_range_factor_domain,
5753 	  "{ A[x] -> [B[(1 : x >= 5)] -> C[(2 : x <= 10)]] }",
5754 	  "{ A[x] -> B[(1 : x >= 5)] }" },
5755 	{ &isl_multi_pw_aff_range_factor_range,
5756 	  "{ A[x] -> [B[(1 : x >= 5)] -> C[(2 : x <= 10)]] }",
5757 	  "{ A[y] -> C[(2 : y <= 10)] }" },
5758 	{ &isl_multi_pw_aff_range_factor_domain,
5759 	  "{ A[x] -> [B[(1 : x >= 5)] -> C[]] }",
5760 	  "{ A[x] -> B[(1 : x >= 5)] }" },
5761 	{ &isl_multi_pw_aff_range_factor_range,
5762 	  "{ A[x] -> [B[(1 : x >= 5)] -> C[]] }",
5763 	  "{ A[y] -> C[] }" },
5764 	{ &isl_multi_pw_aff_range_factor_domain,
5765 	  "{ A[x] -> [B[] -> C[(2 : x <= 10)]] }",
5766 	  "{ A[x] -> B[] }" },
5767 	{ &isl_multi_pw_aff_range_factor_range,
5768 	  "{ A[x] -> [B[] -> C[(2 : x <= 10)]] }",
5769 	  "{ A[y] -> C[(2 : y <= 10)] }" },
5770 	{ &isl_multi_pw_aff_range_factor_domain,
5771 	  "{ A[x] -> [B[] -> C[]] }",
5772 	  "{ A[x] -> B[] }" },
5773 	{ &isl_multi_pw_aff_range_factor_range,
5774 	  "{ A[x] -> [B[] -> C[]] }",
5775 	  "{ A[y] -> C[] }" },
5776 	{ &isl_multi_pw_aff_factor_range,
5777 	  "{ [B[] -> C[]] }",
5778 	  "{ C[] }" },
5779 	{ &isl_multi_pw_aff_range_factor_domain,
5780 	  "{ A[x] -> [B[] -> C[]] : x >= 0 }",
5781 	  "{ A[x] -> B[] : x >= 0 }" },
5782 	{ &isl_multi_pw_aff_range_factor_range,
5783 	  "{ A[x] -> [B[] -> C[]] : x >= 0 }",
5784 	  "{ A[y] -> C[] : y >= 0 }" },
5785 	{ &isl_multi_pw_aff_factor_range,
5786 	  "[N] -> { [B[] -> C[]] : N >= 0 }",
5787 	  "[N] -> { C[] : N >= 0 }" },
5788 };
5789 
5790 /* Perform some basic tests of unary operations on isl_multi_pw_aff objects.
5791  */
test_un_mpa(isl_ctx * ctx)5792 static int test_un_mpa(isl_ctx *ctx)
5793 {
5794 	int i;
5795 	isl_bool ok;
5796 	isl_multi_pw_aff *mpa, *res;
5797 
5798 	for (i = 0; i < ARRAY_SIZE(mpa_un_tests); ++i) {
5799 		mpa = isl_multi_pw_aff_read_from_str(ctx, mpa_un_tests[i].arg);
5800 		res = isl_multi_pw_aff_read_from_str(ctx, mpa_un_tests[i].res);
5801 		mpa = mpa_un_tests[i].fn(mpa);
5802 		ok = isl_multi_pw_aff_plain_is_equal(mpa, res);
5803 		isl_multi_pw_aff_free(mpa);
5804 		isl_multi_pw_aff_free(res);
5805 		if (ok < 0)
5806 			return -1;
5807 		if (!ok)
5808 			isl_die(ctx, isl_error_unknown,
5809 				"unexpected result", return -1);
5810 	}
5811 
5812 	return 0;
5813 }
5814 
5815 /* Inputs for basic tests of binary operations on isl_multi_pw_aff objects.
5816  * "fn" is the function that is tested.
5817  * "arg1" and "arg2" are string descriptions of the inputs.
5818  * "res" is a string description of the expected result.
5819  */
5820 struct {
5821 	__isl_give isl_multi_pw_aff *(*fn)(
5822 		__isl_take isl_multi_pw_aff *mpa1,
5823 		__isl_take isl_multi_pw_aff *mpa2);
5824 	const char *arg1;
5825 	const char *arg2;
5826 	const char *res;
5827 } mpa_bin_tests[] = {
5828 	{ &isl_multi_pw_aff_add, "{ A[] -> [1] }", "{ A[] -> [2] }",
5829 	  "{ A[] -> [3] }" },
5830 	{ &isl_multi_pw_aff_add, "{ A[x] -> [(1 : x >= 5)] }",
5831 	  "{ A[x] -> [(x : x <= 10)] }",
5832 	  "{ A[x] -> [(1 + x : 5 <= x <= 10)] }" },
5833 	{ &isl_multi_pw_aff_add, "{ A[x] -> [] : x >= 5 }",
5834 	  "{ A[x] -> [] : x <= 10 }",
5835 	  "{ A[x] -> [] : 5 <= x <= 10 }" },
5836 	{ &isl_multi_pw_aff_add, "{ A[x] -> [] : x >= 5 }",
5837 	  "[N] -> { A[x] -> [] : x <= N }",
5838 	  "[N] -> { A[x] -> [] : 5 <= x <= N }" },
5839 	{ &isl_multi_pw_aff_add,
5840 	  "[N] -> { A[x] -> [] : x <= N }",
5841 	  "{ A[x] -> [] : x >= 5 }",
5842 	  "[N] -> { A[x] -> [] : 5 <= x <= N }" },
5843 	{ &isl_multi_pw_aff_range_product, "{ A[x] -> B[(1 : x >= 5)] }",
5844 	  "{ A[y] -> C[(2 : y <= 10)] }",
5845 	  "{ A[x] -> [B[(1 : x >= 5)] -> C[(2 : x <= 10)]] }" },
5846 	{ &isl_multi_pw_aff_range_product, "{ A[x] -> B[1] : x >= 5 }",
5847 	  "{ A[y] -> C[2] : y <= 10 }",
5848 	  "{ A[x] -> [B[(1 : x >= 5)] -> C[(2 : x <= 10)]] }" },
5849 	{ &isl_multi_pw_aff_range_product, "{ A[x] -> B[1] : x >= 5 }",
5850 	  "[N] -> { A[y] -> C[2] : y <= N }",
5851 	  "[N] -> { A[x] -> [B[(1 : x >= 5)] -> C[(2 : x <= N)]] }" },
5852 	{ &isl_multi_pw_aff_range_product, "[N] -> { A[x] -> B[1] : x >= N }",
5853 	  "{ A[y] -> C[2] : y <= 10 }",
5854 	  "[N] -> { A[x] -> [B[(1 : x >= N)] -> C[(2 : x <= 10)]] }" },
5855 	{ &isl_multi_pw_aff_range_product, "{ A[] -> B[1] }", "{ A[] -> C[2] }",
5856 	  "{ A[] -> [B[1] -> C[2]] }" },
5857 	{ &isl_multi_pw_aff_range_product, "{ A[] -> B[] }", "{ A[] -> C[] }",
5858 	  "{ A[] -> [B[] -> C[]] }" },
5859 	{ &isl_multi_pw_aff_range_product, "{ A[x] -> B[(1 : x >= 5)] }",
5860 	  "{ A[y] -> C[] : y <= 10 }",
5861 	  "{ A[x] -> [B[(1 : x >= 5)] -> C[]] : x <= 10 }" },
5862 	{ &isl_multi_pw_aff_range_product, "{ A[y] -> C[] : y <= 10 }",
5863 	  "{ A[x] -> B[(1 : x >= 5)] }",
5864 	  "{ A[x] -> [C[] -> B[(1 : x >= 5)]] : x <= 10 }" },
5865 	{ &isl_multi_pw_aff_product, "{ A[x] -> B[(1 : x >= 5)] }",
5866 	  "{ A[y] -> C[(2 : y <= 10)] }",
5867 	  "{ [A[x] -> A[y]] -> [B[(1 : x >= 5)] -> C[(2 : y <= 10)]] }" },
5868 	{ &isl_multi_pw_aff_product, "{ A[x] -> B[(1 : x >= 5)] }",
5869 	  "{ A[y] -> C[] : y <= 10 }",
5870 	  "{ [A[x] -> A[y]] -> [B[(1 : x >= 5)] -> C[]] : y <= 10 }" },
5871 	{ &isl_multi_pw_aff_product, "{ A[y] -> C[] : y <= 10 }",
5872 	  "{ A[x] -> B[(1 : x >= 5)] }",
5873 	  "{ [A[y] -> A[x]] -> [C[] -> B[(1 : x >= 5)]] : y <= 10 }" },
5874 	{ &isl_multi_pw_aff_product, "{ A[x] -> B[(1 : x >= 5)] }",
5875 	  "[N] -> { A[y] -> C[] : y <= N }",
5876 	  "[N] -> { [A[x] -> A[y]] -> [B[(1 : x >= 5)] -> C[]] : y <= N }" },
5877 	{ &isl_multi_pw_aff_product, "[N] -> { A[y] -> C[] : y <= N }",
5878 	  "{ A[x] -> B[(1 : x >= 5)] }",
5879 	  "[N] -> { [A[y] -> A[x]] -> [C[] -> B[(1 : x >= 5)]] : y <= N }" },
5880 	{ &isl_multi_pw_aff_product, "{ A[x] -> B[] : x >= 5 }",
5881 	  "{ A[y] -> C[] : y <= 10 }",
5882 	  "{ [A[x] -> A[y]] -> [B[] -> C[]] : x >= 5 and y <= 10 }" },
5883 	{ &isl_multi_pw_aff_product, "{ A[] -> B[1] }", "{ A[] -> C[2] }",
5884 	  "{ [A[] -> A[]] -> [B[1] -> C[2]] }" },
5885 	{ &isl_multi_pw_aff_product, "{ A[] -> B[] }", "{ A[] -> C[] }",
5886 	  "{ [A[] -> A[]] -> [B[] -> C[]] }" },
5887 	{ &isl_multi_pw_aff_pullback_multi_pw_aff,
5888 	  "{ B[i,j] -> C[i + 2j] }", "{ A[a,b] -> B[b,a] }",
5889 	  "{ A[a,b] -> C[b + 2a] }" },
5890 	{ &isl_multi_pw_aff_pullback_multi_pw_aff,
5891 	  "{ B[i,j] -> C[i + 2j] }",
5892 	  "{ A[a,b] -> B[(b : b > a),(a : b > a)] }",
5893 	  "{ A[a,b] -> C[(b + 2a : b > a)] }" },
5894 	{ &isl_multi_pw_aff_pullback_multi_pw_aff,
5895 	  "{ B[i,j] -> C[(i + 2j : j > 4)] }",
5896 	  "{ A[a,b] -> B[(b : b > a),(a : b > a)] }",
5897 	  "{ A[a,b] -> C[(b + 2a : b > a > 4)] }" },
5898 	{ &isl_multi_pw_aff_pullback_multi_pw_aff,
5899 	  "{ B[i,j] -> C[] }",
5900 	  "{ A[a,b] -> B[(b : b > a),(a : b > a)] }",
5901 	  "{ A[a,b] -> C[] }" },
5902 	{ &isl_multi_pw_aff_pullback_multi_pw_aff,
5903 	  "{ B[i,j] -> C[] : i > j }",
5904 	  "{ A[a,b] -> B[b,a] }",
5905 	  "{ A[a,b] -> C[] : b > a }" },
5906 	{ &isl_multi_pw_aff_pullback_multi_pw_aff,
5907 	  "{ B[i,j] -> C[] : j > 5 }",
5908 	  "{ A[a,b] -> B[(b : b > a),(a : b > a)] }",
5909 	  "{ A[a,b] -> C[] : b > a > 5 }" },
5910 	{ &isl_multi_pw_aff_pullback_multi_pw_aff,
5911 	  "[N] -> { B[i,j] -> C[] : j > N }",
5912 	  "{ A[a,b] -> B[(b : b > a),(a : b > a)] }",
5913 	  "[N] -> { A[a,b] -> C[] : b > a > N }" },
5914 	{ &isl_multi_pw_aff_pullback_multi_pw_aff,
5915 	  "[M,N] -> { B[] -> C[] : N > 5 }",
5916 	  "[M,N] -> { A[] -> B[] : M > N }",
5917 	  "[M,N] -> { A[] -> C[] : M > N > 5 }" },
5918 };
5919 
5920 /* Perform some basic tests of binary operations on isl_multi_pw_aff objects.
5921  */
test_bin_mpa(isl_ctx * ctx)5922 static int test_bin_mpa(isl_ctx *ctx)
5923 {
5924 	int i;
5925 	isl_bool ok;
5926 	isl_multi_pw_aff *mpa1, *mpa2, *res;
5927 
5928 	for (i = 0; i < ARRAY_SIZE(mpa_bin_tests); ++i) {
5929 		mpa1 = isl_multi_pw_aff_read_from_str(ctx,
5930 							mpa_bin_tests[i].arg1);
5931 		mpa2 = isl_multi_pw_aff_read_from_str(ctx,
5932 							mpa_bin_tests[i].arg2);
5933 		res = isl_multi_pw_aff_read_from_str(ctx,
5934 							mpa_bin_tests[i].res);
5935 		mpa1 = mpa_bin_tests[i].fn(mpa1, mpa2);
5936 		ok = isl_multi_pw_aff_plain_is_equal(mpa1, res);
5937 		isl_multi_pw_aff_free(mpa1);
5938 		isl_multi_pw_aff_free(res);
5939 		if (ok < 0)
5940 			return -1;
5941 		if (!ok)
5942 			isl_die(ctx, isl_error_unknown,
5943 				"unexpected result", return -1);
5944 	}
5945 
5946 	return 0;
5947 }
5948 
5949 /* Inputs for basic tests of unary operations on
5950  * isl_multi_union_pw_aff objects.
5951  * "fn" is the function that is tested.
5952  * "arg" is a string description of the input.
5953  * "res" is a string description of the expected result.
5954  */
5955 struct {
5956 	__isl_give isl_multi_union_pw_aff *(*fn)(
5957 		__isl_take isl_multi_union_pw_aff *mupa);
5958 	const char *arg;
5959 	const char *res;
5960 } mupa_un_tests[] = {
5961 	{ &isl_multi_union_pw_aff_factor_range,
5962 	  "[B[{ A[] -> [1] }] -> C[{ A[] -> [2] }]]",
5963 	  "C[{ A[] -> [2] }]" },
5964 	{ &isl_multi_union_pw_aff_factor_range,
5965 	  "[B[] -> C[{ A[] -> [2] }]]",
5966 	  "C[{ A[] -> [2] }]" },
5967 	{ &isl_multi_union_pw_aff_factor_range,
5968 	  "[B[{ A[] -> [1] }] -> C[]]",
5969 	  "C[]" },
5970 	{ &isl_multi_union_pw_aff_factor_range,
5971 	  "[B[] -> C[]]",
5972 	  "C[]" },
5973 	{ &isl_multi_union_pw_aff_factor_range,
5974 	  "([B[] -> C[]] : { A[x] : x >= 0 })",
5975 	  "(C[] : { A[x] : x >= 0 })" },
5976 	{ &isl_multi_union_pw_aff_factor_range,
5977 	  "[N] -> ([B[] -> C[]] : { A[x] : x <= N })",
5978 	  "[N] -> (C[] : { A[x] : x <= N })" },
5979 	{ &isl_multi_union_pw_aff_factor_range,
5980 	  "[N] -> ([B[] -> C[]] : { : N >= 0 })",
5981 	  "[N] -> (C[] : { : N >= 0 })" },
5982 };
5983 
5984 /* Perform some basic tests of unary operations on
5985  * isl_multi_union_pw_aff objects.
5986  */
test_un_mupa(isl_ctx * ctx)5987 static int test_un_mupa(isl_ctx *ctx)
5988 {
5989 	int i;
5990 	isl_bool ok;
5991 	isl_multi_union_pw_aff *mupa, *res;
5992 
5993 	for (i = 0; i < ARRAY_SIZE(mupa_un_tests); ++i) {
5994 		mupa = isl_multi_union_pw_aff_read_from_str(ctx,
5995 							mupa_un_tests[i].arg);
5996 		res = isl_multi_union_pw_aff_read_from_str(ctx,
5997 							mupa_un_tests[i].res);
5998 		mupa = mupa_un_tests[i].fn(mupa);
5999 		ok = isl_multi_union_pw_aff_plain_is_equal(mupa, res);
6000 		isl_multi_union_pw_aff_free(mupa);
6001 		isl_multi_union_pw_aff_free(res);
6002 		if (ok < 0)
6003 			return -1;
6004 		if (!ok)
6005 			isl_die(ctx, isl_error_unknown,
6006 				"unexpected result", return -1);
6007 	}
6008 
6009 	return 0;
6010 }
6011 
6012 /* Inputs for basic tests of binary operations on
6013  * isl_multi_union_pw_aff objects.
6014  * "fn" is the function that is tested.
6015  * "arg1" and "arg2" are string descriptions of the inputs.
6016  * "res" is a string description of the expected result.
6017  */
6018 struct {
6019 	__isl_give isl_multi_union_pw_aff *(*fn)(
6020 		__isl_take isl_multi_union_pw_aff *mupa1,
6021 		__isl_take isl_multi_union_pw_aff *mupa2);
6022 	const char *arg1;
6023 	const char *arg2;
6024 	const char *res;
6025 } mupa_bin_tests[] = {
6026 	{ &isl_multi_union_pw_aff_add, "[{ A[] -> [1] }]", "[{ A[] -> [2] }]",
6027 	  "[{ A[] -> [3] }]" },
6028 	{ &isl_multi_union_pw_aff_sub, "[{ A[] -> [1] }]", "[{ A[] -> [2] }]",
6029 	  "[{ A[] -> [-1] }]" },
6030 	{ &isl_multi_union_pw_aff_add,
6031 	  "[{ A[] -> [1]; B[] -> [4] }]",
6032 	  "[{ A[] -> [2]; C[] -> [5] }]",
6033 	  "[{ A[] -> [3] }]" },
6034 	{ &isl_multi_union_pw_aff_union_add,
6035 	  "[{ A[] -> [1]; B[] -> [4] }]",
6036 	  "[{ A[] -> [2]; C[] -> [5] }]",
6037 	  "[{ A[] -> [3]; B[] -> [4]; C[] -> [5] }]" },
6038 	{ &isl_multi_union_pw_aff_add, "[{ A[x] -> [(1)] : x >= 5 }]",
6039 	  "[{ A[x] -> [(x)] : x <= 10 }]",
6040 	  "[{ A[x] -> [(1 + x)] : 5 <= x <= 10 }]" },
6041 	{ &isl_multi_union_pw_aff_add, "([] : { A[x] : x >= 5 })",
6042 	  "([] : { A[x] : x <= 10 })",
6043 	  "([] : { A[x] : 5 <= x <= 10 })" },
6044 	{ &isl_multi_union_pw_aff_add, "([] : { A[x] : x >= 5 })",
6045 	  "[N] -> ([] : { A[x] : x <= N })",
6046 	  "[N] -> ([] : { A[x] : 5 <= x <= N })" },
6047 	{ &isl_multi_union_pw_aff_add, "[N] -> ([] : { A[x] : x >= N })",
6048 	  "([] : { A[x] : x <= 10 })",
6049 	  "[N] -> ([] : { A[x] : N <= x <= 10 })" },
6050 	{ &isl_multi_union_pw_aff_union_add, "[{ A[x] -> [(1)] : x >= 5 }]",
6051 	  "[{ A[x] -> [(x)] : x <= 10 }]",
6052 	  "[{ A[x] -> [(1 + x)] : 5 <= x <= 10; "
6053 	     "A[x] -> [(1)] : x > 10; A[x] -> [(x)] : x < 5 }]" },
6054 	{ &isl_multi_union_pw_aff_union_add, "([] : { A[x] : x >= 5 })",
6055 	  "([] : { A[x] : x <= 10 })",
6056 	  "([] : { A[x] })" },
6057 	{ &isl_multi_union_pw_aff_union_add, "([] : { A[x] : x >= 0 })",
6058 	  "[N] -> ([] : { A[x] : x >= N })",
6059 	  "[N] -> ([] : { A[x] : x >= 0 or x >= N })" },
6060 	{ &isl_multi_union_pw_aff_union_add,
6061 	  "[N] -> ([] : { A[] : N >= 0})",
6062 	  "[N] -> ([] : { A[] : N <= 0})",
6063 	  "[N] -> ([] : { A[] })" },
6064 	{ &isl_multi_union_pw_aff_union_add,
6065 	  "[N] -> ([] : { A[] })",
6066 	  "[N] -> ([] : { : })",
6067 	  "[N] -> ([] : { : })" },
6068 	{ &isl_multi_union_pw_aff_union_add,
6069 	  "[N] -> ([] : { : })",
6070 	  "[N] -> ([] : { A[] })",
6071 	  "[N] -> ([] : { : })" },
6072 	{ &isl_multi_union_pw_aff_union_add,
6073 	  "[N] -> ([] : { : N >= 0})",
6074 	  "[N] -> ([] : { : N <= 0})",
6075 	  "[N] -> ([] : { : })" },
6076 	{ &isl_multi_union_pw_aff_range_product,
6077 	  "B[{ A[] -> [1] }]",
6078 	  "C[{ A[] -> [2] }]",
6079 	  "[B[{ A[] -> [1] }] -> C[{ A[] -> [2] }]]" },
6080 	{ &isl_multi_union_pw_aff_range_product,
6081 	  "(B[] : { A[x] : x >= 5 })",
6082 	  "(C[] : { A[x] : x <= 10 })",
6083 	  "([B[] -> C[]] : { A[x] : 5 <= x <= 10 })" },
6084 	{ &isl_multi_union_pw_aff_range_product,
6085 	  "B[{ A[x] -> [x + 1] : x >= 5 }]",
6086 	  "(C[] : { A[x] : x <= 10 })",
6087 	  "[B[{ A[x] -> [x + 1] : 5 <= x <= 10 }] -> C[]]" },
6088 	{ &isl_multi_union_pw_aff_range_product,
6089 	  "(C[] : { A[x] : x <= 10 })",
6090 	  "B[{ A[x] -> [x + 1] : x >= 5 }]",
6091 	  "[C[] -> B[{ A[x] -> [x + 1] : 5 <= x <= 10 }]]" },
6092 	{ &isl_multi_union_pw_aff_range_product,
6093 	  "B[{ A[x] -> [x + 1] : x >= 5 }]",
6094 	  "[N] -> (C[] : { A[x] : x <= N })",
6095 	  "[N] -> [B[{ A[x] -> [x + 1] : 5 <= x <= N }] -> C[]]" },
6096 	{ &isl_multi_union_pw_aff_range_product,
6097 	  "[N] -> (C[] : { A[x] : x <= N })",
6098 	  "B[{ A[x] -> [x + 1] : x >= 5 }]",
6099 	  "[N] -> [C[] -> B[{ A[x] -> [x + 1] : 5 <= x <= N }]]" },
6100 	{ &isl_multi_union_pw_aff_range_product,
6101 	  "B[{ A[] -> [1]; D[] -> [3] }]",
6102 	  "C[{ A[] -> [2] }]",
6103 	  "[B[{ A[] -> [1]; D[] -> [3] }] -> C[{ A[] -> [2] }]]" },
6104 	{ &isl_multi_union_pw_aff_range_product,
6105 	  "B[] }]",
6106 	  "(C[] : { A[x] })",
6107 	  "([B[] -> C[]] : { A[x] })" },
6108 	{ &isl_multi_union_pw_aff_range_product,
6109 	  "(B[] : { A[x] })",
6110 	  "C[] }]",
6111 	  "([B[] -> C[]] : { A[x] })" },
6112 };
6113 
6114 /* Perform some basic tests of binary operations on
6115  * isl_multi_union_pw_aff objects.
6116  */
test_bin_mupa(isl_ctx * ctx)6117 static int test_bin_mupa(isl_ctx *ctx)
6118 {
6119 	int i;
6120 	isl_bool ok;
6121 	isl_multi_union_pw_aff *mupa1, *mupa2, *res;
6122 
6123 	for (i = 0; i < ARRAY_SIZE(mupa_bin_tests); ++i) {
6124 		mupa1 = isl_multi_union_pw_aff_read_from_str(ctx,
6125 							mupa_bin_tests[i].arg1);
6126 		mupa2 = isl_multi_union_pw_aff_read_from_str(ctx,
6127 							mupa_bin_tests[i].arg2);
6128 		res = isl_multi_union_pw_aff_read_from_str(ctx,
6129 							mupa_bin_tests[i].res);
6130 		mupa1 = mupa_bin_tests[i].fn(mupa1, mupa2);
6131 		ok = isl_multi_union_pw_aff_plain_is_equal(mupa1, res);
6132 		isl_multi_union_pw_aff_free(mupa1);
6133 		isl_multi_union_pw_aff_free(res);
6134 		if (ok < 0)
6135 			return -1;
6136 		if (!ok)
6137 			isl_die(ctx, isl_error_unknown,
6138 				"unexpected result", return -1);
6139 	}
6140 
6141 	return 0;
6142 }
6143 
6144 /* Inputs for basic tests of binary operations on
6145  * pairs of isl_multi_union_pw_aff and isl_set objects.
6146  * "fn" is the function that is tested.
6147  * "arg1" and "arg2" are string descriptions of the inputs.
6148  * "res" is a string description of the expected result.
6149  */
6150 struct {
6151 	__isl_give isl_multi_union_pw_aff *(*fn)(
6152 		__isl_take isl_multi_union_pw_aff *mupa,
6153 		__isl_take isl_set *set);
6154 	const char *arg1;
6155 	const char *arg2;
6156 	const char *res;
6157 } mupa_set_tests[] = {
6158 	{ &isl_multi_union_pw_aff_intersect_range,
6159 	  "C[{ B[i,j] -> [i + 2j] }]", "{ C[1] }",
6160 	  "C[{ B[i,j] -> [i + 2j] : i + 2j = 1 }]" },
6161 	{ &isl_multi_union_pw_aff_intersect_range,
6162 	  "C[{ B[i,j] -> [i + 2j] }]", "[N] -> { C[N] }",
6163 	  "[N] -> C[{ B[i,j] -> [i + 2j] : i + 2j = N }]" },
6164 	{ &isl_multi_union_pw_aff_intersect_range,
6165 	  "[N] -> C[{ B[i,j] -> [i + 2j + N] }]", "{ C[1] }",
6166 	  "[N] -> C[{ B[i,j] -> [i + 2j + N] : i + 2j + N = 1 }]" },
6167 	{ &isl_multi_union_pw_aff_intersect_range,
6168 	  "C[{ B[i,j] -> [i + 2j] }]", "[N] -> { C[x] : N >= 0 }",
6169 	  "[N] -> C[{ B[i,j] -> [i + 2j] : N >= 0 }]" },
6170 	{ &isl_multi_union_pw_aff_intersect_range,
6171 	  "C[]", "{ C[] }", "C[]" },
6172 	{ &isl_multi_union_pw_aff_intersect_range,
6173 	  "[N] -> (C[] : { : N >= 0 })",
6174 	  "{ C[] }",
6175 	  "[N] -> (C[] : { : N >= 0 })" },
6176 	{ &isl_multi_union_pw_aff_intersect_range,
6177 	  "(C[] : { A[a,b] })",
6178 	  "{ C[] }",
6179 	  "(C[] : { A[a,b] })" },
6180 	{ &isl_multi_union_pw_aff_intersect_range,
6181 	  "[N] -> (C[] : { A[a,b] : a,b <= N })",
6182 	  "{ C[] }",
6183 	  "[N] -> (C[] : { A[a,b] : a,b <= N })" },
6184 	{ &isl_multi_union_pw_aff_intersect_range,
6185 	  "C[]",
6186 	  "[N] -> { C[] : N >= 0 }",
6187 	  "[N] -> (C[] : { : N >= 0 })" },
6188 	{ &isl_multi_union_pw_aff_intersect_range,
6189 	  "(C[] : { A[a,b] })",
6190 	  "[N] -> { C[] : N >= 0 }",
6191 	  "[N] -> (C[] : { A[a,b] : N >= 0 })" },
6192 	{ &isl_multi_union_pw_aff_intersect_range,
6193 	  "[N] -> (C[] : { : N >= 0 })",
6194 	  "[N] -> { C[] : N < 1024 }",
6195 	  "[N] -> (C[] : { : 0 <= N < 1024 })" },
6196 	{ &isl_multi_union_pw_aff_intersect_params,
6197 	  "C[{ B[i,j] -> [i + 2j] }]", "[N] -> { : N >= 0 }",
6198 	  "[N] -> C[{ B[i,j] -> [i + 2j] : N >= 0}]" },
6199 	{ &isl_multi_union_pw_aff_intersect_params,
6200 	  "[N] -> C[{ B[i,j] -> [i + 2j] : N <= 256 }]", "[N] -> { : N >= 0 }",
6201 	  "[N] -> C[{ B[i,j] -> [i + 2j] : 0 <= N <= 256 }]" },
6202 	{ &isl_multi_union_pw_aff_intersect_params,
6203 	  "[N] -> C[{ B[i,j] -> [i + 2j] : N <= 256 }]", "{ : }",
6204 	  "[N] -> C[{ B[i,j] -> [i + 2j] : N <= 256 }]" },
6205 	{ &isl_multi_union_pw_aff_intersect_params,
6206 	  "C[]", "[N] -> { : N >= 0 }",
6207 	  "[N] -> (C[] : { : N >= 0 })" },
6208 	{ &isl_multi_union_pw_aff_intersect_params,
6209 	  "(C[] : { A[a,b] })", "[N] -> { : N >= 0 }",
6210 	  "[N] -> (C[] : { A[a,b] : N >= 0 })" },
6211 	{ &isl_multi_union_pw_aff_intersect_params,
6212 	  "[N] -> (C[] : { A[a,N] })", "{ : }",
6213 	  "[N] -> (C[] : { A[a,N] })" },
6214 	{ &isl_multi_union_pw_aff_intersect_params,
6215 	  "[N] -> (C[] : { A[a,b] : N <= 256 })", "[N] -> { : N >= 0 }",
6216 	  "[N] -> (C[] : { A[a,b] : 0 <= N <= 256 })" },
6217 };
6218 
6219 /* Perform some basic tests of binary operations on
6220  * pairs of isl_multi_union_pw_aff and isl_set objects.
6221  */
test_mupa_set(isl_ctx * ctx)6222 static int test_mupa_set(isl_ctx *ctx)
6223 {
6224 	int i;
6225 	isl_bool ok;
6226 	isl_multi_union_pw_aff *mupa, *res;
6227 	isl_set *set;
6228 
6229 	for (i = 0; i < ARRAY_SIZE(mupa_set_tests); ++i) {
6230 		mupa = isl_multi_union_pw_aff_read_from_str(ctx,
6231 						    mupa_set_tests[i].arg1);
6232 		set = isl_set_read_from_str(ctx, mupa_set_tests[i].arg2);
6233 		res = isl_multi_union_pw_aff_read_from_str(ctx,
6234 						    mupa_set_tests[i].res);
6235 		mupa = mupa_set_tests[i].fn(mupa, set);
6236 		ok = isl_multi_union_pw_aff_plain_is_equal(mupa, res);
6237 		isl_multi_union_pw_aff_free(mupa);
6238 		isl_multi_union_pw_aff_free(res);
6239 		if (ok < 0)
6240 			return -1;
6241 		if (!ok)
6242 			isl_die(ctx, isl_error_unknown,
6243 				"unexpected result", return -1);
6244 	}
6245 
6246 	return 0;
6247 }
6248 
6249 /* Inputs for basic tests of binary operations on
6250  * pairs of isl_multi_union_pw_aff and isl_union_set objects.
6251  * "fn" is the function that is tested.
6252  * "arg1" and "arg2" are string descriptions of the inputs.
6253  * "res" is a string description of the expected result.
6254  */
6255 struct {
6256 	__isl_give isl_multi_union_pw_aff *(*fn)(
6257 		__isl_take isl_multi_union_pw_aff *mupa,
6258 		__isl_take isl_union_set *uset);
6259 	const char *arg1;
6260 	const char *arg2;
6261 	const char *res;
6262 } mupa_uset_tests[] = {
6263 	{ &isl_multi_union_pw_aff_intersect_domain,
6264 	  "C[{ B[i,j] -> [i + 2j] }]", "{ B[i,i] }",
6265 	  "C[{ B[i,i] -> [3i] }]" },
6266 	{ &isl_multi_union_pw_aff_intersect_domain,
6267 	  "(C[] : { B[i,j] })", "{ B[i,i] }",
6268 	  "(C[] : { B[i,i] })" },
6269 	{ &isl_multi_union_pw_aff_intersect_domain,
6270 	  "(C[] : { B[i,j] })", "[N] -> { B[N,N] }",
6271 	  "[N] -> (C[] : { B[N,N] })" },
6272 	{ &isl_multi_union_pw_aff_intersect_domain,
6273 	  "C[]", "{ B[i,i] }",
6274 	  "(C[] : { B[i,i] })" },
6275 	{ &isl_multi_union_pw_aff_intersect_domain,
6276 	  "[N] -> (C[] : { : N >= 0 })", "{ B[i,i] }",
6277 	  "[N] -> (C[] : { B[i,i] : N >= 0 })" },
6278 };
6279 
6280 /* Perform some basic tests of binary operations on
6281  * pairs of isl_multi_union_pw_aff and isl_union_set objects.
6282  */
test_mupa_uset(isl_ctx * ctx)6283 static int test_mupa_uset(isl_ctx *ctx)
6284 {
6285 	int i;
6286 	isl_bool ok;
6287 	isl_multi_union_pw_aff *mupa, *res;
6288 	isl_union_set *uset;
6289 
6290 	for (i = 0; i < ARRAY_SIZE(mupa_uset_tests); ++i) {
6291 		mupa = isl_multi_union_pw_aff_read_from_str(ctx,
6292 						    mupa_uset_tests[i].arg1);
6293 		uset = isl_union_set_read_from_str(ctx,
6294 						    mupa_uset_tests[i].arg2);
6295 		res = isl_multi_union_pw_aff_read_from_str(ctx,
6296 						    mupa_uset_tests[i].res);
6297 		mupa = mupa_uset_tests[i].fn(mupa, uset);
6298 		ok = isl_multi_union_pw_aff_plain_is_equal(mupa, res);
6299 		isl_multi_union_pw_aff_free(mupa);
6300 		isl_multi_union_pw_aff_free(res);
6301 		if (ok < 0)
6302 			return -1;
6303 		if (!ok)
6304 			isl_die(ctx, isl_error_unknown,
6305 				"unexpected result", return -1);
6306 	}
6307 
6308 	return 0;
6309 }
6310 
6311 /* Inputs for basic tests of binary operations on
6312  * pairs of isl_multi_union_pw_aff and isl_multi_aff objects.
6313  * "fn" is the function that is tested.
6314  * "arg1" and "arg2" are string descriptions of the inputs.
6315  * "res" is a string description of the expected result.
6316  */
6317 struct {
6318 	__isl_give isl_multi_union_pw_aff *(*fn)(
6319 		__isl_take isl_multi_union_pw_aff *mupa,
6320 		__isl_take isl_multi_aff *ma);
6321 	const char *arg1;
6322 	const char *arg2;
6323 	const char *res;
6324 } mupa_ma_tests[] = {
6325 	{ &isl_multi_union_pw_aff_apply_multi_aff,
6326 	  "C[{ A[i,j] -> [i]; B[i,j] -> [j] }, "
6327 	    "{ A[i,j] -> [j]; B[i,j] -> [i] }]",
6328 	  "{ C[a,b] -> D[b,a] }",
6329 	  "D[{ A[i,j] -> [j]; B[i,j] -> [i] }, "
6330 	    "{ A[i,j] -> [i]; B[i,j] -> [j] }]" },
6331 	{ &isl_multi_union_pw_aff_apply_multi_aff,
6332 	  "C[{ A[i,j] -> [i] : i >= 0; B[i,j] -> [j] }, "
6333 	    "{ A[i,j] -> [j]; B[i,j] -> [i] }]",
6334 	  "{ C[a,b] -> D[b,a] }",
6335 	  "D[{ A[i,j] -> [j] : i >= 0; B[i,j] -> [i] }, "
6336 	    "{ A[i,j] -> [i] : i >= 0; B[i,j] -> [j] }]" },
6337 	{ &isl_multi_union_pw_aff_apply_multi_aff,
6338 	  "C[{ A[i,j] -> [i]; B[i,j] -> [j] }]",
6339 	  "[N] -> { C[a] -> D[a + N] }",
6340 	  "[N] -> D[{ A[i,j] -> [i + N]; B[i,j] -> [j + N] }] " },
6341 	{ &isl_multi_union_pw_aff_apply_multi_aff,
6342 	  "C[]",
6343 	  "{ C[] -> D[] }",
6344 	  "D[]" },
6345 	{ &isl_multi_union_pw_aff_apply_multi_aff,
6346 	  "[N] -> (C[] : { : N >= 0 })",
6347 	  "{ C[] -> D[] }",
6348 	  "[N] -> (D[] : { : N >= 0 })" },
6349 	{ &isl_multi_union_pw_aff_apply_multi_aff,
6350 	  "C[]",
6351 	  "[N] -> { C[] -> D[N] }",
6352 	  "[N] -> D[{ [N] }]" },
6353 	{ &isl_multi_union_pw_aff_apply_multi_aff,
6354 	  "(C[] : { A[i,j] : i >= j })",
6355 	  "{ C[] -> D[] }",
6356 	  "(D[] : { A[i,j] : i >= j })" },
6357 	{ &isl_multi_union_pw_aff_apply_multi_aff,
6358 	  "[N] -> (C[] : { A[i,j] : N >= 0 })",
6359 	  "{ C[] -> D[] }",
6360 	  "[N] -> (D[] : { A[i,j] : N >= 0 })" },
6361 	{ &isl_multi_union_pw_aff_apply_multi_aff,
6362 	  "(C[] : { A[i,j] : i >= j })",
6363 	  "[N] -> { C[] -> D[N] }",
6364 	  "[N] -> (D[{ A[i,j] -> [N] : i >= j }])" },
6365 };
6366 
6367 /* Perform some basic tests of binary operations on
6368  * pairs of isl_multi_union_pw_aff and isl_multi_aff objects.
6369  */
test_mupa_ma(isl_ctx * ctx)6370 static int test_mupa_ma(isl_ctx *ctx)
6371 {
6372 	int i;
6373 	isl_bool ok;
6374 	isl_multi_union_pw_aff *mupa, *res;
6375 	isl_multi_aff *ma;
6376 
6377 	for (i = 0; i < ARRAY_SIZE(mupa_ma_tests); ++i) {
6378 		mupa = isl_multi_union_pw_aff_read_from_str(ctx,
6379 						    mupa_ma_tests[i].arg1);
6380 		ma = isl_multi_aff_read_from_str(ctx, mupa_ma_tests[i].arg2);
6381 		res = isl_multi_union_pw_aff_read_from_str(ctx,
6382 						    mupa_ma_tests[i].res);
6383 		mupa = mupa_ma_tests[i].fn(mupa, ma);
6384 		ok = isl_multi_union_pw_aff_plain_is_equal(mupa, res);
6385 		isl_multi_union_pw_aff_free(mupa);
6386 		isl_multi_union_pw_aff_free(res);
6387 		if (ok < 0)
6388 			return -1;
6389 		if (!ok)
6390 			isl_die(ctx, isl_error_unknown,
6391 				"unexpected result", return -1);
6392 	}
6393 
6394 	return 0;
6395 }
6396 
6397 /* Inputs for basic tests of binary operations on
6398  * pairs of isl_multi_union_pw_aff and isl_pw_aff objects.
6399  * "fn" is the function that is tested.
6400  * "arg1" and "arg2" are string descriptions of the inputs.
6401  * "res" is a string description of the expected result.
6402  */
6403 struct {
6404 	__isl_give isl_union_pw_aff *(*fn)(
6405 		__isl_take isl_multi_union_pw_aff *mupa,
6406 		__isl_take isl_pw_aff *pa);
6407 	const char *arg1;
6408 	const char *arg2;
6409 	const char *res;
6410 } mupa_pa_tests[] = {
6411 	{ &isl_multi_union_pw_aff_apply_pw_aff,
6412 	  "C[{ A[i,j] -> [i]; B[i,j] -> [j] }]",
6413 	  "[N] -> { C[a] -> [a + N] }",
6414 	  "[N] -> { A[i,j] -> [i + N]; B[i,j] -> [j + N] }" },
6415 	{ &isl_multi_union_pw_aff_apply_pw_aff,
6416 	  "C[{ A[i,j] -> [i]; B[i,j] -> [j] }]",
6417 	  "{ C[a] -> [a] : a >= 0; C[a] -> [-a] : a < 0 }",
6418 	  "{ A[i,j] -> [i] : i >= 0; A[i,j] -> [-i] : i < 0; "
6419 	    "B[i,j] -> [j] : j >= 0; B[i,j] -> [-j] : j < 0 }" },
6420 	{ &isl_multi_union_pw_aff_apply_pw_aff,
6421 	  "C[]",
6422 	  "[N] -> { C[] -> [N] }",
6423 	  "[N] -> { [N] }" },
6424 	{ &isl_multi_union_pw_aff_apply_pw_aff,
6425 	  "C[]",
6426 	  "[N] -> { C[] -> [N] : N >= 0; C[] -> [-N] : N < 0 }",
6427 	  "[N] -> { [N] : N >= 0; [-N] : N < 0 }" },
6428 	{ &isl_multi_union_pw_aff_apply_pw_aff,
6429 	  "[N] -> (C[] : { : N >= 0 })",
6430 	  "[N] -> { C[] -> [N] }",
6431 	  "[N] -> { [N] : N >= 0 }" },
6432 	{ &isl_multi_union_pw_aff_apply_pw_aff,
6433 	  "[N] -> (C[] : { : N >= 0 })",
6434 	  "[N] -> { C[] -> [N] : N >= 0; C[] -> [-N] : N < 0 }",
6435 	  "[N] -> { [N] : N >= 0 }" },
6436 	{ &isl_multi_union_pw_aff_apply_pw_aff,
6437 	  "[N] -> (C[] : { : N >= 0 })",
6438 	  "{ C[] -> [0] }",
6439 	  "[N] -> { [0] : N >= 0 }" },
6440 	{ &isl_multi_union_pw_aff_apply_pw_aff,
6441 	  "(C[] : { A[i,j] : i >= j })",
6442 	  "[N] -> { C[] -> [N] }",
6443 	  "[N] -> { A[i,j] -> [N] : i >= j }" },
6444 	{ &isl_multi_union_pw_aff_apply_pw_aff,
6445 	  "(C[] : { A[i,j] : i >= j })",
6446 	  "[N] -> { C[] -> [N] : N >= 0 }",
6447 	  "[N] -> { A[i,j] -> [N] : i >= j and N >= 0 }" },
6448 };
6449 
6450 /* Perform some basic tests of binary operations on
6451  * pairs of isl_multi_union_pw_aff and isl_pw_aff objects.
6452  */
test_mupa_pa(isl_ctx * ctx)6453 static int test_mupa_pa(isl_ctx *ctx)
6454 {
6455 	int i;
6456 	isl_bool ok;
6457 	isl_multi_union_pw_aff *mupa;
6458 	isl_union_pw_aff *upa, *res;
6459 	isl_pw_aff *pa;
6460 
6461 	for (i = 0; i < ARRAY_SIZE(mupa_pa_tests); ++i) {
6462 		mupa = isl_multi_union_pw_aff_read_from_str(ctx,
6463 						    mupa_pa_tests[i].arg1);
6464 		pa = isl_pw_aff_read_from_str(ctx, mupa_pa_tests[i].arg2);
6465 		res = isl_union_pw_aff_read_from_str(ctx,
6466 						    mupa_pa_tests[i].res);
6467 		upa = mupa_pa_tests[i].fn(mupa, pa);
6468 		ok = isl_union_pw_aff_plain_is_equal(upa, res);
6469 		isl_union_pw_aff_free(upa);
6470 		isl_union_pw_aff_free(res);
6471 		if (ok < 0)
6472 			return -1;
6473 		if (!ok)
6474 			isl_die(ctx, isl_error_unknown,
6475 				"unexpected result", return -1);
6476 	}
6477 
6478 	return 0;
6479 }
6480 
6481 /* Inputs for basic tests of binary operations on
6482  * pairs of isl_multi_union_pw_aff and isl_pw_multi_aff objects.
6483  * "fn" is the function that is tested.
6484  * "arg1" and "arg2" are string descriptions of the inputs.
6485  * "res" is a string description of the expected result.
6486  */
6487 struct {
6488 	__isl_give isl_multi_union_pw_aff *(*fn)(
6489 		__isl_take isl_multi_union_pw_aff *mupa,
6490 		__isl_take isl_pw_multi_aff *pma);
6491 	const char *arg1;
6492 	const char *arg2;
6493 	const char *res;
6494 } mupa_pma_tests[] = {
6495 	{ &isl_multi_union_pw_aff_apply_pw_multi_aff,
6496 	  "C[{ A[i,j] -> [i]; B[i,j] -> [j] }, "
6497 	    "{ A[i,j] -> [j]; B[i,j] -> [i] }]",
6498 	  "{ C[a,b] -> D[b,a] }",
6499 	  "D[{ A[i,j] -> [j]; B[i,j] -> [i] }, "
6500 	    "{ A[i,j] -> [i]; B[i,j] -> [j] }]" },
6501 	{ &isl_multi_union_pw_aff_apply_pw_multi_aff,
6502 	  "C[{ A[i,j] -> [i] : i >= 0; B[i,j] -> [j] }, "
6503 	    "{ A[i,j] -> [j]; B[i,j] -> [i] }]",
6504 	  "{ C[a,b] -> D[b,a] }",
6505 	  "D[{ A[i,j] -> [j] : i >= 0; B[i,j] -> [i] }, "
6506 	    "{ A[i,j] -> [i] : i >= 0; B[i,j] -> [j] }]" },
6507 	{ &isl_multi_union_pw_aff_apply_pw_multi_aff,
6508 	  "C[{ A[i,j] -> [i]; B[i,j] -> [j] }]",
6509 	  "[N] -> { C[a] -> D[a + N] }",
6510 	  "[N] -> D[{ A[i,j] -> [i + N]; B[i,j] -> [j + N] }]" },
6511 	{ &isl_multi_union_pw_aff_apply_pw_multi_aff,
6512 	  "C[{ A[i,j] -> [i]; B[i,j] -> [j] }]",
6513 	  "{ C[a] -> D[a] : a >= 0; C[a] -> D[-a] : a < 0 }",
6514 	  "D[{ A[i,j] -> [i] : i >= 0; A[i,j] -> [-i] : i < 0; "
6515 	      "B[i,j] -> [j] : j >= 0; B[i,j] -> [-j] : j < 0 }]" },
6516 	{ &isl_multi_union_pw_aff_apply_pw_multi_aff,
6517 	  "C[{ A[i,j] -> [i]; B[i,j] -> [j] }, "
6518 	    "{ A[i,j] -> [j]; B[i,j] -> [i] }]",
6519 	  "{ C[a,b] -> D[a,b] : a >= b; C[a,b] -> D[b,a] : a < b }",
6520 	  "D[{ A[i,j] -> [i] : i >= j; A[i,j] -> [j] : i < j; "
6521 	      "B[i,j] -> [j] : i <= j; B[i,j] -> [i] : i > j }, "
6522 	    "{ A[i,j] -> [j] : i >= j; A[i,j] -> [i] : i < j; "
6523 	      "B[i,j] -> [i] : i <= j; B[i,j] -> [j] : i > j }]" },
6524 	{ &isl_multi_union_pw_aff_apply_pw_multi_aff,
6525 	  "C[]",
6526 	  "{ C[] -> D[] }",
6527 	  "D[]" },
6528 	{ &isl_multi_union_pw_aff_apply_pw_multi_aff,
6529 	  "[N] -> (C[] : { : N >= 0 })",
6530 	  "{ C[] -> D[] }",
6531 	  "[N] -> (D[] : { : N >= 0 })" },
6532 	{ &isl_multi_union_pw_aff_apply_pw_multi_aff,
6533 	  "C[]",
6534 	  "[N] -> { C[] -> D[N] }",
6535 	  "[N] -> D[{ [N] }]" },
6536 	{ &isl_multi_union_pw_aff_apply_pw_multi_aff,
6537 	  "(C[] : { A[i,j] : i >= j })",
6538 	  "{ C[] -> D[] }",
6539 	  "(D[] : { A[i,j] : i >= j })" },
6540 	{ &isl_multi_union_pw_aff_apply_pw_multi_aff,
6541 	  "[N] -> (C[] : { A[i,j] : N >= 0 })",
6542 	  "{ C[] -> D[] }",
6543 	  "[N] -> (D[] : { A[i,j] : N >= 0 })" },
6544 	{ &isl_multi_union_pw_aff_apply_pw_multi_aff,
6545 	  "(C[] : { A[i,j] : i >= j })",
6546 	  "[N] -> { C[] -> D[N] }",
6547 	  "[N] -> (D[{ A[i,j] -> [N] : i >= j }])" },
6548 	{ &isl_multi_union_pw_aff_apply_pw_multi_aff,
6549 	  "C[]",
6550 	  "[N] -> { C[] -> D[N] : N >= 0; C[] -> D[-N] : N < 0 }",
6551 	  "[N] -> D[{ [N] : N >= 0; [-N] : N < 0 }]" },
6552 	{ &isl_multi_union_pw_aff_apply_pw_multi_aff,
6553 	  "[N] -> (C[] : { : N >= 0 })",
6554 	  "[N] -> { C[] -> D[N] }",
6555 	  "[N] -> D[{ [N] : N >= 0 }]" },
6556 	{ &isl_multi_union_pw_aff_apply_pw_multi_aff,
6557 	  "[N] -> (C[] : { : N >= 0 })",
6558 	  "[N] -> { C[] -> D[N] : N >= 0; C[] -> D[-N] : N < 0 }",
6559 	  "[N] -> D[{ [N] : N >= 0 }]" },
6560 	{ &isl_multi_union_pw_aff_apply_pw_multi_aff,
6561 	  "[N] -> (C[] : { : N >= 0 })",
6562 	  "{ C[] -> D[0] }",
6563 	  "[N] -> D[{ [0] : N >= 0 }]" },
6564 	{ &isl_multi_union_pw_aff_apply_pw_multi_aff,
6565 	  "(C[] : { A[i,j] : i >= j })",
6566 	  "[N] -> { C[] -> D[N] : N >= 0 }",
6567 	  "[N] -> D[{ A[i,j] -> [N] : i >= j and N >= 0 }]" },
6568 };
6569 
6570 /* Perform some basic tests of binary operations on
6571  * pairs of isl_multi_union_pw_aff and isl_pw_multi_aff objects.
6572  */
test_mupa_pma(isl_ctx * ctx)6573 static int test_mupa_pma(isl_ctx *ctx)
6574 {
6575 	int i;
6576 	isl_bool ok;
6577 	isl_multi_union_pw_aff *mupa, *res;
6578 	isl_pw_multi_aff *pma;
6579 
6580 	for (i = 0; i < ARRAY_SIZE(mupa_pma_tests); ++i) {
6581 		mupa = isl_multi_union_pw_aff_read_from_str(ctx,
6582 						    mupa_pma_tests[i].arg1);
6583 		pma = isl_pw_multi_aff_read_from_str(ctx,
6584 						    mupa_pma_tests[i].arg2);
6585 		res = isl_multi_union_pw_aff_read_from_str(ctx,
6586 						    mupa_pma_tests[i].res);
6587 		mupa = mupa_pma_tests[i].fn(mupa, pma);
6588 		ok = isl_multi_union_pw_aff_plain_is_equal(mupa, res);
6589 		isl_multi_union_pw_aff_free(mupa);
6590 		isl_multi_union_pw_aff_free(res);
6591 		if (ok < 0)
6592 			return -1;
6593 		if (!ok)
6594 			isl_die(ctx, isl_error_unknown,
6595 				"unexpected result", return -1);
6596 	}
6597 
6598 	return 0;
6599 }
6600 
6601 /* Inputs for basic tests of binary operations on
6602  * pairs of isl_multi_union_pw_aff and isl_union_pw_multi_aff objects.
6603  * "fn" is the function that is tested.
6604  * "arg1" and "arg2" are string descriptions of the inputs.
6605  * "res" is a string description of the expected result.
6606  */
6607 struct {
6608 	__isl_give isl_multi_union_pw_aff *(*fn)(
6609 		__isl_take isl_multi_union_pw_aff *mupa,
6610 		__isl_take isl_union_pw_multi_aff *upma);
6611 	const char *arg1;
6612 	const char *arg2;
6613 	const char *res;
6614 } mupa_upma_tests[] = {
6615 	{ &isl_multi_union_pw_aff_pullback_union_pw_multi_aff,
6616 	  "C[{ B[i,j] -> [i + 2j] }]", "{ A[a,b] -> B[b,a] }",
6617 	  "C[{ A[a,b] -> [b + 2a] }]" },
6618 	{ &isl_multi_union_pw_aff_pullback_union_pw_multi_aff,
6619 	  "C[{ B[i,j] -> [i + 2j] }]",
6620 	  "{ A[a,b] -> B[b,a] : b > a }",
6621 	  "C[{ A[a,b] -> [b + 2a] : b > a }]" },
6622 	{ &isl_multi_union_pw_aff_pullback_union_pw_multi_aff,
6623 	  "C[{ B[i,j] -> [i + 2j] : j > 4 }]",
6624 	  "{ A[a,b] -> B[b,a] : b > a }",
6625 	  "C[{ A[a,b] -> [b + 2a] : b > a > 4 }]" },
6626 	{ &isl_multi_union_pw_aff_pullback_union_pw_multi_aff,
6627 	  "C[{ B[i,j] -> [i + 2j] }]",
6628 	  "{ A[a,b] -> B[b,a] : a > b; A[a,b] -> B[a,b] : a <= b }",
6629 	  "C[{ A[a,b] -> [b + 2a] : a > b; A[a,b] -> [a + 2b] : a <= b }]" },
6630 	{ &isl_multi_union_pw_aff_pullback_union_pw_multi_aff,
6631 	  "(C[] : { B[a,b] })",
6632 	  "{ A[a,b] -> B[b,a] }",
6633 	  "(C[] : { A[a,b] })" },
6634 	{ &isl_multi_union_pw_aff_pullback_union_pw_multi_aff,
6635 	  "(C[] : { B[a,b] })",
6636 	  "{ B[a,b] -> A[b,a] }",
6637 	  "(C[] : { })" },
6638 	{ &isl_multi_union_pw_aff_pullback_union_pw_multi_aff,
6639 	  "(C[] : { B[a,b] })",
6640 	  "{ A[a,b] -> B[b,a] : a > b }",
6641 	  "(C[] : { A[a,b] : a > b })" },
6642 	{ &isl_multi_union_pw_aff_pullback_union_pw_multi_aff,
6643 	  "(C[] : { B[a,b] : a > b })",
6644 	  "{ A[a,b] -> B[b,a] }",
6645 	  "(C[] : { A[a,b] : b > a })" },
6646 	{ &isl_multi_union_pw_aff_pullback_union_pw_multi_aff,
6647 	  "[N] -> (C[] : { B[a,b] : a > N })",
6648 	  "{ A[a,b] -> B[b,a] : a > b }",
6649 	  "[N] -> (C[] : { A[a,b] : a > b > N })" },
6650 	{ &isl_multi_union_pw_aff_pullback_union_pw_multi_aff,
6651 	  "(C[] : { B[a,b] : a > b })",
6652 	  "[N] -> { A[a,b] -> B[b,a] : a > N }",
6653 	  "[N] -> (C[] : { A[a,b] : b > a > N })" },
6654 	{ &isl_multi_union_pw_aff_pullback_union_pw_multi_aff,
6655 	  "C[]",
6656 	  "{ A[a,b] -> B[b,a] }",
6657 	  "C[]" },
6658 	{ &isl_multi_union_pw_aff_pullback_union_pw_multi_aff,
6659 	  "[N] -> (C[] : { : N >= 0 })",
6660 	  "{ A[a,b] -> B[b,a] }",
6661 	  "[N] -> (C[] : { : N >= 0 })" },
6662 	{ &isl_multi_union_pw_aff_pullback_union_pw_multi_aff,
6663 	  "C[]",
6664 	  "[N] -> { A[a,b] -> B[b,a] : N >= 0 }",
6665 	  "[N] -> (C[] : { : N >= 0 })" },
6666 };
6667 
6668 /* Perform some basic tests of binary operations on
6669  * pairs of isl_multi_union_pw_aff and isl_union_pw_multi_aff objects.
6670  */
test_mupa_upma(isl_ctx * ctx)6671 static int test_mupa_upma(isl_ctx *ctx)
6672 {
6673 	int i;
6674 	isl_bool ok;
6675 	isl_multi_union_pw_aff *mupa, *res;
6676 	isl_union_pw_multi_aff *upma;
6677 
6678 	for (i = 0; i < ARRAY_SIZE(mupa_upma_tests); ++i) {
6679 		mupa = isl_multi_union_pw_aff_read_from_str(ctx,
6680 						    mupa_upma_tests[i].arg1);
6681 		upma = isl_union_pw_multi_aff_read_from_str(ctx,
6682 						    mupa_upma_tests[i].arg2);
6683 		res = isl_multi_union_pw_aff_read_from_str(ctx,
6684 						    mupa_upma_tests[i].res);
6685 		mupa = mupa_upma_tests[i].fn(mupa, upma);
6686 		ok = isl_multi_union_pw_aff_plain_is_equal(mupa, res);
6687 		isl_multi_union_pw_aff_free(mupa);
6688 		isl_multi_union_pw_aff_free(res);
6689 		if (ok < 0)
6690 			return -1;
6691 		if (!ok)
6692 			isl_die(ctx, isl_error_unknown,
6693 				"unexpected result", return -1);
6694 	}
6695 
6696 	return 0;
6697 }
6698 
6699 /* Check that the input tuple of an isl_aff can be set properly.
6700  */
test_aff_set_tuple_id(isl_ctx * ctx)6701 static isl_stat test_aff_set_tuple_id(isl_ctx *ctx)
6702 {
6703 	isl_id *id;
6704 	isl_aff *aff;
6705 	isl_stat equal;
6706 
6707 	aff = isl_aff_read_from_str(ctx, "{ [x] -> [x + 1] }");
6708 	id = isl_id_alloc(ctx, "A", NULL);
6709 	aff = isl_aff_set_tuple_id(aff, isl_dim_in, id);
6710 	equal = aff_check_plain_equal(aff, "{ A[x] -> [x + 1] }");
6711 	isl_aff_free(aff);
6712 	if (equal < 0)
6713 		return isl_stat_error;
6714 
6715 	return isl_stat_ok;
6716 }
6717 
6718 /* Check that affine expressions get normalized on addition/subtraction.
6719  * In particular, check that (final) unused integer divisions get removed
6720  * such that an expression derived from expressions with integer divisions
6721  * is found to be obviously equal to one that is created directly.
6722  */
test_aff_normalize(isl_ctx * ctx)6723 static isl_stat test_aff_normalize(isl_ctx *ctx)
6724 {
6725 	isl_aff *aff, *aff2;
6726 	isl_stat ok;
6727 
6728 	aff = isl_aff_read_from_str(ctx, "{ [x] -> [x//2] }");
6729 	aff2 = isl_aff_read_from_str(ctx, "{ [x] -> [1 + x//2] }");
6730 	aff = isl_aff_sub(aff2, aff);
6731 	ok = aff_check_plain_equal(aff, "{ [x] -> [1] }");
6732 	isl_aff_free(aff);
6733 
6734 	return ok;
6735 }
6736 
test_aff(isl_ctx * ctx)6737 int test_aff(isl_ctx *ctx)
6738 {
6739 	const char *str;
6740 	isl_set *set;
6741 	isl_space *space;
6742 	isl_local_space *ls;
6743 	isl_aff *aff;
6744 	int zero;
6745 	isl_stat equal;
6746 
6747 	if (test_upa(ctx) < 0)
6748 		return -1;
6749 	if (test_bin_aff(ctx) < 0)
6750 		return -1;
6751 	if (test_bin_pw_aff(ctx) < 0)
6752 		return -1;
6753 	if (test_upma_test(ctx) < 0)
6754 		return -1;
6755 	if (test_bin_upma(ctx) < 0)
6756 		return -1;
6757 	if (test_bin_upma_fail(ctx) < 0)
6758 		return -1;
6759 	if (test_upma_uset(ctx) < 0)
6760 		return -1;
6761 	if (test_un_mpa(ctx) < 0)
6762 		return -1;
6763 	if (test_bin_mpa(ctx) < 0)
6764 		return -1;
6765 	if (test_un_mupa(ctx) < 0)
6766 		return -1;
6767 	if (test_bin_mupa(ctx) < 0)
6768 		return -1;
6769 	if (test_mupa_set(ctx) < 0)
6770 		return -1;
6771 	if (test_mupa_uset(ctx) < 0)
6772 		return -1;
6773 	if (test_mupa_ma(ctx) < 0)
6774 		return -1;
6775 	if (test_mupa_pa(ctx) < 0)
6776 		return -1;
6777 	if (test_mupa_pma(ctx) < 0)
6778 		return -1;
6779 	if (test_mupa_upma(ctx) < 0)
6780 		return -1;
6781 
6782 	space = isl_space_set_alloc(ctx, 0, 1);
6783 	ls = isl_local_space_from_space(space);
6784 	aff = isl_aff_zero_on_domain(ls);
6785 
6786 	aff = isl_aff_add_coefficient_si(aff, isl_dim_in, 0, 1);
6787 	aff = isl_aff_scale_down_ui(aff, 3);
6788 	aff = isl_aff_floor(aff);
6789 	aff = isl_aff_add_coefficient_si(aff, isl_dim_in, 0, 1);
6790 	aff = isl_aff_scale_down_ui(aff, 2);
6791 	aff = isl_aff_floor(aff);
6792 	aff = isl_aff_add_coefficient_si(aff, isl_dim_in, 0, 1);
6793 
6794 	str = "{ [10] }";
6795 	set = isl_set_read_from_str(ctx, str);
6796 	aff = isl_aff_gist(aff, set);
6797 
6798 	aff = isl_aff_add_constant_si(aff, -16);
6799 	zero = isl_aff_plain_is_zero(aff);
6800 	isl_aff_free(aff);
6801 
6802 	if (zero < 0)
6803 		return -1;
6804 	if (!zero)
6805 		isl_die(ctx, isl_error_unknown, "unexpected result", return -1);
6806 
6807 	aff = isl_aff_read_from_str(ctx, "{ [-1] }");
6808 	aff = isl_aff_scale_down_ui(aff, 64);
6809 	aff = isl_aff_floor(aff);
6810 	equal = aff_check_plain_equal(aff, "{ [-1] }");
6811 	isl_aff_free(aff);
6812 	if (equal < 0)
6813 		return -1;
6814 
6815 	if (test_aff_set_tuple_id(ctx) < 0)
6816 		return -1;
6817 	if (test_aff_normalize(ctx) < 0)
6818 		return -1;
6819 
6820 	return 0;
6821 }
6822 
6823 /* Inputs for isl_set_bind tests.
6824  * "set" is the input set.
6825  * "tuple" is the binding tuple.
6826  * "res" is the expected result.
6827  */
6828 static
6829 struct {
6830 	const char *set;
6831 	const char *tuple;
6832 	const char *res;
6833 } bind_set_tests[] = {
6834 	{ "{ A[M, N] : M mod 2 = 0 and N mod 8 = 3 }",
6835 	  "{ A[M, N] }",
6836 	  "[M, N] -> { : M mod 2 = 0 and N mod 8 = 3 }" },
6837 	{ "{ B[N, M] : M mod 2 = 0 and N mod 8 = 3 }",
6838 	  "{ B[N, M] }",
6839 	  "[M, N] -> { : M mod 2 = 0 and N mod 8 = 3 }" },
6840 	{ "[M] -> { C[N] : M mod 2 = 0 and N mod 8 = 3 }",
6841 	  "{ C[N] }",
6842 	  "[M, N] -> { : M mod 2 = 0 and N mod 8 = 3 }" },
6843 	{ "[M] -> { D[x, N] : x mod 2 = 0 and N mod 8 = 3 and M >= 0 }",
6844 	  "{ D[M, N] }",
6845 	  "[M, N] -> { : M mod 2 = 0 and N mod 8 = 3 and M >= 0 }" },
6846 };
6847 
6848 /* Perform basic isl_set_bind tests.
6849  */
test_bind_set(isl_ctx * ctx)6850 static isl_stat test_bind_set(isl_ctx *ctx)
6851 {
6852 	int i;
6853 
6854 	for (i = 0; i < ARRAY_SIZE(bind_set_tests); ++i) {
6855 		const char *str;
6856 		isl_set *set;
6857 		isl_multi_id *tuple;
6858 		isl_stat r;
6859 
6860 		set = isl_set_read_from_str(ctx, bind_set_tests[i].set);
6861 		str = bind_set_tests[i].tuple;
6862 		tuple = isl_multi_id_read_from_str(ctx, str);
6863 		set = isl_set_bind(set, tuple);
6864 		r = set_check_equal(set, bind_set_tests[i].res);
6865 		isl_set_free(set);
6866 		if (r < 0)
6867 			return isl_stat_error;
6868 	}
6869 
6870 	return isl_stat_ok;
6871 }
6872 
6873 /* Inputs for isl_map_bind_domain tests.
6874  * "map" is the input map.
6875  * "tuple" is the binding tuple.
6876  * "res" is the expected result.
6877  */
6878 struct {
6879 	const char *map;
6880 	const char *tuple;
6881 	const char *res;
6882 } bind_map_domain_tests[] = {
6883 	{ "{ A[M, N] -> [M + floor(N/2)] }",
6884 	  "{ A[M, N] }",
6885 	  "[M, N] -> { [M + floor(N/2)] }" },
6886 	{ "{ B[N, M] -> [M + floor(N/2)] }",
6887 	  "{ B[N, M] }",
6888 	  "[N, M] -> { [M + floor(N/2)] }" },
6889 	{ "[M] -> { C[N] -> [M + floor(N/2)] }",
6890 	  "{ C[N] }",
6891 	  "[M, N] -> { [M + floor(N/2)] }" },
6892 	{ "[M] -> { C[x, N] -> [x + floor(N/2)] }",
6893 	  "{ C[M, N] }",
6894 	  "[M, N] -> { [M + floor(N/2)] }" },
6895 	{ "[M] -> { C[x, N] -> [M + floor(N/2)] }",
6896 	  "{ C[M, N] }",
6897 	  "[M, N] -> { [M + floor(N/2)] }" },
6898 	{ "[A, M] -> { C[N, x] -> [x + floor(N/2)] }",
6899 	  "{ C[N, M] }",
6900 	  "[A, N, M] -> { [M + floor(N/2)] }" },
6901 };
6902 
6903 /* Perform basic isl_map_bind_domain tests.
6904  */
test_bind_map_domain(isl_ctx * ctx)6905 static isl_stat test_bind_map_domain(isl_ctx *ctx)
6906 {
6907 	int i;
6908 
6909 	for (i = 0; i < ARRAY_SIZE(bind_map_domain_tests); ++i) {
6910 		const char *str;
6911 		isl_map *map;
6912 		isl_set *set;
6913 		isl_multi_id *tuple;
6914 		isl_stat r;
6915 
6916 		str = bind_map_domain_tests[i].map;
6917 		map = isl_map_read_from_str(ctx, str);
6918 		str = bind_map_domain_tests[i].tuple;
6919 		tuple = isl_multi_id_read_from_str(ctx, str);
6920 		set = isl_map_bind_domain(map, tuple);
6921 		str = bind_map_domain_tests[i].res;
6922 		r = set_check_equal(set, str);
6923 		isl_set_free(set);
6924 		if (r < 0)
6925 			return isl_stat_error;
6926 	}
6927 
6928 	return isl_stat_ok;
6929 }
6930 
6931 /* Inputs for isl_union_map_bind_range tests.
6932  * "map" is the input union map.
6933  * "tuple" is the binding tuple.
6934  * "res" is the expected result.
6935  */
6936 struct {
6937 	const char *map;
6938 	const char *tuple;
6939 	const char *res;
6940 } bind_umap_range_tests[] = {
6941 	{ "{ B[N, M] -> A[M, N] : M mod 2 = 0 and N mod 8 = 3 }",
6942 	  "{ A[M, N] }",
6943 	  "[M, N] -> { B[N, M] : M mod 2 = 0 and N mod 8 = 3 }" },
6944 	{ "{ B[N, M] -> A[M, N] : M mod 2 = 0 and N mod 8 = 3 }",
6945 	  "{ B[M, N] }",
6946 	  "{ }" },
6947 	{ "{ A[] -> B[]; C[] -> D[]; E[] -> B[] }",
6948 	  "{ B[] }",
6949 	  "{ A[]; E[] }" },
6950 };
6951 
6952 /* Perform basic isl_union_map_bind_range tests.
6953  */
test_bind_umap_range(isl_ctx * ctx)6954 static isl_stat test_bind_umap_range(isl_ctx *ctx)
6955 {
6956 	int i;
6957 
6958 	for (i = 0; i < ARRAY_SIZE(bind_umap_range_tests); ++i) {
6959 		const char *str;
6960 		isl_union_map *umap;
6961 		isl_union_set *uset;
6962 		isl_multi_id *tuple;
6963 		isl_stat r;
6964 
6965 		str = bind_umap_range_tests[i].map;
6966 		umap = isl_union_map_read_from_str(ctx, str);
6967 		str = bind_umap_range_tests[i].tuple;
6968 		tuple = isl_multi_id_read_from_str(ctx, str);
6969 		uset = isl_union_map_bind_range(umap, tuple);
6970 		str = bind_umap_range_tests[i].res;
6971 		r = uset_check_equal(uset, str);
6972 		isl_union_set_free(uset);
6973 		if (r < 0)
6974 			return isl_stat_error;
6975 	}
6976 
6977 	return isl_stat_ok;
6978 }
6979 
6980 /* Inputs for isl_pw_multi_aff_bind_domain tests.
6981  * "pma" is the input expression.
6982  * "tuple" is the binding tuple.
6983  * "res" is the expected result.
6984  */
6985 struct {
6986 	const char *pma;
6987 	const char *tuple;
6988 	const char *res;
6989 } bind_pma_domain_tests[] = {
6990 	{ "{ A[M, N] -> [M + floor(N/2)] }",
6991 	  "{ A[M, N] }",
6992 	  "[M, N] -> { [M + floor(N/2)] }" },
6993 	{ "{ B[N, M] -> [M + floor(N/2)] }",
6994 	  "{ B[N, M] }",
6995 	  "[N, M] -> { [M + floor(N/2)] }" },
6996 	{ "[M] -> { C[N] -> [M + floor(N/2)] }",
6997 	  "{ C[N] }",
6998 	  "[M, N] -> { [M + floor(N/2)] }" },
6999 	{ "[M] -> { C[x, N] -> [x + floor(N/2)] }",
7000 	  "{ C[M, N] }",
7001 	  "[M, N] -> { [M + floor(N/2)] }" },
7002 	{ "[M] -> { C[x, N] -> [M + floor(N/2)] }",
7003 	  "{ C[M, N] }",
7004 	  "[M, N] -> { [M + floor(N/2)] }" },
7005 	{ "[A, M] -> { C[N, x] -> [x + floor(N/2)] }",
7006 	  "{ C[N, M] }",
7007 	  "[A, N, M] -> { [M + floor(N/2)] }" },
7008 };
7009 
7010 /* Perform basic isl_pw_multi_aff_bind_domain tests.
7011  */
test_bind_pma_domain(isl_ctx * ctx)7012 static isl_stat test_bind_pma_domain(isl_ctx *ctx)
7013 {
7014 	int i;
7015 
7016 	for (i = 0; i < ARRAY_SIZE(bind_pma_domain_tests); ++i) {
7017 		const char *str;
7018 		isl_pw_multi_aff *pma;
7019 		isl_multi_id *tuple;
7020 		isl_stat r;
7021 
7022 		str = bind_pma_domain_tests[i].pma;
7023 		pma = isl_pw_multi_aff_read_from_str(ctx, str);
7024 		str = bind_pma_domain_tests[i].tuple;
7025 		tuple = isl_multi_id_read_from_str(ctx, str);
7026 		pma = isl_pw_multi_aff_bind_domain(pma, tuple);
7027 		str = bind_pma_domain_tests[i].res;
7028 		r = pw_multi_aff_check_plain_equal(pma, str);
7029 		isl_pw_multi_aff_free(pma);
7030 		if (r < 0)
7031 			return isl_stat_error;
7032 	}
7033 
7034 	return isl_stat_ok;
7035 }
7036 
7037 /* Inputs for isl_pw_multi_aff_bind_domain_wrapped_domain tests.
7038  * "pma" is the input expression.
7039  * "tuple" is the binding tuple.
7040  * "res" is the expected result.
7041  */
7042 struct {
7043 	const char *pma;
7044 	const char *tuple;
7045 	const char *res;
7046 } bind_pma_domain_wrapped_tests[] = {
7047 	{ "{ [A[M, N] -> B[]] -> [M + floor(N/2)] }",
7048 	  "{ A[M, N] }",
7049 	  "[M, N] -> { B[] -> [M + floor(N/2)] }" },
7050 	{ "{ [B[N, M] -> D[]] -> [M + floor(N/2)] }",
7051 	  "{ B[N, M] }",
7052 	  "[N, M] -> { D[] -> [M + floor(N/2)] }" },
7053 	{ "[M] -> { [C[N] -> B[x]] -> [x + M + floor(N/2)] }",
7054 	  "{ C[N] }",
7055 	  "[M, N] -> { B[x] -> [x + M + floor(N/2)] }" },
7056 	{ "[M] -> { [C[x, N] -> B[]] -> [x + floor(N/2)] }",
7057 	  "{ C[M, N] }",
7058 	  "[M, N] -> { B[] -> [M + floor(N/2)] }" },
7059 	{ "[M] -> { [C[x, N] -> B[]] -> [M + floor(N/2)] }",
7060 	  "{ C[M, N] }",
7061 	  "[M, N] -> { B[] -> [M + floor(N/2)] }" },
7062 	{ "[A, M] -> { [C[N, x] -> B[]] -> [x + floor(N/2)] }",
7063 	  "{ C[N, M] }",
7064 	  "[A, N, M] -> { B[] -> [M + floor(N/2)] }" },
7065 };
7066 
7067 /* Perform basic isl_pw_multi_aff_bind_domain_wrapped_domain tests.
7068  */
test_bind_pma_domain_wrapped(isl_ctx * ctx)7069 static isl_stat test_bind_pma_domain_wrapped(isl_ctx *ctx)
7070 {
7071 	int i;
7072 
7073 	for (i = 0; i < ARRAY_SIZE(bind_pma_domain_wrapped_tests); ++i) {
7074 		const char *str;
7075 		isl_pw_multi_aff *pma;
7076 		isl_multi_id *tuple;
7077 		isl_stat r;
7078 
7079 		str = bind_pma_domain_wrapped_tests[i].pma;
7080 		pma = isl_pw_multi_aff_read_from_str(ctx, str);
7081 		str = bind_pma_domain_wrapped_tests[i].tuple;
7082 		tuple = isl_multi_id_read_from_str(ctx, str);
7083 		pma = isl_pw_multi_aff_bind_domain_wrapped_domain(pma, tuple);
7084 		str = bind_pma_domain_wrapped_tests[i].res;
7085 		r = pw_multi_aff_check_plain_equal(pma, str);
7086 		isl_pw_multi_aff_free(pma);
7087 		if (r < 0)
7088 			return isl_stat_error;
7089 	}
7090 
7091 	return isl_stat_ok;
7092 }
7093 
7094 /* Inputs for isl_aff_bind_id tests.
7095  * "aff" is the input expression.
7096  * "id" is the binding id.
7097  * "res" is the expected result.
7098  */
7099 static
7100 struct {
7101 	const char *aff;
7102 	const char *id;
7103 	const char *res;
7104 } bind_aff_tests[] = {
7105 	{ "{ [4] }", "M", "[M = 4] -> { : }" },
7106 	{ "{ B[x] -> [floor(x/2)] }", "M", "[M] -> { B[x] : M = floor(x/2) }" },
7107 	{ "[M] -> { [4] }", "M", "[M = 4] -> { : }" },
7108 	{ "[M] -> { [floor(M/2)] }", "M", "[M] -> { : floor(M/2) = M }" },
7109 	{ "{ [NaN] }", "M", "{ : false }" },
7110 	{ "{ A[x] -> [NaN] }", "M", "{ A[x] : false }" },
7111 };
7112 
7113 /* Perform basic isl_aff_bind_id tests.
7114  */
test_bind_aff(isl_ctx * ctx)7115 static isl_stat test_bind_aff(isl_ctx *ctx)
7116 {
7117 	int i;
7118 
7119 	for (i = 0; i < ARRAY_SIZE(bind_aff_tests); ++i) {
7120 		isl_aff *aff;
7121 		isl_set *res;
7122 		isl_id *id;
7123 		isl_stat r;
7124 
7125 		aff = isl_aff_read_from_str(ctx, bind_aff_tests[i].aff);
7126 		id = isl_id_read_from_str(ctx, bind_aff_tests[i].id);
7127 		res = isl_set_from_basic_set(isl_aff_bind_id(aff, id));
7128 		r = set_check_equal(res, bind_aff_tests[i].res);
7129 		isl_set_free(res);
7130 		if (r < 0)
7131 			return isl_stat_error;
7132 	}
7133 
7134 	return isl_stat_ok;
7135 }
7136 
7137 /* Inputs for isl_pw_aff_bind_id tests.
7138  * "pa" is the input expression.
7139  * "id" is the binding id.
7140  * "res" is the expected result.
7141  */
7142 static
7143 struct {
7144 	const char *pa;
7145 	const char *id;
7146 	const char *res;
7147 } bind_pa_tests[] = {
7148 	{ "{ [4] }", "M", "[M = 4] -> { : }" },
7149 	{ "{ B[x] -> [floor(x/2)] }", "M", "[M] -> { B[x] : M = floor(x/2) }" },
7150 	{ "[M] -> { [4] }", "M", "[M = 4] -> { : }" },
7151 	{ "[M] -> { [floor(M/2)] }", "M", "[M] -> { : floor(M/2) = M }" },
7152 	{ "[M] -> { [M] : M >= 0; [-M] : M < 0 }", "M", "[M] -> { : M >= 0 }" },
7153 	{ "{ [NaN] }", "M", "{ : false }" },
7154 	{ "{ A[x] -> [NaN] }", "M", "{ A[x] : false }" },
7155 };
7156 
7157 /* Perform basic isl_pw_aff_bind_id tests.
7158  */
test_bind_pa(isl_ctx * ctx)7159 static isl_stat test_bind_pa(isl_ctx *ctx)
7160 {
7161 	int i;
7162 
7163 	for (i = 0; i < ARRAY_SIZE(bind_pa_tests); ++i) {
7164 		isl_pw_aff *pa;
7165 		isl_set *res;
7166 		isl_id *id;
7167 		isl_stat r;
7168 
7169 		pa = isl_pw_aff_read_from_str(ctx, bind_pa_tests[i].pa);
7170 		id = isl_id_read_from_str(ctx, bind_pa_tests[i].id);
7171 		res = isl_pw_aff_bind_id(pa, id);
7172 		r = set_check_equal(res, bind_pa_tests[i].res);
7173 		isl_set_free(res);
7174 		if (r < 0)
7175 			return isl_stat_error;
7176 	}
7177 
7178 	return isl_stat_ok;
7179 }
7180 
7181 /* Inputs for isl_multi_union_pw_aff_bind tests.
7182  * "mupa" is the input expression.
7183  * "tuple" is the binding tuple.
7184  * "res" is the expected result.
7185  */
7186 static
7187 struct {
7188 	const char *mupa;
7189 	const char *tuple;
7190 	const char *res;
7191 } bind_mupa_tests[] = {
7192 	{ "A[{ [4] }, { [5] }]",
7193 	  "{ A[M, N] }",
7194 	  "[M = 4, N = 5] -> { : }" },
7195 	{ "A[{ B[x] -> [floor(x/2)] }, { B[y] -> [y + 5] }]",
7196 	  "{ A[M, N] }",
7197 	  "[M, N] -> { B[x] : M = floor(x/2) and N = x + 5 }" },
7198 	{ "[M] -> A[{ [4] }, { [M + 1] }]",
7199 	  "{ A[M, N] }",
7200 	  "[M = 4, N = 5] -> { : }" },
7201 };
7202 
7203 /* Perform basic isl_multi_union_pw_aff_bind tests.
7204  */
test_bind_mupa(isl_ctx * ctx)7205 static isl_stat test_bind_mupa(isl_ctx *ctx)
7206 {
7207 	int i;
7208 
7209 	for (i = 0; i < ARRAY_SIZE(bind_mupa_tests); ++i) {
7210 		const char *str;
7211 		isl_multi_union_pw_aff *mupa;
7212 		isl_union_set *res;
7213 		isl_multi_id *tuple;
7214 		isl_stat r;
7215 
7216 		str = bind_mupa_tests[i].mupa;
7217 		mupa = isl_multi_union_pw_aff_read_from_str(ctx, str);
7218 		str = bind_mupa_tests[i].tuple;
7219 		tuple = isl_multi_id_read_from_str(ctx, str);
7220 		res = isl_multi_union_pw_aff_bind(mupa, tuple);
7221 		r = uset_check_equal(res, bind_mupa_tests[i].res);
7222 		isl_union_set_free(res);
7223 		if (r < 0)
7224 			return isl_stat_error;
7225 	}
7226 
7227 	return isl_stat_ok;
7228 }
7229 
7230 /* Perform tests that reinterpret dimensions as parameters.
7231  */
test_bind(isl_ctx * ctx)7232 static int test_bind(isl_ctx *ctx)
7233 {
7234 	if (test_bind_set(ctx) < 0)
7235 		return -1;
7236 	if (test_bind_map_domain(ctx) < 0)
7237 		return -1;
7238 	if (test_bind_umap_range(ctx) < 0)
7239 		return -1;
7240 	if (test_bind_pma_domain(ctx) < 0)
7241 		return -1;
7242 	if (test_bind_pma_domain_wrapped(ctx) < 0)
7243 		return -1;
7244 	if (test_bind_aff(ctx) < 0)
7245 		return -1;
7246 	if (test_bind_pa(ctx) < 0)
7247 		return -1;
7248 	if (test_bind_mupa(ctx) < 0)
7249 		return -1;
7250 
7251 	return 0;
7252 }
7253 
7254 /* Inputs for isl_set_unbind_params tests.
7255  * "set" is the input parameter domain.
7256  * "tuple" is the tuple of the constructed set.
7257  * "res" is the expected result.
7258  */
7259 struct {
7260 	const char *set;
7261 	const char *tuple;
7262 	const char *res;
7263 } unbind_set_tests[] = {
7264 	{ "[M, N] -> { : M mod 2 = 0 and N mod 8 = 3 }",
7265 	  "{ A[M, N] }",
7266 	  "{ A[M, N] : M mod 2 = 0 and N mod 8 = 3 }" },
7267 	{ "[M, N] -> { : M mod 2 = 0 and N mod 8 = 3 }",
7268 	  "{ B[N, M] }",
7269 	  "{ B[N, M] : M mod 2 = 0 and N mod 8 = 3 }" },
7270 	{ "[M, N] -> { : M mod 2 = 0 and N mod 8 = 3 }",
7271 	  "{ C[N] }",
7272 	  "[M] -> { C[N] : M mod 2 = 0 and N mod 8 = 3 }" },
7273 	{ "[M, N] -> { : M mod 2 = 0 and N mod 8 = 3 }",
7274 	  "{ D[T, N] }",
7275 	  "[M] -> { D[x, N] : M mod 2 = 0 and N mod 8 = 3 }" },
7276 };
7277 
7278 /* Perform basic isl_set_unbind_params tests.
7279  */
test_unbind_set(isl_ctx * ctx)7280 static isl_stat test_unbind_set(isl_ctx *ctx)
7281 {
7282 	int i;
7283 
7284 	for (i = 0; i < ARRAY_SIZE(unbind_set_tests); ++i) {
7285 		const char *str;
7286 		isl_set *set;
7287 		isl_multi_id *tuple;
7288 		isl_stat r;
7289 
7290 		set = isl_set_read_from_str(ctx, unbind_set_tests[i].set);
7291 		str = unbind_set_tests[i].tuple;
7292 		tuple = isl_multi_id_read_from_str(ctx, str);
7293 		set = isl_set_unbind_params(set, tuple);
7294 		r = set_check_equal(set, unbind_set_tests[i].res);
7295 		isl_set_free(set);
7296 		if (r < 0)
7297 			return isl_stat_error;
7298 	}
7299 
7300 	return isl_stat_ok;
7301 }
7302 
7303 /* Inputs for isl_aff_unbind_params_insert_domain tests.
7304  * "aff" is the input affine expression defined over a parameter domain.
7305  * "tuple" is the tuple of the domain that gets introduced.
7306  * "res" is the expected result.
7307  */
7308 struct {
7309 	const char *aff;
7310 	const char *tuple;
7311 	const char *res;
7312 } unbind_aff_tests[] = {
7313 	{ "[M, N] -> { [M + floor(N/2)] }",
7314 	  "{ A[M, N] }",
7315 	  "{ A[M, N] -> [M + floor(N/2)] }" },
7316 	{ "[M, N] -> { [M + floor(N/2)] }",
7317 	  "{ B[N, M] }",
7318 	  "{ B[N, M] -> [M + floor(N/2)] }" },
7319 	{ "[M, N] -> { [M + floor(N/2)] }",
7320 	  "{ C[N] }",
7321 	  "[M] -> { C[N] -> [M + floor(N/2)] }" },
7322 	{ "[M, N] -> { [M + floor(N/2)] }",
7323 	  "{ D[A, B, C, N, Z] }",
7324 	  "[M] -> { D[A, B, C, N, Z] -> [M + floor(N/2)] }" },
7325 };
7326 
7327 /* Perform basic isl_aff_unbind_params_insert_domain tests.
7328  */
test_unbind_aff(isl_ctx * ctx)7329 static isl_stat test_unbind_aff(isl_ctx *ctx)
7330 {
7331 	int i;
7332 
7333 	for (i = 0; i < ARRAY_SIZE(unbind_aff_tests); ++i) {
7334 		const char *str;
7335 		isl_aff *aff;
7336 		isl_multi_id *tuple;
7337 		isl_stat r;
7338 
7339 		aff = isl_aff_read_from_str(ctx, unbind_aff_tests[i].aff);
7340 		str = unbind_aff_tests[i].tuple;
7341 		tuple = isl_multi_id_read_from_str(ctx, str);
7342 		aff = isl_aff_unbind_params_insert_domain(aff, tuple);
7343 		r = aff_check_plain_equal(aff, unbind_aff_tests[i].res);
7344 		isl_aff_free(aff);
7345 		if (r < 0)
7346 			return isl_stat_error;
7347 	}
7348 
7349 	return isl_stat_ok;
7350 }
7351 
7352 /* Inputs for isl_multi_aff_unbind_params_insert_domain tests.
7353  * "ma" is the input multi affine expression defined over a parameter domain.
7354  * "tuple" is the tuple of the domain that gets introduced.
7355  * "res" is the expected result.
7356  */
7357 static struct {
7358 	const char *ma;
7359 	const char *tuple;
7360 	const char *res;
7361 } unbind_multi_aff_tests[] = {
7362 	{ "[M, N] -> { T[M + floor(N/2)] }",
7363 	  "{ A[M, N] }",
7364 	  "{ A[M, N] -> T[M + floor(N/2)] }" },
7365 	{ "[M, N] -> { [M + floor(N/2)] }",
7366 	  "{ B[N, M] }",
7367 	  "{ B[N, M] -> [M + floor(N/2)] }" },
7368 	{ "[M, N] -> { [M + floor(N/2)] }",
7369 	  "{ C[N] }",
7370 	  "[M] -> { C[N] -> [M + floor(N/2)] }" },
7371 	{ "[M, N] -> { [M + floor(N/2)] }",
7372 	  "{ D[A, B, C, N, Z] }",
7373 	  "[M] -> { D[A, B, C, N, Z] -> [M + floor(N/2)] }" },
7374 	{ "[M, N] -> { T[M + floor(N/2), N + floor(M/3)] }",
7375 	  "{ A[M, N] }",
7376 	  "{ A[M, N] -> T[M + floor(N/2), N + floor(M/3)] }" },
7377 };
7378 
7379 /* Perform basic isl_multi_aff_unbind_params_insert_domain tests.
7380  */
test_unbind_multi_aff(isl_ctx * ctx)7381 static isl_stat test_unbind_multi_aff(isl_ctx *ctx)
7382 {
7383 	int i;
7384 
7385 	for (i = 0; i < ARRAY_SIZE(unbind_multi_aff_tests); ++i) {
7386 		const char *str;
7387 		isl_multi_aff *ma;
7388 		isl_multi_id *tuple;
7389 		isl_stat r;
7390 
7391 		str = unbind_multi_aff_tests[i].ma;
7392 		ma = isl_multi_aff_read_from_str(ctx, str);
7393 		str = unbind_multi_aff_tests[i].tuple;
7394 		tuple = isl_multi_id_read_from_str(ctx, str);
7395 		ma = isl_multi_aff_unbind_params_insert_domain(ma, tuple);
7396 		str = unbind_multi_aff_tests[i].res;
7397 		r = multi_aff_check_plain_equal(ma, str);
7398 		isl_multi_aff_free(ma);
7399 		if (r < 0)
7400 			return isl_stat_error;
7401 	}
7402 
7403 	return isl_stat_ok;
7404 }
7405 
7406 /* Perform tests that reinterpret parameters.
7407  */
test_unbind(isl_ctx * ctx)7408 static int test_unbind(isl_ctx *ctx)
7409 {
7410 	if (test_unbind_set(ctx) < 0)
7411 		return -1;
7412 	if (test_unbind_aff(ctx) < 0)
7413 		return -1;
7414 	if (test_unbind_multi_aff(ctx) < 0)
7415 		return -1;
7416 
7417 	return 0;
7418 }
7419 
7420 /* Check that "pa" consists of a single expression.
7421  */
check_single_piece(isl_ctx * ctx,__isl_take isl_pw_aff * pa)7422 static int check_single_piece(isl_ctx *ctx, __isl_take isl_pw_aff *pa)
7423 {
7424 	isl_size n;
7425 
7426 	n = isl_pw_aff_n_piece(pa);
7427 	isl_pw_aff_free(pa);
7428 
7429 	if (n < 0)
7430 		return -1;
7431 	if (n != 1)
7432 		isl_die(ctx, isl_error_unknown, "expecting single expression",
7433 			return -1);
7434 
7435 	return 0;
7436 }
7437 
7438 /* Check that the computation below results in a single expression.
7439  * One or two expressions may result depending on which constraint
7440  * ends up being considered as redundant with respect to the other
7441  * constraints after the projection that is performed internally
7442  * by isl_set_dim_min.
7443  */
test_dim_max_1(isl_ctx * ctx)7444 static int test_dim_max_1(isl_ctx *ctx)
7445 {
7446 	const char *str;
7447 	isl_set *set;
7448 	isl_pw_aff *pa;
7449 
7450 	str = "[n] -> { [a, b] : n >= 0 and 4a >= -4 + n and b >= 0 and "
7451 				"-4a <= b <= 3 and b < n - 4a }";
7452 	set = isl_set_read_from_str(ctx, str);
7453 	pa = isl_set_dim_min(set, 0);
7454 	return check_single_piece(ctx, pa);
7455 }
7456 
7457 /* Check that the computation below results in a single expression.
7458  * The PIP problem corresponding to these constraints has a row
7459  * that causes a split of the solution domain.  The solver should
7460  * first pick rows that split off empty parts such that the actual
7461  * solution domain does not get split.
7462  * Note that the description contains some redundant constraints.
7463  * If these constraints get removed first, then the row mentioned
7464  * above does not appear in the PIP problem.
7465  */
test_dim_max_2(isl_ctx * ctx)7466 static int test_dim_max_2(isl_ctx *ctx)
7467 {
7468 	const char *str;
7469 	isl_set *set;
7470 	isl_pw_aff *pa;
7471 
7472 	str = "[P, N] -> { [a] : a < N and a >= 0 and N > P and a <= P and "
7473 				"N > 0 and P >= 0 }";
7474 	set = isl_set_read_from_str(ctx, str);
7475 	pa = isl_set_dim_max(set, 0);
7476 	return check_single_piece(ctx, pa);
7477 }
7478 
test_dim_max(isl_ctx * ctx)7479 int test_dim_max(isl_ctx *ctx)
7480 {
7481 	int equal;
7482 	const char *str;
7483 	isl_set *set1, *set2;
7484 	isl_set *set;
7485 	isl_map *map;
7486 	isl_pw_aff *pwaff;
7487 
7488 	if (test_dim_max_1(ctx) < 0)
7489 		return -1;
7490 	if (test_dim_max_2(ctx) < 0)
7491 		return -1;
7492 
7493 	str = "[N] -> { [i] : 0 <= i <= min(N,10) }";
7494 	set = isl_set_read_from_str(ctx, str);
7495 	pwaff = isl_set_dim_max(set, 0);
7496 	set1 = isl_set_from_pw_aff(pwaff);
7497 	str = "[N] -> { [10] : N >= 10; [N] : N <= 9 and N >= 0 }";
7498 	set2 = isl_set_read_from_str(ctx, str);
7499 	equal = isl_set_is_equal(set1, set2);
7500 	isl_set_free(set1);
7501 	isl_set_free(set2);
7502 	if (equal < 0)
7503 		return -1;
7504 	if (!equal)
7505 		isl_die(ctx, isl_error_unknown, "unexpected result", return -1);
7506 
7507 	str = "[N] -> { [i] : 0 <= i <= max(2N,N+6) }";
7508 	set = isl_set_read_from_str(ctx, str);
7509 	pwaff = isl_set_dim_max(set, 0);
7510 	set1 = isl_set_from_pw_aff(pwaff);
7511 	str = "[N] -> { [6 + N] : -6 <= N <= 5; [2N] : N >= 6 }";
7512 	set2 = isl_set_read_from_str(ctx, str);
7513 	equal = isl_set_is_equal(set1, set2);
7514 	isl_set_free(set1);
7515 	isl_set_free(set2);
7516 	if (equal < 0)
7517 		return -1;
7518 	if (!equal)
7519 		isl_die(ctx, isl_error_unknown, "unexpected result", return -1);
7520 
7521 	str = "[N] -> { [i] : 0 <= i <= 2N or 0 <= i <= N+6 }";
7522 	set = isl_set_read_from_str(ctx, str);
7523 	pwaff = isl_set_dim_max(set, 0);
7524 	set1 = isl_set_from_pw_aff(pwaff);
7525 	str = "[N] -> { [6 + N] : -6 <= N <= 5; [2N] : N >= 6 }";
7526 	set2 = isl_set_read_from_str(ctx, str);
7527 	equal = isl_set_is_equal(set1, set2);
7528 	isl_set_free(set1);
7529 	isl_set_free(set2);
7530 	if (equal < 0)
7531 		return -1;
7532 	if (!equal)
7533 		isl_die(ctx, isl_error_unknown, "unexpected result", return -1);
7534 
7535 	str = "[N,M] -> { [i,j] -> [([i/16]), i%16, ([j/16]), j%16] : "
7536 			"0 <= i < N and 0 <= j < M }";
7537 	map = isl_map_read_from_str(ctx, str);
7538 	set = isl_map_range(map);
7539 
7540 	pwaff = isl_set_dim_max(isl_set_copy(set), 0);
7541 	set1 = isl_set_from_pw_aff(pwaff);
7542 	str = "[N,M] -> { [([(N-1)/16])] : M,N > 0 }";
7543 	set2 = isl_set_read_from_str(ctx, str);
7544 	equal = isl_set_is_equal(set1, set2);
7545 	isl_set_free(set1);
7546 	isl_set_free(set2);
7547 
7548 	pwaff = isl_set_dim_max(isl_set_copy(set), 3);
7549 	set1 = isl_set_from_pw_aff(pwaff);
7550 	str = "[N,M] -> { [t] : t = min(M-1,15) and M,N > 0 }";
7551 	set2 = isl_set_read_from_str(ctx, str);
7552 	if (equal >= 0 && equal)
7553 		equal = isl_set_is_equal(set1, set2);
7554 	isl_set_free(set1);
7555 	isl_set_free(set2);
7556 
7557 	isl_set_free(set);
7558 
7559 	if (equal < 0)
7560 		return -1;
7561 	if (!equal)
7562 		isl_die(ctx, isl_error_unknown, "unexpected result", return -1);
7563 
7564 	/* Check that solutions are properly merged. */
7565 	str = "[n] -> { [a, b, c] : c >= -4a - 2b and "
7566 				"c <= -1 + n - 4a - 2b and c >= -2b and "
7567 				"4a >= -4 + n and c >= 0 }";
7568 	set = isl_set_read_from_str(ctx, str);
7569 	pwaff = isl_set_dim_min(set, 2);
7570 	set1 = isl_set_from_pw_aff(pwaff);
7571 	str = "[n] -> { [(0)] : n >= 1 }";
7572 	set2 = isl_set_read_from_str(ctx, str);
7573 	equal = isl_set_is_equal(set1, set2);
7574 	isl_set_free(set1);
7575 	isl_set_free(set2);
7576 
7577 	if (equal < 0)
7578 		return -1;
7579 	if (!equal)
7580 		isl_die(ctx, isl_error_unknown, "unexpected result", return -1);
7581 
7582 	/* Check that empty solution lie in the right space. */
7583 	str = "[n] -> { [t,a] : 1 = 0 }";
7584 	set = isl_set_read_from_str(ctx, str);
7585 	pwaff = isl_set_dim_max(set, 0);
7586 	set1 = isl_set_from_pw_aff(pwaff);
7587 	str = "[n] -> { [t] : 1 = 0 }";
7588 	set2 = isl_set_read_from_str(ctx, str);
7589 	equal = isl_set_is_equal(set1, set2);
7590 	isl_set_free(set1);
7591 	isl_set_free(set2);
7592 
7593 	if (equal < 0)
7594 		return -1;
7595 	if (!equal)
7596 		isl_die(ctx, isl_error_unknown, "unexpected result", return -1);
7597 
7598 	return 0;
7599 }
7600 
7601 /* Basic test for isl_pw_multi_aff_product.
7602  *
7603  * Check that multiple pieces are properly handled.
7604  */
test_product_pma(isl_ctx * ctx)7605 static int test_product_pma(isl_ctx *ctx)
7606 {
7607 	isl_stat equal;
7608 	const char *str;
7609 	isl_pw_multi_aff *pma1, *pma2;
7610 
7611 	str = "{ A[i] -> B[1] : i < 0; A[i] -> B[2] : i >= 0 }";
7612 	pma1 = isl_pw_multi_aff_read_from_str(ctx, str);
7613 	str = "{ C[] -> D[] }";
7614 	pma2 = isl_pw_multi_aff_read_from_str(ctx, str);
7615 	pma1 = isl_pw_multi_aff_product(pma1, pma2);
7616 	str = "{ [A[i] -> C[]] -> [B[(1)] -> D[]] : i < 0;"
7617 		"[A[i] -> C[]] -> [B[(2)] -> D[]] : i >= 0 }";
7618 	equal = pw_multi_aff_check_plain_equal(pma1, str);
7619 	isl_pw_multi_aff_free(pma1);
7620 	if (equal < 0)
7621 		return -1;
7622 
7623 	return 0;
7624 }
7625 
test_product(isl_ctx * ctx)7626 int test_product(isl_ctx *ctx)
7627 {
7628 	const char *str;
7629 	isl_set *set;
7630 	isl_union_set *uset1, *uset2;
7631 	int ok;
7632 
7633 	str = "{ A[i] }";
7634 	set = isl_set_read_from_str(ctx, str);
7635 	set = isl_set_product(set, isl_set_copy(set));
7636 	ok = isl_set_is_wrapping(set);
7637 	isl_set_free(set);
7638 	if (ok < 0)
7639 		return -1;
7640 	if (!ok)
7641 		isl_die(ctx, isl_error_unknown, "unexpected result", return -1);
7642 
7643 	str = "{ [] }";
7644 	uset1 = isl_union_set_read_from_str(ctx, str);
7645 	uset1 = isl_union_set_product(uset1, isl_union_set_copy(uset1));
7646 	str = "{ [[] -> []] }";
7647 	uset2 = isl_union_set_read_from_str(ctx, str);
7648 	ok = isl_union_set_is_equal(uset1, uset2);
7649 	isl_union_set_free(uset1);
7650 	isl_union_set_free(uset2);
7651 	if (ok < 0)
7652 		return -1;
7653 	if (!ok)
7654 		isl_die(ctx, isl_error_unknown, "unexpected result", return -1);
7655 
7656 	if (test_product_pma(ctx) < 0)
7657 		return -1;
7658 
7659 	return 0;
7660 }
7661 
7662 /* Check that two sets are not considered disjoint just because
7663  * they have a different set of (named) parameters.
7664  */
test_disjoint(isl_ctx * ctx)7665 static int test_disjoint(isl_ctx *ctx)
7666 {
7667 	const char *str;
7668 	isl_set *set, *set2;
7669 	int disjoint;
7670 
7671 	str = "[n] -> { [[]->[]] }";
7672 	set = isl_set_read_from_str(ctx, str);
7673 	str = "{ [[]->[]] }";
7674 	set2 = isl_set_read_from_str(ctx, str);
7675 	disjoint = isl_set_is_disjoint(set, set2);
7676 	isl_set_free(set);
7677 	isl_set_free(set2);
7678 	if (disjoint < 0)
7679 		return -1;
7680 	if (disjoint)
7681 		isl_die(ctx, isl_error_unknown, "unexpected result", return -1);
7682 
7683 	return 0;
7684 }
7685 
7686 /* Inputs for isl_pw_multi_aff_is_equal tests.
7687  * "f1" and "f2" are the two function that need to be compared.
7688  * "equal" is the expected result.
7689  */
7690 struct {
7691 	int equal;
7692 	const char *f1;
7693 	const char *f2;
7694 } pma_equal_tests[] = {
7695 	{ 1, "[N] -> { [floor(N/2)] : 0 <= N <= 1 }",
7696 	     "[N] -> { [0] : 0 <= N <= 1 }" },
7697 	{ 1, "[N] -> { [floor(N/2)] : 0 <= N <= 2 }",
7698 	     "[N] -> { [0] : 0 <= N <= 1; [1] : N = 2 }" },
7699 	{ 0, "[N] -> { [floor(N/2)] : 0 <= N <= 2 }",
7700 	     "[N] -> { [0] : 0 <= N <= 1 }" },
7701 	{ 0, "{ [NaN] }", "{ [NaN] }" },
7702 };
7703 
test_equal(isl_ctx * ctx)7704 int test_equal(isl_ctx *ctx)
7705 {
7706 	int i;
7707 	const char *str;
7708 	isl_set *set, *set2;
7709 	int equal;
7710 
7711 	str = "{ S_6[i] }";
7712 	set = isl_set_read_from_str(ctx, str);
7713 	str = "{ S_7[i] }";
7714 	set2 = isl_set_read_from_str(ctx, str);
7715 	equal = isl_set_is_equal(set, set2);
7716 	isl_set_free(set);
7717 	isl_set_free(set2);
7718 	if (equal < 0)
7719 		return -1;
7720 	if (equal)
7721 		isl_die(ctx, isl_error_unknown, "unexpected result", return -1);
7722 
7723 	for (i = 0; i < ARRAY_SIZE(pma_equal_tests); ++i) {
7724 		int expected = pma_equal_tests[i].equal;
7725 		isl_pw_multi_aff *f1, *f2;
7726 
7727 		f1 = isl_pw_multi_aff_read_from_str(ctx, pma_equal_tests[i].f1);
7728 		f2 = isl_pw_multi_aff_read_from_str(ctx, pma_equal_tests[i].f2);
7729 		equal = isl_pw_multi_aff_is_equal(f1, f2);
7730 		isl_pw_multi_aff_free(f1);
7731 		isl_pw_multi_aff_free(f2);
7732 		if (equal < 0)
7733 			return -1;
7734 		if (equal != expected)
7735 			isl_die(ctx, isl_error_unknown,
7736 				"unexpected equality result", return -1);
7737 	}
7738 
7739 	return 0;
7740 }
7741 
test_plain_fixed(isl_ctx * ctx,__isl_take isl_map * map,enum isl_dim_type type,unsigned pos,int fixed)7742 static int test_plain_fixed(isl_ctx *ctx, __isl_take isl_map *map,
7743 	enum isl_dim_type type, unsigned pos, int fixed)
7744 {
7745 	isl_bool test;
7746 
7747 	test = isl_map_plain_is_fixed(map, type, pos, NULL);
7748 	isl_map_free(map);
7749 	if (test < 0)
7750 		return -1;
7751 	if (test == fixed)
7752 		return 0;
7753 	if (fixed)
7754 		isl_die(ctx, isl_error_unknown,
7755 			"map not detected as fixed", return -1);
7756 	else
7757 		isl_die(ctx, isl_error_unknown,
7758 			"map detected as fixed", return -1);
7759 }
7760 
test_fixed(isl_ctx * ctx)7761 int test_fixed(isl_ctx *ctx)
7762 {
7763 	const char *str;
7764 	isl_map *map;
7765 
7766 	str = "{ [i] -> [i] }";
7767 	map = isl_map_read_from_str(ctx, str);
7768 	if (test_plain_fixed(ctx, map, isl_dim_out, 0, 0))
7769 		return -1;
7770 	str = "{ [i] -> [1] }";
7771 	map = isl_map_read_from_str(ctx, str);
7772 	if (test_plain_fixed(ctx, map, isl_dim_out, 0, 1))
7773 		return -1;
7774 	str = "{ S_1[p1] -> [o0] : o0 = -2 and p1 >= 1 and p1 <= 7 }";
7775 	map = isl_map_read_from_str(ctx, str);
7776 	if (test_plain_fixed(ctx, map, isl_dim_out, 0, 1))
7777 		return -1;
7778 	map = isl_map_read_from_str(ctx, str);
7779 	map = isl_map_neg(map);
7780 	if (test_plain_fixed(ctx, map, isl_dim_out, 0, 1))
7781 		return -1;
7782 
7783 	return 0;
7784 }
7785 
7786 struct isl_vertices_test_data {
7787 	const char *set;
7788 	int n;
7789 	const char *vertex[6];
7790 } vertices_tests[] = {
7791 	{ "{ A[t, i] : t = 12 and i >= 4 and i <= 12 }",
7792 	  2, { "{ A[12, 4] }", "{ A[12, 12] }" } },
7793 	{ "{ A[t, i] : t = 14 and i = 1 }",
7794 	  1, { "{ A[14, 1] }" } },
7795 	{ "[n, m] -> { [a, b, c] : b <= a and a <= n and b > 0 and c >= b and "
7796 				"c <= m and m <= n and m > 0 }",
7797 	  6, {
7798 		"[n, m] -> { [n, m, m] : 0 < m <= n }",
7799 		"[n, m] -> { [n, 1, m] : 0 < m <= n }",
7800 		"[n, m] -> { [n, 1, 1] : 0 < m <= n }",
7801 		"[n, m] -> { [m, m, m] : 0 < m <= n }",
7802 		"[n, m] -> { [1, 1, m] : 0 < m <= n }",
7803 		"[n, m] -> { [1, 1, 1] : 0 < m <= n }"
7804 	    } },
7805 };
7806 
7807 /* Check that "vertex" corresponds to one of the vertices in data->vertex.
7808  */
find_vertex(__isl_take isl_vertex * vertex,void * user)7809 static isl_stat find_vertex(__isl_take isl_vertex *vertex, void *user)
7810 {
7811 	struct isl_vertices_test_data *data = user;
7812 	isl_ctx *ctx;
7813 	isl_multi_aff *ma;
7814 	isl_basic_set *bset;
7815 	isl_pw_multi_aff *pma;
7816 	int i;
7817 	isl_bool equal;
7818 
7819 	ctx = isl_vertex_get_ctx(vertex);
7820 	bset = isl_vertex_get_domain(vertex);
7821 	ma = isl_vertex_get_expr(vertex);
7822 	pma = isl_pw_multi_aff_alloc(isl_set_from_basic_set(bset), ma);
7823 
7824 	for (i = 0; i < data->n; ++i) {
7825 		isl_pw_multi_aff *pma_i;
7826 
7827 		pma_i = isl_pw_multi_aff_read_from_str(ctx, data->vertex[i]);
7828 		equal = isl_pw_multi_aff_plain_is_equal(pma, pma_i);
7829 		isl_pw_multi_aff_free(pma_i);
7830 
7831 		if (equal < 0 || equal)
7832 			break;
7833 	}
7834 
7835 	isl_pw_multi_aff_free(pma);
7836 	isl_vertex_free(vertex);
7837 
7838 	if (equal < 0)
7839 		return isl_stat_error;
7840 
7841 	return equal ? isl_stat_ok : isl_stat_error;
7842 }
7843 
test_vertices(isl_ctx * ctx)7844 int test_vertices(isl_ctx *ctx)
7845 {
7846 	int i;
7847 
7848 	for (i = 0; i < ARRAY_SIZE(vertices_tests); ++i) {
7849 		isl_basic_set *bset;
7850 		isl_vertices *vertices;
7851 		int ok = 1;
7852 		isl_size n;
7853 
7854 		bset = isl_basic_set_read_from_str(ctx, vertices_tests[i].set);
7855 		vertices = isl_basic_set_compute_vertices(bset);
7856 		n = isl_vertices_get_n_vertices(vertices);
7857 		if (vertices_tests[i].n != n)
7858 			ok = 0;
7859 		if (isl_vertices_foreach_vertex(vertices, &find_vertex,
7860 						&vertices_tests[i]) < 0)
7861 			ok = 0;
7862 		isl_vertices_free(vertices);
7863 		isl_basic_set_free(bset);
7864 
7865 		if (n < 0)
7866 			return -1;
7867 		if (!ok)
7868 			isl_die(ctx, isl_error_unknown, "unexpected vertices",
7869 				return -1);
7870 	}
7871 
7872 	return 0;
7873 }
7874 
7875 /* Inputs for basic tests of unary operations on isl_union_map.
7876  * "fn" is the function that is being tested.
7877  * "arg" is a string description of the input.
7878  * "res" is a string description of the expected result.
7879  */
7880 static struct {
7881 	__isl_give isl_union_map *(*fn)(__isl_take isl_union_map *umap);
7882 	const char *arg;
7883 	const char *res;
7884 } umap_un_tests[] = {
7885 	{ &isl_union_map_range_reverse,
7886 	  "{ A[] -> [B[] -> C[]]; A[] -> B[]; A[0] -> N[B[1] -> B[2]] }",
7887 	  "{ A[] -> [C[] -> B[]]; A[0] -> N[B[2] -> B[1]] }" },
7888 	{ &isl_union_map_range_reverse,
7889 	  "{ A[] -> N[B[] -> C[]] }",
7890 	  "{ A[] -> [C[] -> B[]] }" },
7891 	{ &isl_union_map_range_reverse,
7892 	  "{ A[] -> N[B[x] -> B[y]] }",
7893 	  "{ A[] -> N[B[*] -> B[*]] }" },
7894 };
7895 
7896 /* Perform basic tests of unary operations on isl_union_map.
7897  */
test_un_union_map(isl_ctx * ctx)7898 static isl_stat test_un_union_map(isl_ctx *ctx)
7899 {
7900 	int i;
7901 
7902 	for (i = 0; i < ARRAY_SIZE(umap_un_tests); ++i) {
7903 		const char *str;
7904 		isl_union_map *umap, *res;
7905 		isl_bool equal;
7906 
7907 		str = umap_un_tests[i].arg;
7908 		umap = isl_union_map_read_from_str(ctx, str);
7909 		str = umap_un_tests[i].res;
7910 		res = isl_union_map_read_from_str(ctx, str);
7911 		umap = umap_un_tests[i].fn(umap);
7912 		equal = isl_union_map_is_equal(umap, res);
7913 		isl_union_map_free(umap);
7914 		isl_union_map_free(res);
7915 		if (equal < 0)
7916 			return isl_stat_error;
7917 		if (!equal)
7918 			isl_die(ctx, isl_error_unknown,
7919 				"unexpected result", return isl_stat_error);
7920 	}
7921 
7922 	return isl_stat_ok;
7923 }
7924 
7925 /* Inputs for basic tests of binary operations on isl_union_map.
7926  * "fn" is the function that is being tested.
7927  * "arg1" and "arg2" are string descriptions of the inputs.
7928  * "res" is a string description of the expected result.
7929  */
7930 static struct {
7931 	__isl_give isl_union_map *(*fn)(__isl_take isl_union_map *umap1,
7932 				__isl_take isl_union_map *umap2);
7933 	const char *arg1;
7934 	const char *arg2;
7935 	const char *res;
7936 } umap_bin_tests[] = {
7937 	{ &isl_union_map_intersect,
7938 	  "[n] -> { A[i] -> [] : 0 <= i <= n; B[] -> [] }",
7939 	  "[m] -> { A[i] -> [] : 0 <= i <= m; C[] -> [] }",
7940 	  "[m, n] -> { A[i] -> [] : 0 <= i <= n and i <= m }" },
7941 	{ &isl_union_map_intersect_domain_factor_range,
7942 	  "{ [A[i] -> B[i + 1]] -> C[i + 2] }",
7943 	  "[N] -> { B[i] -> C[N] }",
7944 	  "[N] -> { [A[N - 2] -> B[N - 1]] -> C[N] }" },
7945 	{ &isl_union_map_intersect_domain_factor_range,
7946 	  "{ T[A[i] -> B[i + 1]] -> C[i + 2] }",
7947 	  "[N] -> { B[i] -> C[N] }",
7948 	  "[N] -> { T[A[N - 2] -> B[N - 1]] -> C[N] }" },
7949 	{ &isl_union_map_intersect_domain_factor_range,
7950 	  "{ [A[i] -> B[i + 1]] -> C[i + 2] }",
7951 	  "[N] -> { A[i] -> C[N] }",
7952 	  "{ }" },
7953 	{ &isl_union_map_intersect_range_factor_domain,
7954 	  "{ A[i] -> [B[i + 1] -> C[i + 2]] }",
7955 	  "[N] -> { A[i] -> B[N] }",
7956 	  "[N] -> { A[N - 1] -> [B[N] -> C[N + 1]] }" },
7957 	{ &isl_union_map_intersect_range_factor_domain,
7958 	  "{ A[i] -> T[B[i + 1] -> C[i + 2]] }",
7959 	  "[N] -> { A[i] -> B[N] }",
7960 	  "[N] -> { A[N - 1] -> T[B[N] -> C[N + 1]] }" },
7961 	{ &isl_union_map_intersect_range_factor_domain,
7962 	  "{ A[i] -> [B[i + 1] -> C[i + 2]] }",
7963 	  "[N] -> { A[i] -> C[N] }",
7964 	  "{ }" },
7965 	{ &isl_union_map_intersect_range_factor_range,
7966 	  "{ A[i] -> [B[i + 1] -> C[i + 2]] }",
7967 	  "[N] -> { A[i] -> C[N] }",
7968 	  "[N] -> { A[N - 2] -> [B[N - 1] -> C[N]] }" },
7969 	{ &isl_union_map_intersect_range_factor_range,
7970 	  "{ A[i] -> T[B[i + 1] -> C[i + 2]] }",
7971 	  "[N] -> { A[i] -> C[N] }",
7972 	  "[N] -> { A[N - 2] -> T[B[N - 1] -> C[N]] }" },
7973 	{ &isl_union_map_intersect_range_factor_range,
7974 	  "{ A[i] -> [B[i + 1] -> C[i + 2]] }",
7975 	  "[N] -> { A[i] -> B[N] }",
7976 	  "{ }" },
7977 };
7978 
7979 /* Perform basic tests of binary operations on isl_union_map.
7980  */
test_bin_union_map(isl_ctx * ctx)7981 static isl_stat test_bin_union_map(isl_ctx *ctx)
7982 {
7983 	int i;
7984 
7985 	for (i = 0; i < ARRAY_SIZE(umap_bin_tests); ++i) {
7986 		const char *str;
7987 		isl_union_map *umap1, *umap2, *res;
7988 		isl_bool equal;
7989 
7990 		str = umap_bin_tests[i].arg1;
7991 		umap1 = isl_union_map_read_from_str(ctx, str);
7992 		str = umap_bin_tests[i].arg2;
7993 		umap2 = isl_union_map_read_from_str(ctx, str);
7994 		str = umap_bin_tests[i].res;
7995 		res = isl_union_map_read_from_str(ctx, str);
7996 		umap1 = umap_bin_tests[i].fn(umap1, umap2);
7997 		equal = isl_union_map_is_equal(umap1, res);
7998 		isl_union_map_free(umap1);
7999 		isl_union_map_free(res);
8000 		if (equal < 0)
8001 			return isl_stat_error;
8002 		if (!equal)
8003 			isl_die(ctx, isl_error_unknown,
8004 				"unexpected result", return isl_stat_error);
8005 	}
8006 
8007 	return isl_stat_ok;
8008 }
8009 
8010 /* Check that isl_union_set_contains finds space independently
8011  * of the parameters.
8012  */
test_union_set_contains(isl_ctx * ctx)8013 static isl_stat test_union_set_contains(isl_ctx *ctx)
8014 {
8015 	const char *str;
8016 	isl_bool ok;
8017 	isl_space *space;
8018 	isl_id *id;
8019 	isl_union_set *uset;
8020 
8021 	str = "[N] -> { A[0:N]; B[*,*] }";
8022 	uset = isl_union_set_read_from_str(ctx, str);
8023 	space = isl_space_unit(ctx);
8024 	id = isl_id_alloc(ctx, "A", NULL);
8025 	space = isl_space_add_named_tuple_id_ui(space, id, 1);
8026 	ok = isl_union_set_contains(uset, space);
8027 	isl_space_free(space);
8028 	isl_union_set_free(uset);
8029 
8030 	if (ok < 0)
8031 		return isl_stat_error;
8032 	if (!ok)
8033 		isl_die(ctx, isl_error_unknown,
8034 			"unexpected result", return isl_stat_error);
8035 
8036 	return isl_stat_ok;
8037 }
8038 
8039 /* Perform basic tests of operations on isl_union_map or isl_union_set.
8040  */
test_union_map(isl_ctx * ctx)8041 static int test_union_map(isl_ctx *ctx)
8042 {
8043 	if (test_un_union_map(ctx) < 0)
8044 		return -1;
8045 	if (test_bin_union_map(ctx) < 0)
8046 		return -1;
8047 	if (test_union_set_contains(ctx) < 0)
8048 		return -1;
8049 	return 0;
8050 }
8051 
test_union_pw(isl_ctx * ctx)8052 int test_union_pw(isl_ctx *ctx)
8053 {
8054 	int equal;
8055 	const char *str;
8056 	isl_union_set *uset;
8057 	isl_union_pw_qpolynomial *upwqp1, *upwqp2;
8058 
8059 	str = "{ [x] -> x^2 }";
8060 	upwqp1 = isl_union_pw_qpolynomial_read_from_str(ctx, str);
8061 	upwqp2 = isl_union_pw_qpolynomial_copy(upwqp1);
8062 	uset = isl_union_pw_qpolynomial_domain(upwqp1);
8063 	upwqp1 = isl_union_pw_qpolynomial_copy(upwqp2);
8064 	upwqp1 = isl_union_pw_qpolynomial_intersect_domain(upwqp1, uset);
8065 	equal = isl_union_pw_qpolynomial_plain_is_equal(upwqp1, upwqp2);
8066 	isl_union_pw_qpolynomial_free(upwqp1);
8067 	isl_union_pw_qpolynomial_free(upwqp2);
8068 	if (equal < 0)
8069 		return -1;
8070 	if (!equal)
8071 		isl_die(ctx, isl_error_unknown, "unexpected result", return -1);
8072 
8073 	return 0;
8074 }
8075 
8076 /* Inputs for basic tests of functions that select
8077  * subparts of the domain of an isl_multi_union_pw_aff.
8078  * "fn" is the function that is tested.
8079  * "arg" is a string description of the input.
8080  * "res" is a string description of the expected result.
8081  */
8082 struct {
8083 	__isl_give isl_union_set *(*fn)(
8084 		__isl_take isl_multi_union_pw_aff *mupa);
8085 	const char *arg;
8086 	const char *res;
8087 } un_locus_tests[] = {
8088 	{ &isl_multi_union_pw_aff_zero_union_set,
8089 	  "F[{ A[i,j] -> [i]; B[i,j] -> [i] }]",
8090 	  "{ A[0,j]; B[0,j] }" },
8091 	{ &isl_multi_union_pw_aff_zero_union_set,
8092 	  "F[{ A[i,j] -> [i-j]; B[i,j] -> [i-j] : i >= 0 }]",
8093 	  "{ A[i,i]; B[i,i] : i >= 0 }" },
8094 	{ &isl_multi_union_pw_aff_zero_union_set,
8095 	  "(F[] : { A[i,j]; B[i,i] : i >= 0 })",
8096 	  "{ A[i,j]; B[i,i] : i >= 0 }" },
8097 };
8098 
8099 /* Perform some basic tests of functions that select
8100  * subparts of the domain of an isl_multi_union_pw_aff.
8101  */
test_un_locus(isl_ctx * ctx)8102 static int test_un_locus(isl_ctx *ctx)
8103 {
8104 	int i;
8105 	isl_bool ok;
8106 	isl_union_set *uset, *res;
8107 	isl_multi_union_pw_aff *mupa;
8108 
8109 	for (i = 0; i < ARRAY_SIZE(un_locus_tests); ++i) {
8110 		mupa = isl_multi_union_pw_aff_read_from_str(ctx,
8111 						    un_locus_tests[i].arg);
8112 		res = isl_union_set_read_from_str(ctx, un_locus_tests[i].res);
8113 		uset = un_locus_tests[i].fn(mupa);
8114 		ok = isl_union_set_is_equal(uset, res);
8115 		isl_union_set_free(uset);
8116 		isl_union_set_free(res);
8117 		if (ok < 0)
8118 			return -1;
8119 		if (!ok)
8120 			isl_die(ctx, isl_error_unknown,
8121 				"unexpected result", return -1);
8122 	}
8123 
8124 	return 0;
8125 }
8126 
8127 /* Inputs for basic tests of functions that select
8128  * subparts of an isl_union_map based on a relation
8129  * specified by an isl_multi_union_pw_aff.
8130  * "fn" is the function that is tested.
8131  * "arg1" and "arg2" are string descriptions of the inputs.
8132  * "res" is a string description of the expected result.
8133  */
8134 struct {
8135 	__isl_give isl_union_map *(*fn)(
8136 		__isl_take isl_union_map *umap,
8137 		__isl_take isl_multi_union_pw_aff *mupa);
8138 	const char *arg1;
8139 	const char *arg2;
8140 	const char *res;
8141 } bin_locus_tests[] = {
8142 	{ &isl_union_map_eq_at_multi_union_pw_aff,
8143 	  "{ A[i,j] -> B[i',j'] }",
8144 	  "F[{ A[i,j] -> [i]; B[i,j] -> [i] }]",
8145 	  "{ A[i,j] -> B[i,j'] }" },
8146 	{ &isl_union_map_eq_at_multi_union_pw_aff,
8147 	  "{ A[i,j] -> B[i',j'] }",
8148 	  "F[{ A[i,j] -> [i]; B[i,j] -> [i] }, "
8149 	    "{ A[i,j] -> [j]; B[i,j] -> [j] }]",
8150 	  "{ A[i,j] -> B[i,j] }" },
8151 	{ &isl_union_map_eq_at_multi_union_pw_aff,
8152 	  "{ A[i,j] -> B[i',j']; A[i,j] -> C[i',j'] }",
8153 	  "F[{ A[i,j] -> [i]; B[i,j] -> [i] }]",
8154 	  "{ A[i,j] -> B[i,j'] }" },
8155 	{ &isl_union_map_eq_at_multi_union_pw_aff,
8156 	  "{ A[i,j] -> B[i',j']; A[i,j] -> C[i',j'] }",
8157 	  "F[{ A[i,j] -> [i]; B[i,j] -> [i]; C[i,j] -> [0] }]",
8158 	  "{ A[i,j] -> B[i,j']; A[0,j] -> C[i',j'] }" },
8159 	{ &isl_union_map_eq_at_multi_union_pw_aff,
8160 	  "{ A[i,j] -> B[i',j'] }",
8161 	  "F[{ A[i,j] -> [i] : i > j; B[i,j] -> [i] }]",
8162 	  "{ A[i,j] -> B[i,j'] : i > j }" },
8163 	{ &isl_union_map_lex_lt_at_multi_union_pw_aff,
8164 	  "{ A[i,j] -> B[i',j'] }",
8165 	  "F[{ A[i,j] -> [i]; B[i,j] -> [i] }, "
8166 	    "{ A[i,j] -> [j]; B[i,j] -> [j] }]",
8167 	  "{ A[i,j] -> B[i',j'] : i,j << i',j' }" },
8168 	{ &isl_union_map_lex_gt_at_multi_union_pw_aff,
8169 	  "{ A[i,j] -> B[i',j'] }",
8170 	  "F[{ A[i,j] -> [i]; B[i,j] -> [i] }, "
8171 	    "{ A[i,j] -> [j]; B[i,j] -> [j] }]",
8172 	  "{ A[i,j] -> B[i',j'] : i,j >> i',j' }" },
8173 	{ &isl_union_map_eq_at_multi_union_pw_aff,
8174 	  "{ A[i,j] -> B[i',j']; A[i,j] -> C[i',j'] }",
8175 	  "(F[] : { A[i,j]; B[i,j] })",
8176 	  "{ A[i,j] -> B[i',j'] }" },
8177 	{ &isl_union_map_eq_at_multi_union_pw_aff,
8178 	  "{ A[i,j] -> B[i',j'] }",
8179 	  "(F[] : { A[i,j] : i > j; B[i,j] : i < j })",
8180 	  "{ A[i,j] -> B[i',j'] : i > j and i' < j' }" },
8181 	{ &isl_union_map_eq_at_multi_union_pw_aff,
8182 	  "[N] -> { A[i,j] -> B[i',j'] : i,i' <= N }",
8183 	  "(F[] : { A[i,j] : i > j; B[i,j] : i < j })",
8184 	  "[N] -> { A[i,j] -> B[i',j'] : i > j and i' < j' and i,i' <= N }" },
8185 	{ &isl_union_map_eq_at_multi_union_pw_aff,
8186 	  "{ A[i,j] -> B[i',j'] }",
8187 	  "[N] -> (F[] : { A[i,j] : i < N; B[i,j] : i < N })",
8188 	  "[N] -> { A[i,j] -> B[i',j'] : i,i' < N }" },
8189 	{ &isl_union_map_eq_at_multi_union_pw_aff,
8190 	  "{ A[i,j] -> B[i',j'] }",
8191 	  "[N] -> (F[] : { : N >= 0 })",
8192 	  "[N] -> { A[i,j] -> B[i',j'] : N >= 0 }" },
8193 };
8194 
8195 /* Perform some basic tests of functions that select
8196  * subparts of an isl_union_map based on a relation
8197  * specified by an isl_multi_union_pw_aff.
8198  */
test_bin_locus(isl_ctx * ctx)8199 static int test_bin_locus(isl_ctx *ctx)
8200 {
8201 	int i;
8202 	isl_bool ok;
8203 	isl_union_map *umap, *res;
8204 	isl_multi_union_pw_aff *mupa;
8205 
8206 	for (i = 0; i < ARRAY_SIZE(bin_locus_tests); ++i) {
8207 		umap = isl_union_map_read_from_str(ctx,
8208 						    bin_locus_tests[i].arg1);
8209 		mupa = isl_multi_union_pw_aff_read_from_str(ctx,
8210 						    bin_locus_tests[i].arg2);
8211 		res = isl_union_map_read_from_str(ctx, bin_locus_tests[i].res);
8212 		umap = bin_locus_tests[i].fn(umap, mupa);
8213 		ok = isl_union_map_is_equal(umap, res);
8214 		isl_union_map_free(umap);
8215 		isl_union_map_free(res);
8216 		if (ok < 0)
8217 			return -1;
8218 		if (!ok)
8219 			isl_die(ctx, isl_error_unknown,
8220 				"unexpected result", return -1);
8221 	}
8222 
8223 	return 0;
8224 }
8225 
8226 /* Inputs for basic tests of functions that determine
8227  * the part of the domain where two isl_multi_aff objects
8228  * related to each other in a specific way.
8229  * "fn" is the function that is being tested.
8230  * "arg1" and "arg2" are string descriptions of the inputs.
8231  * "res" is a string description of the expected result.
8232  */
8233 static struct {
8234 	__isl_give isl_set *(*fn)(__isl_take isl_multi_aff *ma1,
8235 		__isl_take isl_multi_aff *ma2);
8236 	const char *arg1;
8237 	const char *arg2;
8238 	const char *res;
8239 } bin_locus_ma_tests[] = {
8240 	{ &isl_multi_aff_lex_le_set, "{ [] }", "{ [] }", "{ : }" },
8241 	{ &isl_multi_aff_lex_lt_set, "{ [] }", "{ [] }", "{ : false }" },
8242 	{ &isl_multi_aff_lex_le_set,
8243 	  "{ A[i] -> [i] }", "{ A[i] -> [0] }",
8244 	  "{ A[i] : i <= 0 }" },
8245 	{ &isl_multi_aff_lex_lt_set,
8246 	  "{ A[i] -> [i] }", "{ A[i] -> [0] }",
8247 	  "{ A[i] : i < 0 }" },
8248 	{ &isl_multi_aff_lex_le_set,
8249 	  "{ A[i] -> [i, i] }", "{ A[i] -> [0, 0] }",
8250 	  "{ A[i] : i <= 0 }" },
8251 	{ &isl_multi_aff_lex_le_set,
8252 	  "{ A[i] -> [i, 0] }", "{ A[i] -> [0, 0] }",
8253 	  "{ A[i] : i <= 0 }" },
8254 	{ &isl_multi_aff_lex_le_set,
8255 	  "{ A[i] -> [i, 1] }", "{ A[i] -> [0, 0] }",
8256 	  "{ A[i] : i < 0 }" },
8257 };
8258 
8259 /* Perform some basic tests of functions that determine
8260  * the part of the domain where two isl_multi_aff objects
8261  * related to each other in a specific way.
8262  */
test_bin_locus_ma(isl_ctx * ctx)8263 static isl_stat test_bin_locus_ma(isl_ctx *ctx)
8264 {
8265 	int i;
8266 
8267 	for (i = 0; i < ARRAY_SIZE(bin_locus_ma_tests); ++i) {
8268 		const char *str;
8269 		isl_bool ok;
8270 		isl_multi_aff *ma1, *ma2;
8271 		isl_set *set, *res;
8272 
8273 		str = bin_locus_ma_tests[i].arg1;
8274 		ma1 = isl_multi_aff_read_from_str(ctx, str);
8275 		str = bin_locus_ma_tests[i].arg2;
8276 		ma2 = isl_multi_aff_read_from_str(ctx, str);
8277 		res = isl_set_read_from_str(ctx, bin_locus_ma_tests[i].res);
8278 		set = bin_locus_ma_tests[i].fn(ma1, ma2);
8279 		ok = isl_set_is_equal(set, res);
8280 		isl_set_free(set);
8281 		isl_set_free(res);
8282 		if (ok < 0)
8283 			return isl_stat_error;
8284 		if (!ok)
8285 			isl_die(ctx, isl_error_unknown,
8286 				"unexpected result", return isl_stat_error);
8287 	}
8288 
8289 	return isl_stat_ok;
8290 }
8291 
8292 /* Perform basic locus tests.
8293  */
test_locus(isl_ctx * ctx)8294 static int test_locus(isl_ctx *ctx)
8295 {
8296 	if (test_un_locus(ctx) < 0)
8297 		return -1;
8298 	if (test_bin_locus(ctx) < 0)
8299 		return -1;
8300 	if (test_bin_locus_ma(ctx) < 0)
8301 		return -1;
8302 	return 0;
8303 }
8304 
8305 /* Test that isl_union_pw_qpolynomial_eval picks up the function
8306  * defined over the correct domain space.
8307  */
test_eval_1(isl_ctx * ctx)8308 static int test_eval_1(isl_ctx *ctx)
8309 {
8310 	const char *str;
8311 	isl_point *pnt;
8312 	isl_set *set;
8313 	isl_union_pw_qpolynomial *upwqp;
8314 	isl_val *v;
8315 	int cmp;
8316 
8317 	str = "{ A[x] -> x^2; B[x] -> -x^2 }";
8318 	upwqp = isl_union_pw_qpolynomial_read_from_str(ctx, str);
8319 	str = "{ A[6] }";
8320 	set = isl_set_read_from_str(ctx, str);
8321 	pnt = isl_set_sample_point(set);
8322 	v = isl_union_pw_qpolynomial_eval(upwqp, pnt);
8323 	cmp = isl_val_cmp_si(v, 36);
8324 	isl_val_free(v);
8325 
8326 	if (!v)
8327 		return -1;
8328 	if (cmp != 0)
8329 		isl_die(ctx, isl_error_unknown, "unexpected value", return -1);
8330 
8331 	return 0;
8332 }
8333 
8334 /* Check that isl_qpolynomial_eval handles getting called on a void point.
8335  */
test_eval_2(isl_ctx * ctx)8336 static int test_eval_2(isl_ctx *ctx)
8337 {
8338 	const char *str;
8339 	isl_point *pnt;
8340 	isl_set *set;
8341 	isl_qpolynomial *qp;
8342 	isl_val *v;
8343 	isl_bool ok;
8344 
8345 	str = "{ A[x] -> [x] }";
8346 	qp = isl_qpolynomial_from_aff(isl_aff_read_from_str(ctx, str));
8347 	str = "{ A[x] : false }";
8348 	set = isl_set_read_from_str(ctx, str);
8349 	pnt = isl_set_sample_point(set);
8350 	v = isl_qpolynomial_eval(qp, pnt);
8351 	ok = isl_val_is_nan(v);
8352 	isl_val_free(v);
8353 
8354 	if (ok < 0)
8355 		return -1;
8356 	if (!ok)
8357 		isl_die(ctx, isl_error_unknown, "expecting NaN", return -1);
8358 
8359 	return 0;
8360 }
8361 
8362 /* Check that a polynomial (without local variables) can be evaluated
8363  * in a rational point.
8364  */
test_eval_3(isl_ctx * ctx)8365 static isl_stat test_eval_3(isl_ctx *ctx)
8366 {
8367 	isl_pw_qpolynomial *pwqp;
8368 	isl_point *pnt;
8369 	isl_val *v;
8370 	isl_stat r;
8371 
8372 	pwqp = isl_pw_qpolynomial_read_from_str(ctx, "{ [x] -> x^2 }");
8373 	pnt = isl_point_zero(isl_pw_qpolynomial_get_domain_space(pwqp));
8374 	v = isl_val_read_from_str(ctx, "1/2");
8375 	pnt = isl_point_set_coordinate_val(pnt, isl_dim_set, 0, v);
8376 	v = isl_pw_qpolynomial_eval(pwqp, pnt);
8377 	r = val_check_equal(v, "1/4");
8378 	isl_val_free(v);
8379 
8380 	return r;
8381 }
8382 
8383 /* Inputs for isl_pw_aff_eval test.
8384  * "f" is the affine function.
8385  * "p" is the point where the function should be evaluated.
8386  * "res" is the expected result.
8387  */
8388 struct {
8389 	const char *f;
8390 	const char *p;
8391 	const char *res;
8392 } aff_eval_tests[] = {
8393 	{ "{ [i] -> [2 * i] }", "{ [4] }", "8" },
8394 	{ "{ [i] -> [2 * i] }", "{ [x] : false }", "NaN" },
8395 	{ "{ [i] -> [i + floor(i/2) + floor(i/3)] }", "{ [0] }", "0" },
8396 	{ "{ [i] -> [i + floor(i/2) + floor(i/3)] }", "{ [1] }", "1" },
8397 	{ "{ [i] -> [i + floor(i/2) + floor(i/3)] }", "{ [2] }", "3" },
8398 	{ "{ [i] -> [i + floor(i/2) + floor(i/3)] }", "{ [3] }", "5" },
8399 	{ "{ [i] -> [i + floor(i/2) + floor(i/3)] }", "{ [4] }", "7" },
8400 	{ "{ [i] -> [floor((3 * floor(i/2))/5)] }", "{ [0] }", "0" },
8401 	{ "{ [i] -> [floor((3 * floor(i/2))/5)] }", "{ [1] }", "0" },
8402 	{ "{ [i] -> [floor((3 * floor(i/2))/5)] }", "{ [2] }", "0" },
8403 	{ "{ [i] -> [floor((3 * floor(i/2))/5)] }", "{ [3] }", "0" },
8404 	{ "{ [i] -> [floor((3 * floor(i/2))/5)] }", "{ [4] }", "1" },
8405 	{ "{ [i] -> [floor((3 * floor(i/2))/5)] }", "{ [6] }", "1" },
8406 	{ "{ [i] -> [floor((3 * floor(i/2))/5)] }", "{ [8] }", "2" },
8407 	{ "{ [i] -> [i] : i > 0; [i] -> [-i] : i < 0 }", "{ [4] }", "4" },
8408 	{ "{ [i] -> [i] : i > 0; [i] -> [-i] : i < 0 }", "{ [-2] }", "2" },
8409 	{ "{ [i] -> [i] : i > 0; [i] -> [-i] : i < 0 }", "{ [0] }", "NaN" },
8410 	{ "[N] -> { [2 * N] }", "[N] -> { : N = 4 }", "8" },
8411 	{ "{ [i, j] -> [(i + j)/2] }", "{ [1, 1] }", "1" },
8412 	{ "{ [i, j] -> [(i + j)/2] }", "{ [1, 2] }", "3/2" },
8413 	{ "{ [i] -> [i] : i mod 2 = 0 }", "{ [4] }", "4" },
8414 	{ "{ [i] -> [i] : i mod 2 = 0 }", "{ [3] }", "NaN" },
8415 	{ "{ [i] -> [i] : i mod 2 = 0 }", "{ [x] : false }", "NaN" },
8416 };
8417 
8418 /* Perform basic isl_pw_aff_eval tests.
8419  */
test_eval_aff(isl_ctx * ctx)8420 static int test_eval_aff(isl_ctx *ctx)
8421 {
8422 	int i;
8423 
8424 	for (i = 0; i < ARRAY_SIZE(aff_eval_tests); ++i) {
8425 		isl_stat r;
8426 		isl_pw_aff *pa;
8427 		isl_set *set;
8428 		isl_point *pnt;
8429 		isl_val *v;
8430 
8431 		pa = isl_pw_aff_read_from_str(ctx, aff_eval_tests[i].f);
8432 		set = isl_set_read_from_str(ctx, aff_eval_tests[i].p);
8433 		pnt = isl_set_sample_point(set);
8434 		v = isl_pw_aff_eval(pa, pnt);
8435 		r = val_check_equal(v, aff_eval_tests[i].res);
8436 		isl_val_free(v);
8437 		if (r < 0)
8438 			return -1;
8439 	}
8440 	return 0;
8441 }
8442 
8443 /* Perform basic evaluation tests.
8444  */
test_eval(isl_ctx * ctx)8445 static int test_eval(isl_ctx *ctx)
8446 {
8447 	if (test_eval_1(ctx) < 0)
8448 		return -1;
8449 	if (test_eval_2(ctx) < 0)
8450 		return -1;
8451 	if (test_eval_3(ctx) < 0)
8452 		return -1;
8453 	if (test_eval_aff(ctx) < 0)
8454 		return -1;
8455 	return 0;
8456 }
8457 
8458 /* Descriptions of sets that are tested for reparsing after printing.
8459  */
8460 const char *output_tests[] = {
8461 	"{ [1, y] : 0 <= y <= 1; [x, -x] : 0 <= x <= 1 }",
8462 	"{ [x] : 1 = 0 }",
8463 	"{ [x] : false }",
8464 	"{ [x] : x mod 2 = 0 }",
8465 	"{ [x] : x mod 2 = 1 }",
8466 	"{ [x, y] : x mod 2 = 0 and 3*floor(y/2) < x }",
8467 	"{ [y, x] : x mod 2 = 0 and 3*floor(y/2) < x }",
8468 	"{ [x, y] : x mod 2 = 0 and 3*floor(y/2) = x + y }",
8469 	"{ [y, x] : x mod 2 = 0 and 3*floor(y/2) = x + y }",
8470 	"[n] -> { [y, x] : 2*((x + 2y) mod 3) = n }",
8471 	"{ [x, y] : (2*floor(x/3) + 3*floor(y/4)) mod 5 = x }",
8472 };
8473 
8474 /* Check that printing a set and reparsing a set from the printed output
8475  * results in the same set.
8476  */
test_output_set(isl_ctx * ctx)8477 static int test_output_set(isl_ctx *ctx)
8478 {
8479 	int i;
8480 	char *str;
8481 	isl_set *set1, *set2;
8482 	isl_bool equal;
8483 
8484 	for (i = 0; i < ARRAY_SIZE(output_tests); ++i) {
8485 		set1 = isl_set_read_from_str(ctx, output_tests[i]);
8486 		str = isl_set_to_str(set1);
8487 		set2 = isl_set_read_from_str(ctx, str);
8488 		free(str);
8489 		equal = isl_set_is_equal(set1, set2);
8490 		isl_set_free(set1);
8491 		isl_set_free(set2);
8492 		if (equal < 0)
8493 			return -1;
8494 		if (!equal)
8495 			isl_die(ctx, isl_error_unknown,
8496 				"parsed output not the same", return -1);
8497 	}
8498 
8499 	return 0;
8500 }
8501 
8502 /* Check that an isl_multi_aff is printed using a consistent space.
8503  */
test_output_ma(isl_ctx * ctx)8504 static isl_stat test_output_ma(isl_ctx *ctx)
8505 {
8506 	char *str;
8507 	isl_bool equal;
8508 	isl_aff *aff;
8509 	isl_multi_aff *ma, *ma2;
8510 
8511 	ma = isl_multi_aff_read_from_str(ctx, "{ [a, b] -> [a + b] }");
8512 	aff = isl_aff_read_from_str(ctx, "{ [c, d] -> [c + d] }");
8513 	ma = isl_multi_aff_set_aff(ma, 0, aff);
8514 	str = isl_multi_aff_to_str(ma);
8515 	ma2 = isl_multi_aff_read_from_str(ctx, str);
8516 	free(str);
8517 	equal = isl_multi_aff_plain_is_equal(ma, ma2);
8518 	isl_multi_aff_free(ma2);
8519 	isl_multi_aff_free(ma);
8520 
8521 	if (equal < 0)
8522 		return isl_stat_error;
8523 	if (!equal)
8524 		isl_die(ctx, isl_error_unknown, "bad conversion",
8525 			return isl_stat_error);
8526 
8527 	return isl_stat_ok;
8528 }
8529 
8530 /* Check that an isl_multi_pw_aff is printed using a consistent space.
8531  */
test_output_mpa(isl_ctx * ctx)8532 static isl_stat test_output_mpa(isl_ctx *ctx)
8533 {
8534 	char *str;
8535 	isl_bool equal;
8536 	isl_pw_aff *pa;
8537 	isl_multi_pw_aff *mpa, *mpa2;
8538 
8539 	mpa = isl_multi_pw_aff_read_from_str(ctx, "{ [a, b] -> [a + b] }");
8540 	pa = isl_pw_aff_read_from_str(ctx, "{ [c, d] -> [c + d] }");
8541 	mpa = isl_multi_pw_aff_set_pw_aff(mpa, 0, pa);
8542 	str = isl_multi_pw_aff_to_str(mpa);
8543 	mpa2 = isl_multi_pw_aff_read_from_str(ctx, str);
8544 	free(str);
8545 	equal = isl_multi_pw_aff_plain_is_equal(mpa, mpa2);
8546 	isl_multi_pw_aff_free(mpa2);
8547 	isl_multi_pw_aff_free(mpa);
8548 
8549 	if (equal < 0)
8550 		return isl_stat_error;
8551 	if (!equal)
8552 		isl_die(ctx, isl_error_unknown, "bad conversion",
8553 			return isl_stat_error);
8554 
8555 	return isl_stat_ok;
8556 }
8557 
test_output(isl_ctx * ctx)8558 int test_output(isl_ctx *ctx)
8559 {
8560 	char *s;
8561 	const char *str;
8562 	isl_pw_aff *pa;
8563 	isl_printer *p;
8564 	int equal;
8565 
8566 	if (test_output_set(ctx) < 0)
8567 		return -1;
8568 	if (test_output_ma(ctx) < 0)
8569 		return -1;
8570 	if (test_output_mpa(ctx) < 0)
8571 		return -1;
8572 
8573 	str = "[x] -> { [1] : x % 4 <= 2; [2] : x = 3 }";
8574 	pa = isl_pw_aff_read_from_str(ctx, str);
8575 
8576 	p = isl_printer_to_str(ctx);
8577 	p = isl_printer_set_output_format(p, ISL_FORMAT_C);
8578 	p = isl_printer_print_pw_aff(p, pa);
8579 	s = isl_printer_get_str(p);
8580 	isl_printer_free(p);
8581 	isl_pw_aff_free(pa);
8582 	if (!s)
8583 		equal = -1;
8584 	else
8585 		equal = !strcmp(s, "4 * floord(x, 4) + 2 >= x ? 1 : 2");
8586 	free(s);
8587 	if (equal < 0)
8588 		return -1;
8589 	if (!equal)
8590 		isl_die(ctx, isl_error_unknown, "unexpected result", return -1);
8591 
8592 	return 0;
8593 }
8594 
test_sample(isl_ctx * ctx)8595 int test_sample(isl_ctx *ctx)
8596 {
8597 	const char *str;
8598 	isl_basic_set *bset1, *bset2;
8599 	int empty, subset;
8600 
8601 	str = "{ [a, b, c, d, e, f, g, h, i, j, k] : "
8602 	    "3i >= 1073741823b - c - 1073741823e + f and c >= 0 and "
8603 	    "3i >= -1 + 3221225466b + c + d - 3221225466e - f and "
8604 	    "2e >= a - b and 3e <= 2a and 3k <= -a and f <= -1 + a and "
8605 	    "3i <= 4 - a + 4b + 2c - e - 2f and 3k <= -a + c - f and "
8606 	    "3h >= -2 + a and 3g >= -3 - a and 3k >= -2 - a and "
8607 	    "3i >= -2 - a - 2c + 3e + 2f and 3h <= a + c - f and "
8608 	    "3h >= a + 2147483646b + 2c - 2147483646e - 2f and "
8609 	    "3g <= -1 - a and 3i <= 1 + c + d - f and a <= 1073741823 and "
8610 	    "f >= 1 - a + 1073741822b + c + d - 1073741822e and "
8611 	    "3i >= 1 + 2b - 2c + e + 2f + 3g and "
8612 	    "1073741822f <= 1073741822 - a + 1073741821b + 1073741822c +"
8613 		"d - 1073741821e and "
8614 	    "3j <= 3 - a + 3b and 3g <= -2 - 2b + c + d - e - f and "
8615 	    "3j >= 1 - a + b + 2e and "
8616 	    "3f >= -3 + a + 3221225462b + 3c + d - 3221225465e and "
8617 	    "3i <= 4 - a + 4b - e and "
8618 	    "f <= 1073741822 + 1073741822b - 1073741822e and 3h <= a and "
8619 	    "f >= 0 and 2e <= 4 - a + 5b - d and 2e <= a - b + d and "
8620 	    "c <= -1 + a and 3i >= -2 - a + 3e and "
8621 	    "1073741822e <= 1073741823 - a + 1073741822b + c and "
8622 	    "3g >= -4 + 3221225464b + 3c + d - 3221225467e - 3f and "
8623 	    "3i >= -1 + 3221225466b + 3c + d - 3221225466e - 3f and "
8624 	    "1073741823e >= 1 + 1073741823b - d and "
8625 	    "3i >= 1073741823b + c - 1073741823e - f and "
8626 	    "3i >= 1 + 2b + e + 3g }";
8627 	bset1 = isl_basic_set_read_from_str(ctx, str);
8628 	bset2 = isl_basic_set_sample(isl_basic_set_copy(bset1));
8629 	empty = isl_basic_set_is_empty(bset2);
8630 	subset = isl_basic_set_is_subset(bset2, bset1);
8631 	isl_basic_set_free(bset1);
8632 	isl_basic_set_free(bset2);
8633 	if (empty < 0 || subset < 0)
8634 		return -1;
8635 	if (empty)
8636 		isl_die(ctx, isl_error_unknown, "point not found", return -1);
8637 	if (!subset)
8638 		isl_die(ctx, isl_error_unknown, "bad point found", return -1);
8639 
8640 	return 0;
8641 }
8642 
test_fixed_power(isl_ctx * ctx)8643 int test_fixed_power(isl_ctx *ctx)
8644 {
8645 	const char *str;
8646 	isl_map *map;
8647 	isl_val *exp;
8648 	int equal;
8649 
8650 	str = "{ [i] -> [i + 1] }";
8651 	map = isl_map_read_from_str(ctx, str);
8652 	exp = isl_val_int_from_si(ctx, 23);
8653 	map = isl_map_fixed_power_val(map, exp);
8654 	equal = map_check_equal(map, "{ [i] -> [i + 23] }");
8655 	isl_map_free(map);
8656 	if (equal < 0)
8657 		return -1;
8658 
8659 	return 0;
8660 }
8661 
test_slice(isl_ctx * ctx)8662 int test_slice(isl_ctx *ctx)
8663 {
8664 	const char *str;
8665 	isl_map *map;
8666 	int equal;
8667 
8668 	str = "{ [i] -> [j] }";
8669 	map = isl_map_read_from_str(ctx, str);
8670 	map = isl_map_equate(map, isl_dim_in, 0, isl_dim_out, 0);
8671 	equal = map_check_equal(map, "{ [i] -> [i] }");
8672 	isl_map_free(map);
8673 	if (equal < 0)
8674 		return -1;
8675 
8676 	str = "{ [i] -> [j] }";
8677 	map = isl_map_read_from_str(ctx, str);
8678 	map = isl_map_equate(map, isl_dim_in, 0, isl_dim_in, 0);
8679 	equal = map_check_equal(map, "{ [i] -> [j] }");
8680 	isl_map_free(map);
8681 	if (equal < 0)
8682 		return -1;
8683 
8684 	str = "{ [i] -> [j] }";
8685 	map = isl_map_read_from_str(ctx, str);
8686 	map = isl_map_oppose(map, isl_dim_in, 0, isl_dim_out, 0);
8687 	equal = map_check_equal(map, "{ [i] -> [-i] }");
8688 	isl_map_free(map);
8689 	if (equal < 0)
8690 		return -1;
8691 
8692 	str = "{ [i] -> [j] }";
8693 	map = isl_map_read_from_str(ctx, str);
8694 	map = isl_map_oppose(map, isl_dim_in, 0, isl_dim_in, 0);
8695 	equal = map_check_equal(map, "{ [0] -> [j] }");
8696 	isl_map_free(map);
8697 	if (equal < 0)
8698 		return -1;
8699 
8700 	str = "{ [i] -> [j] }";
8701 	map = isl_map_read_from_str(ctx, str);
8702 	map = isl_map_order_gt(map, isl_dim_in, 0, isl_dim_out, 0);
8703 	equal = map_check_equal(map, "{ [i] -> [j] : i > j }");
8704 	isl_map_free(map);
8705 	if (equal < 0)
8706 		return -1;
8707 
8708 	str = "{ [i] -> [j] }";
8709 	map = isl_map_read_from_str(ctx, str);
8710 	map = isl_map_order_gt(map, isl_dim_in, 0, isl_dim_in, 0);
8711 	equal = map_check_equal(map, "{ [i] -> [j] : false }");
8712 	isl_map_free(map);
8713 	if (equal < 0)
8714 		return -1;
8715 
8716 	return 0;
8717 }
8718 
test_eliminate(isl_ctx * ctx)8719 int test_eliminate(isl_ctx *ctx)
8720 {
8721 	const char *str;
8722 	isl_map *map;
8723 	int equal;
8724 
8725 	str = "{ [i] -> [j] : i = 2j }";
8726 	map = isl_map_read_from_str(ctx, str);
8727 	map = isl_map_eliminate(map, isl_dim_out, 0, 1);
8728 	equal = map_check_equal(map, "{ [i] -> [j] : exists a : i = 2a }");
8729 	isl_map_free(map);
8730 	if (equal < 0)
8731 		return -1;
8732 
8733 	return 0;
8734 }
8735 
8736 /* Check basic functionality of isl_map_deltas_map.
8737  */
test_deltas_map(isl_ctx * ctx)8738 static int test_deltas_map(isl_ctx *ctx)
8739 {
8740 	const char *str;
8741 	isl_map *map;
8742 	int equal;
8743 
8744 	str = "{ A[i] -> A[i + 1] }";
8745 	map = isl_map_read_from_str(ctx, str);
8746 	map = isl_map_deltas_map(map);
8747 	equal = map_check_equal(map, "{ [A[i] -> A[i + 1]] -> A[1] }");
8748 	isl_map_free(map);
8749 	if (equal < 0)
8750 		return -1;
8751 
8752 	return 0;
8753 }
8754 
8755 /* Check that isl_set_dim_residue_class detects that the values of j
8756  * in the set below are all odd and that it does not detect any spurious
8757  * strides.
8758  */
test_residue_class(isl_ctx * ctx)8759 static int test_residue_class(isl_ctx *ctx)
8760 {
8761 	const char *str;
8762 	isl_set *set;
8763 	isl_int m, r;
8764 	isl_stat res;
8765 
8766 	str = "{ [i,j] : j = 4 i + 1 and 0 <= i <= 100; "
8767 		"[i,j] : j = 4 i + 3 and 500 <= i <= 600 }";
8768 	set = isl_set_read_from_str(ctx, str);
8769 	isl_int_init(m);
8770 	isl_int_init(r);
8771 	res = isl_set_dim_residue_class(set, 1, &m, &r);
8772 	if (res >= 0 &&
8773 	    (isl_int_cmp_si(m, 2) != 0 || isl_int_cmp_si(r, 1) != 0))
8774 		isl_die(ctx, isl_error_unknown, "incorrect residue class",
8775 			res = isl_stat_error);
8776 	isl_int_clear(r);
8777 	isl_int_clear(m);
8778 	isl_set_free(set);
8779 
8780 	return res;
8781 }
8782 
test_align_parameters_1(isl_ctx * ctx)8783 static int test_align_parameters_1(isl_ctx *ctx)
8784 {
8785 	const char *str;
8786 	isl_space *space;
8787 	isl_multi_aff *ma1, *ma2;
8788 	int equal;
8789 
8790 	str = "{ A[B[] -> C[]] -> D[E[] -> F[]] }";
8791 	ma1 = isl_multi_aff_read_from_str(ctx, str);
8792 
8793 	space = isl_space_params_alloc(ctx, 1);
8794 	space = isl_space_set_dim_name(space, isl_dim_param, 0, "N");
8795 	ma1 = isl_multi_aff_align_params(ma1, space);
8796 
8797 	str = "[N] -> { A[B[] -> C[]] -> D[E[] -> F[]] }";
8798 	ma2 = isl_multi_aff_read_from_str(ctx, str);
8799 
8800 	equal = isl_multi_aff_plain_is_equal(ma1, ma2);
8801 
8802 	isl_multi_aff_free(ma1);
8803 	isl_multi_aff_free(ma2);
8804 
8805 	if (equal < 0)
8806 		return -1;
8807 	if (!equal)
8808 		isl_die(ctx, isl_error_unknown,
8809 			"result not as expected", return -1);
8810 
8811 	return 0;
8812 }
8813 
8814 /* Check the isl_multi_*_from_*_list operation in case inputs
8815  * have unaligned parameters.
8816  * In particular, older versions of isl would simply fail
8817  * (without printing any error message).
8818  */
test_align_parameters_2(isl_ctx * ctx)8819 static isl_stat test_align_parameters_2(isl_ctx *ctx)
8820 {
8821 	isl_space *space;
8822 	isl_map *map;
8823 	isl_aff *aff;
8824 	isl_multi_aff *ma;
8825 
8826 	map = isl_map_read_from_str(ctx, "{ A[] -> M[x] }");
8827 	space = isl_map_get_space(map);
8828 	isl_map_free(map);
8829 
8830 	aff = isl_aff_read_from_str(ctx, "[N] -> { A[] -> [N] }");
8831 	ma = isl_multi_aff_from_aff_list(space, isl_aff_list_from_aff(aff));
8832 	isl_multi_aff_free(ma);
8833 
8834 	if (!ma)
8835 		return isl_stat_error;
8836 	return isl_stat_ok;
8837 }
8838 
8839 /* Perform basic parameter alignment tests.
8840  */
test_align_parameters(isl_ctx * ctx)8841 static int test_align_parameters(isl_ctx *ctx)
8842 {
8843 	if (test_align_parameters_1(ctx) < 0)
8844 		return -1;
8845 	if (test_align_parameters_2(ctx) < 0)
8846 		return -1;
8847 
8848 	return 0;
8849 }
8850 
8851 /* Check that isl_*_drop_unused_params actually drops the unused parameters
8852  * by comparing the result using isl_*_plain_is_equal.
8853  * Note that this assumes that isl_*_plain_is_equal does not consider
8854  * objects that only differ by unused parameters to be equal.
8855  */
test_drop_unused_parameters(isl_ctx * ctx)8856 int test_drop_unused_parameters(isl_ctx *ctx)
8857 {
8858 	const char *str_with, *str_without;
8859 	isl_basic_set *bset1, *bset2;
8860 	isl_set *set1, *set2;
8861 	isl_pw_aff *pwa1, *pwa2;
8862 	int equal;
8863 
8864 	str_with = "[n, m, o] -> { [m] }";
8865 	str_without = "[m] -> { [m] }";
8866 
8867 	bset1 = isl_basic_set_read_from_str(ctx, str_with);
8868 	bset2 = isl_basic_set_read_from_str(ctx, str_without);
8869 	bset1 = isl_basic_set_drop_unused_params(bset1);
8870 	equal = isl_basic_set_plain_is_equal(bset1, bset2);
8871 	isl_basic_set_free(bset1);
8872 	isl_basic_set_free(bset2);
8873 
8874 	if (equal < 0)
8875 		return -1;
8876 	if (!equal)
8877 		isl_die(ctx, isl_error_unknown,
8878 			"result not as expected", return -1);
8879 
8880 	set1 = isl_set_read_from_str(ctx, str_with);
8881 	set2 = isl_set_read_from_str(ctx, str_without);
8882 	set1 = isl_set_drop_unused_params(set1);
8883 	equal = isl_set_plain_is_equal(set1, set2);
8884 	isl_set_free(set1);
8885 	isl_set_free(set2);
8886 
8887 	if (equal < 0)
8888 		return -1;
8889 	if (!equal)
8890 		isl_die(ctx, isl_error_unknown,
8891 			"result not as expected", return -1);
8892 
8893 	pwa1 = isl_pw_aff_read_from_str(ctx, str_with);
8894 	pwa2 = isl_pw_aff_read_from_str(ctx, str_without);
8895 	pwa1 = isl_pw_aff_drop_unused_params(pwa1);
8896 	equal = isl_pw_aff_plain_is_equal(pwa1, pwa2);
8897 	isl_pw_aff_free(pwa1);
8898 	isl_pw_aff_free(pwa2);
8899 
8900 	if (equal < 0)
8901 		return -1;
8902 	if (!equal)
8903 		isl_die(ctx, isl_error_unknown,
8904 			"result not as expected", return -1);
8905 
8906 	return 0;
8907 }
8908 
test_list(isl_ctx * ctx)8909 static int test_list(isl_ctx *ctx)
8910 {
8911 	isl_id *a, *b, *c, *d, *id;
8912 	isl_id_list *list;
8913 	isl_size n;
8914 	int ok;
8915 
8916 	a = isl_id_alloc(ctx, "a", NULL);
8917 	b = isl_id_alloc(ctx, "b", NULL);
8918 	c = isl_id_alloc(ctx, "c", NULL);
8919 	d = isl_id_alloc(ctx, "d", NULL);
8920 
8921 	list = isl_id_list_alloc(ctx, 4);
8922 	list = isl_id_list_add(list, b);
8923 	list = isl_id_list_insert(list, 0, a);
8924 	list = isl_id_list_add(list, c);
8925 	list = isl_id_list_add(list, d);
8926 	list = isl_id_list_drop(list, 1, 1);
8927 
8928 	n = isl_id_list_n_id(list);
8929 	if (n < 0)
8930 		return -1;
8931 	if (n != 3) {
8932 		isl_id_list_free(list);
8933 		isl_die(ctx, isl_error_unknown,
8934 			"unexpected number of elements in list", return -1);
8935 	}
8936 
8937 	id = isl_id_list_get_id(list, 0);
8938 	ok = id == a;
8939 	isl_id_free(id);
8940 	id = isl_id_list_get_id(list, 1);
8941 	ok = ok && id == c;
8942 	isl_id_free(id);
8943 	id = isl_id_list_get_id(list, 2);
8944 	ok = ok && id == d;
8945 	isl_id_free(id);
8946 
8947 	isl_id_list_free(list);
8948 
8949 	if (!ok)
8950 		isl_die(ctx, isl_error_unknown,
8951 			"unexpected elements in list", return -1);
8952 
8953 	return 0;
8954 }
8955 
8956 /* Check the conversion from an isl_multi_aff to an isl_basic_set.
8957  */
test_ma_conversion(isl_ctx * ctx)8958 static isl_stat test_ma_conversion(isl_ctx *ctx)
8959 {
8960 	const char *str;
8961 	isl_bool equal;
8962 	isl_multi_aff *ma;
8963 	isl_basic_set *bset1, *bset2;
8964 
8965 	str = "[N] -> { A[0, N + 1] }";
8966 	ma = isl_multi_aff_read_from_str(ctx, str);
8967 	bset1 = isl_basic_set_read_from_str(ctx, str);
8968 	bset2 = isl_basic_set_from_multi_aff(ma);
8969 	equal = isl_basic_set_is_equal(bset1, bset2);
8970 	isl_basic_set_free(bset1);
8971 	isl_basic_set_free(bset2);
8972 	if (equal < 0)
8973 		return isl_stat_error;
8974 	if (!equal)
8975 		isl_die(ctx, isl_error_unknown, "bad conversion",
8976 			return isl_stat_error);
8977 	return isl_stat_ok;
8978 }
8979 
8980 const char *set_conversion_tests[] = {
8981 	"[N] -> { [i] : N - 1 <= 2 i <= N }",
8982 	"[N] -> { [i] : exists a : i = 4 a and N - 1 <= i <= N }",
8983 	"[N] -> { [i,j] : exists a : i = 4 a and N - 1 <= i, 2j <= N }",
8984 	"[N] -> { [[i]->[j]] : exists a : i = 4 a and N - 1 <= i, 2j <= N }",
8985 	"[N] -> { [3*floor(N/2) + 5*floor(N/3)] }",
8986 	"[a, b] -> { [c, d] : (4*floor((-a + c)/4) = -a + c and "
8987 			"32*floor((-b + d)/32) = -b + d and 5 <= c <= 8 and "
8988 			"-3 + c <= d <= 28 + c) }",
8989 };
8990 
8991 /* Check that converting from isl_set to isl_pw_multi_aff and back
8992  * to isl_set produces the original isl_set.
8993  */
test_set_conversion(isl_ctx * ctx)8994 static int test_set_conversion(isl_ctx *ctx)
8995 {
8996 	int i;
8997 	const char *str;
8998 	isl_set *set1, *set2;
8999 	isl_pw_multi_aff *pma;
9000 	int equal;
9001 
9002 	for (i = 0; i < ARRAY_SIZE(set_conversion_tests); ++i) {
9003 		str = set_conversion_tests[i];
9004 		set1 = isl_set_read_from_str(ctx, str);
9005 		pma = isl_pw_multi_aff_from_set(isl_set_copy(set1));
9006 		set2 = isl_set_from_pw_multi_aff(pma);
9007 		equal = isl_set_is_equal(set1, set2);
9008 		isl_set_free(set1);
9009 		isl_set_free(set2);
9010 
9011 		if (equal < 0)
9012 			return -1;
9013 		if (!equal)
9014 			isl_die(ctx, isl_error_unknown, "bad conversion",
9015 				return -1);
9016 	}
9017 
9018 	return 0;
9019 }
9020 
9021 const char *conversion_tests[] = {
9022 	"{ [a, b, c, d] -> s0[a, b, e, f] : "
9023 	    "exists (e0 = [(a - 2c)/3], e1 = [(-4 + b - 5d)/9], "
9024 	    "e2 = [(-d + f)/9]: 3e0 = a - 2c and 9e1 = -4 + b - 5d and "
9025 	    "9e2 = -d + f and f >= 0 and f <= 8 and 9e >= -5 - 2a and "
9026 	    "9e <= -2 - 2a) }",
9027 	"{ [a, b] -> [c] : exists (e0 = floor((-a - b + c)/5): "
9028 	    "5e0 = -a - b + c and c >= -a and c <= 4 - a) }",
9029 	"{ [a, b] -> [c] : exists d : 18 * d = -3 - a + 2c and 1 <= c <= 3 }",
9030 };
9031 
9032 /* Check that converting from isl_map to isl_pw_multi_aff and back
9033  * to isl_map produces the original isl_map.
9034  */
test_map_conversion(isl_ctx * ctx)9035 static int test_map_conversion(isl_ctx *ctx)
9036 {
9037 	int i;
9038 	isl_map *map1, *map2;
9039 	isl_pw_multi_aff *pma;
9040 	int equal;
9041 
9042 	for (i = 0; i < ARRAY_SIZE(conversion_tests); ++i) {
9043 		map1 = isl_map_read_from_str(ctx, conversion_tests[i]);
9044 		pma = isl_pw_multi_aff_from_map(isl_map_copy(map1));
9045 		map2 = isl_map_from_pw_multi_aff(pma);
9046 		equal = isl_map_is_equal(map1, map2);
9047 		isl_map_free(map1);
9048 		isl_map_free(map2);
9049 
9050 		if (equal < 0)
9051 			return -1;
9052 		if (!equal)
9053 			isl_die(ctx, isl_error_unknown, "bad conversion",
9054 				return -1);
9055 	}
9056 
9057 	return 0;
9058 }
9059 
9060 /* Descriptions of isl_pw_multi_aff objects for testing conversion
9061  * to isl_multi_pw_aff and back.
9062  */
9063 const char *mpa_conversion_tests[] = {
9064 	"{ [x] -> A[x] }",
9065 	"{ [x] -> A[x] : x >= 0 }",
9066 	"{ [x] -> A[x] : x >= 0; [x] -> A[-x] : x < 0 }",
9067 	"{ [x] -> A[x, x + 1] }",
9068 	"{ [x] -> A[] }",
9069 	"{ [x] -> A[] : x >= 0 }",
9070 };
9071 
9072 /* Check that conversion from isl_pw_multi_aff to isl_multi_pw_aff and
9073  * back to isl_pw_multi_aff preserves the original meaning.
9074  */
test_mpa_conversion(isl_ctx * ctx)9075 static int test_mpa_conversion(isl_ctx *ctx)
9076 {
9077 	int i;
9078 	isl_pw_multi_aff *pma1, *pma2;
9079 	isl_multi_pw_aff *mpa;
9080 	int equal;
9081 
9082 	for (i = 0; i < ARRAY_SIZE(mpa_conversion_tests); ++i) {
9083 		const char *str;
9084 		str = mpa_conversion_tests[i];
9085 		pma1 = isl_pw_multi_aff_read_from_str(ctx, str);
9086 		pma2 = isl_pw_multi_aff_copy(pma1);
9087 		mpa = isl_multi_pw_aff_from_pw_multi_aff(pma1);
9088 		pma1 = isl_pw_multi_aff_from_multi_pw_aff(mpa);
9089 		equal = isl_pw_multi_aff_plain_is_equal(pma1, pma2);
9090 		isl_pw_multi_aff_free(pma1);
9091 		isl_pw_multi_aff_free(pma2);
9092 
9093 		if (equal < 0)
9094 			return -1;
9095 		if (!equal)
9096 			isl_die(ctx, isl_error_unknown, "bad conversion",
9097 				return -1);
9098 	}
9099 
9100 	return 0;
9101 }
9102 
9103 /* Descriptions of union maps that should be convertible
9104  * to an isl_multi_union_pw_aff.
9105  */
9106 const char *umap_mupa_conversion_tests[] = {
9107 	"{ [a, b, c, d] -> s0[a, b, e, f] : "
9108 	    "exists (e0 = [(a - 2c)/3], e1 = [(-4 + b - 5d)/9], "
9109 	    "e2 = [(-d + f)/9]: 3e0 = a - 2c and 9e1 = -4 + b - 5d and "
9110 	    "9e2 = -d + f and f >= 0 and f <= 8 and 9e >= -5 - 2a and "
9111 	    "9e <= -2 - 2a) }",
9112 	"{ [a, b] -> [c] : exists (e0 = floor((-a - b + c)/5): "
9113 	    "5e0 = -a - b + c and c >= -a and c <= 4 - a) }",
9114 	"{ [a, b] -> [c] : exists d : 18 * d = -3 - a + 2c and 1 <= c <= 3 }",
9115 	"{ A[] -> B[0]; C[] -> B[1] }",
9116 	"{ A[] -> B[]; C[] -> B[] }",
9117 };
9118 
9119 /* Check that converting from isl_union_map to isl_multi_union_pw_aff and back
9120  * to isl_union_map produces the original isl_union_map.
9121  */
test_union_map_mupa_conversion(isl_ctx * ctx)9122 static int test_union_map_mupa_conversion(isl_ctx *ctx)
9123 {
9124 	int i;
9125 	isl_union_map *umap1, *umap2;
9126 	isl_multi_union_pw_aff *mupa;
9127 	int equal;
9128 
9129 	for (i = 0; i < ARRAY_SIZE(umap_mupa_conversion_tests); ++i) {
9130 		const char *str;
9131 		str = umap_mupa_conversion_tests[i];
9132 		umap1 = isl_union_map_read_from_str(ctx, str);
9133 		umap2 = isl_union_map_copy(umap1);
9134 		mupa = isl_multi_union_pw_aff_from_union_map(umap2);
9135 		umap2 = isl_union_map_from_multi_union_pw_aff(mupa);
9136 		equal = isl_union_map_is_equal(umap1, umap2);
9137 		isl_union_map_free(umap1);
9138 		isl_union_map_free(umap2);
9139 
9140 		if (equal < 0)
9141 			return -1;
9142 		if (!equal)
9143 			isl_die(ctx, isl_error_unknown, "bad conversion",
9144 				return -1);
9145 	}
9146 
9147 	return 0;
9148 }
9149 
test_conversion(isl_ctx * ctx)9150 static int test_conversion(isl_ctx *ctx)
9151 {
9152 	if (test_ma_conversion(ctx) < 0)
9153 		return -1;
9154 	if (test_set_conversion(ctx) < 0)
9155 		return -1;
9156 	if (test_map_conversion(ctx) < 0)
9157 		return -1;
9158 	if (test_mpa_conversion(ctx) < 0)
9159 		return -1;
9160 	if (test_union_map_mupa_conversion(ctx) < 0)
9161 		return -1;
9162 	return 0;
9163 }
9164 
9165 /* Check that isl_basic_map_curry does not modify input.
9166  */
test_curry(isl_ctx * ctx)9167 static int test_curry(isl_ctx *ctx)
9168 {
9169 	const char *str;
9170 	isl_basic_map *bmap1, *bmap2;
9171 	int equal;
9172 
9173 	str = "{ [A[] -> B[]] -> C[] }";
9174 	bmap1 = isl_basic_map_read_from_str(ctx, str);
9175 	bmap2 = isl_basic_map_curry(isl_basic_map_copy(bmap1));
9176 	equal = isl_basic_map_is_equal(bmap1, bmap2);
9177 	isl_basic_map_free(bmap1);
9178 	isl_basic_map_free(bmap2);
9179 
9180 	if (equal < 0)
9181 		return -1;
9182 	if (equal)
9183 		isl_die(ctx, isl_error_unknown,
9184 			"curried map should not be equal to original",
9185 			return -1);
9186 
9187 	return 0;
9188 }
9189 
9190 struct {
9191 	const char *set;
9192 	const char *ma;
9193 	const char *res;
9194 } preimage_tests[] = {
9195 	{ "{ B[i,j] : 0 <= i < 10 and 0 <= j < 100 }",
9196 	  "{ A[j,i] -> B[i,j] }",
9197 	  "{ A[j,i] : 0 <= i < 10 and 0 <= j < 100 }" },
9198 	{ "{ rat: B[i,j] : 0 <= i, j and 3 i + 5 j <= 100 }",
9199 	  "{ A[a,b] -> B[a/2,b/6] }",
9200 	  "{ rat: A[a,b] : 0 <= a, b and 9 a + 5 b <= 600 }" },
9201 	{ "{ B[i,j] : 0 <= i, j and 3 i + 5 j <= 100 }",
9202 	  "{ A[a,b] -> B[a/2,b/6] }",
9203 	  "{ A[a,b] : 0 <= a, b and 9 a + 5 b <= 600 and "
9204 		    "exists i,j : a = 2 i and b = 6 j }" },
9205 	{ "[n] -> { S[i] : 0 <= i <= 100 }", "[n] -> { S[n] }",
9206 	  "[n] -> { : 0 <= n <= 100 }" },
9207 	{ "{ B[i] : 0 <= i < 100 and exists a : i = 4 a }",
9208 	  "{ A[a] -> B[2a] }",
9209 	  "{ A[a] : 0 <= a < 50 and exists b : a = 2 b }" },
9210 	{ "{ B[i] : 0 <= i < 100 and exists a : i = 4 a }",
9211 	  "{ A[a] -> B[([a/2])] }",
9212 	  "{ A[a] : 0 <= a < 200 and exists b : [a/2] = 4 b }" },
9213 	{ "{ B[i,j,k] : 0 <= i,j,k <= 100 }",
9214 	  "{ A[a] -> B[a,a,a/3] }",
9215 	  "{ A[a] : 0 <= a <= 100 and exists b : a = 3 b }" },
9216 	{ "{ B[i,j] : j = [(i)/2] } ", "{ A[i,j] -> B[i/3,j] }",
9217 	  "{ A[i,j] : j = [(i)/6] and exists a : i = 3 a }" },
9218 };
9219 
test_preimage_basic_set(isl_ctx * ctx)9220 static int test_preimage_basic_set(isl_ctx *ctx)
9221 {
9222 	int i;
9223 	isl_basic_set *bset1, *bset2;
9224 	isl_multi_aff *ma;
9225 	int equal;
9226 
9227 	for (i = 0; i < ARRAY_SIZE(preimage_tests); ++i) {
9228 		bset1 = isl_basic_set_read_from_str(ctx, preimage_tests[i].set);
9229 		ma = isl_multi_aff_read_from_str(ctx, preimage_tests[i].ma);
9230 		bset2 = isl_basic_set_read_from_str(ctx, preimage_tests[i].res);
9231 		bset1 = isl_basic_set_preimage_multi_aff(bset1, ma);
9232 		equal = isl_basic_set_is_equal(bset1, bset2);
9233 		isl_basic_set_free(bset1);
9234 		isl_basic_set_free(bset2);
9235 		if (equal < 0)
9236 			return -1;
9237 		if (!equal)
9238 			isl_die(ctx, isl_error_unknown, "bad preimage",
9239 				return -1);
9240 	}
9241 
9242 	return 0;
9243 }
9244 
9245 struct {
9246 	const char *map;
9247 	const char *ma;
9248 	const char *res;
9249 } preimage_domain_tests[] = {
9250 	{ "{ B[i,j] -> C[2i + 3j] : 0 <= i < 10 and 0 <= j < 100 }",
9251 	  "{ A[j,i] -> B[i,j] }",
9252 	  "{ A[j,i] -> C[2i + 3j] : 0 <= i < 10 and 0 <= j < 100 }" },
9253 	{ "{ B[i] -> C[i]; D[i] -> E[i] }",
9254 	  "{ A[i] -> B[i + 1] }",
9255 	  "{ A[i] -> C[i + 1] }" },
9256 	{ "{ B[i] -> C[i]; B[i] -> E[i] }",
9257 	  "{ A[i] -> B[i + 1] }",
9258 	  "{ A[i] -> C[i + 1]; A[i] -> E[i + 1] }" },
9259 	{ "{ B[i] -> C[([i/2])] }",
9260 	  "{ A[i] -> B[2i] }",
9261 	  "{ A[i] -> C[i] }" },
9262 	{ "{ B[i,j] -> C[([i/2]), ([(i+j)/3])] }",
9263 	  "{ A[i] -> B[([i/5]), ([i/7])] }",
9264 	  "{ A[i] -> C[([([i/5])/2]), ([(([i/5])+([i/7]))/3])] }" },
9265 	{ "[N] -> { B[i] -> C[([N/2]), i, ([N/3])] }",
9266 	  "[N] -> { A[] -> B[([N/5])] }",
9267 	  "[N] -> { A[] -> C[([N/2]), ([N/5]), ([N/3])] }" },
9268 	{ "{ B[i] -> C[i] : exists a : i = 5 a }",
9269 	  "{ A[i] -> B[2i] }",
9270 	  "{ A[i] -> C[2i] : exists a : 2i = 5 a }" },
9271 	{ "{ B[i] -> C[i] : exists a : i = 2 a; "
9272 	    "B[i] -> D[i] : exists a : i = 2 a + 1 }",
9273 	  "{ A[i] -> B[2i] }",
9274 	  "{ A[i] -> C[2i] }" },
9275 	{ "{ A[i] -> B[i] }", "{ C[i] -> A[(i + floor(i/3))/2] }",
9276 	  "{ C[i] -> B[j] : 2j = i + floor(i/3) }" },
9277 };
9278 
test_preimage_union_map(isl_ctx * ctx)9279 static int test_preimage_union_map(isl_ctx *ctx)
9280 {
9281 	int i;
9282 	isl_union_map *umap1, *umap2;
9283 	isl_multi_aff *ma;
9284 	int equal;
9285 
9286 	for (i = 0; i < ARRAY_SIZE(preimage_domain_tests); ++i) {
9287 		umap1 = isl_union_map_read_from_str(ctx,
9288 						preimage_domain_tests[i].map);
9289 		ma = isl_multi_aff_read_from_str(ctx,
9290 						preimage_domain_tests[i].ma);
9291 		umap2 = isl_union_map_read_from_str(ctx,
9292 						preimage_domain_tests[i].res);
9293 		umap1 = isl_union_map_preimage_domain_multi_aff(umap1, ma);
9294 		equal = isl_union_map_is_equal(umap1, umap2);
9295 		isl_union_map_free(umap1);
9296 		isl_union_map_free(umap2);
9297 		if (equal < 0)
9298 			return -1;
9299 		if (!equal)
9300 			isl_die(ctx, isl_error_unknown, "bad preimage",
9301 				return -1);
9302 	}
9303 
9304 	return 0;
9305 }
9306 
test_preimage(isl_ctx * ctx)9307 static int test_preimage(isl_ctx *ctx)
9308 {
9309 	if (test_preimage_basic_set(ctx) < 0)
9310 		return -1;
9311 	if (test_preimage_union_map(ctx) < 0)
9312 		return -1;
9313 
9314 	return 0;
9315 }
9316 
9317 struct {
9318 	const char *ma1;
9319 	const char *ma;
9320 	const char *res;
9321 } pullback_tests[] = {
9322 	{ "{ B[i,j] -> C[i + 2j] }" , "{ A[a,b] -> B[b,a] }",
9323 	  "{ A[a,b] -> C[b + 2a] }" },
9324 	{ "{ B[i] -> C[2i] }", "{ A[a] -> B[(a)/2] }", "{ A[a] -> C[a] }" },
9325 	{ "{ B[i] -> C[(i)/2] }", "{ A[a] -> B[2a] }", "{ A[a] -> C[a] }" },
9326 	{ "{ B[i] -> C[(i)/2] }", "{ A[a] -> B[(a)/3] }",
9327 	  "{ A[a] -> C[(a)/6] }" },
9328 	{ "{ B[i] -> C[2i] }", "{ A[a] -> B[5a] }", "{ A[a] -> C[10a] }" },
9329 	{ "{ B[i] -> C[2i] }", "{ A[a] -> B[(a)/3] }",
9330 	  "{ A[a] -> C[(2a)/3] }" },
9331 	{ "{ B[i,j] -> C[i + j] }", "{ A[a] -> B[a,a] }", "{ A[a] -> C[2a] }"},
9332 	{ "{ B[a] -> C[a,a] }", "{ A[i,j] -> B[i + j] }",
9333 	  "{ A[i,j] -> C[i + j, i + j] }"},
9334 	{ "{ B[i] -> C[([i/2])] }", "{ B[5] }", "{ C[2] }" },
9335 	{ "[n] -> { B[i,j] -> C[([i/2]) + 2j] }",
9336 	  "[n] -> { B[n,[n/3]] }", "[n] -> { C[([n/2]) + 2*[n/3]] }", },
9337 	{ "{ [i, j] -> [floor((i)/4) + floor((2*i+j)/5)] }",
9338 	  "{ [i, j] -> [floor((i)/3), j] }",
9339 	  "{ [i, j] -> [(floor((i)/12) + floor((j + 2*floor((i)/3))/5))] }" },
9340 };
9341 
test_pullback(isl_ctx * ctx)9342 static int test_pullback(isl_ctx *ctx)
9343 {
9344 	int i;
9345 	isl_multi_aff *ma1, *ma2;
9346 	isl_multi_aff *ma;
9347 	int equal;
9348 
9349 	for (i = 0; i < ARRAY_SIZE(pullback_tests); ++i) {
9350 		ma1 = isl_multi_aff_read_from_str(ctx, pullback_tests[i].ma1);
9351 		ma = isl_multi_aff_read_from_str(ctx, pullback_tests[i].ma);
9352 		ma2 = isl_multi_aff_read_from_str(ctx, pullback_tests[i].res);
9353 		ma1 = isl_multi_aff_pullback_multi_aff(ma1, ma);
9354 		equal = isl_multi_aff_plain_is_equal(ma1, ma2);
9355 		isl_multi_aff_free(ma1);
9356 		isl_multi_aff_free(ma2);
9357 		if (equal < 0)
9358 			return -1;
9359 		if (!equal)
9360 			isl_die(ctx, isl_error_unknown, "bad pullback",
9361 				return -1);
9362 	}
9363 
9364 	return 0;
9365 }
9366 
9367 /* Check that negation is printed correctly and that equal expressions
9368  * are correctly identified.
9369  */
test_ast(isl_ctx * ctx)9370 static int test_ast(isl_ctx *ctx)
9371 {
9372 	isl_ast_expr *expr, *expr1, *expr2, *expr3;
9373 	char *str;
9374 	int ok, equal;
9375 
9376 	expr1 = isl_ast_expr_from_id(isl_id_alloc(ctx, "A", NULL));
9377 	expr2 = isl_ast_expr_from_id(isl_id_alloc(ctx, "B", NULL));
9378 	expr = isl_ast_expr_add(expr1, expr2);
9379 	expr2 = isl_ast_expr_copy(expr);
9380 	expr = isl_ast_expr_neg(expr);
9381 	expr2 = isl_ast_expr_neg(expr2);
9382 	equal = isl_ast_expr_is_equal(expr, expr2);
9383 	str = isl_ast_expr_to_C_str(expr);
9384 	ok = str ? !strcmp(str, "-(A + B)") : -1;
9385 	free(str);
9386 	isl_ast_expr_free(expr);
9387 	isl_ast_expr_free(expr2);
9388 
9389 	if (ok < 0 || equal < 0)
9390 		return -1;
9391 	if (!equal)
9392 		isl_die(ctx, isl_error_unknown,
9393 			"equal expressions not considered equal", return -1);
9394 	if (!ok)
9395 		isl_die(ctx, isl_error_unknown,
9396 			"isl_ast_expr printed incorrectly", return -1);
9397 
9398 	expr1 = isl_ast_expr_from_id(isl_id_alloc(ctx, "A", NULL));
9399 	expr2 = isl_ast_expr_from_id(isl_id_alloc(ctx, "B", NULL));
9400 	expr = isl_ast_expr_add(expr1, expr2);
9401 	expr3 = isl_ast_expr_from_id(isl_id_alloc(ctx, "C", NULL));
9402 	expr = isl_ast_expr_sub(expr3, expr);
9403 	str = isl_ast_expr_to_C_str(expr);
9404 	ok = str ? !strcmp(str, "C - (A + B)") : -1;
9405 	free(str);
9406 	isl_ast_expr_free(expr);
9407 
9408 	if (ok < 0)
9409 		return -1;
9410 	if (!ok)
9411 		isl_die(ctx, isl_error_unknown,
9412 			"isl_ast_expr printed incorrectly", return -1);
9413 
9414 	return 0;
9415 }
9416 
9417 /* Check that isl_ast_build_expr_from_set returns a valid expression
9418  * for an empty set.  Note that isl_ast_build_expr_from_set getting
9419  * called on an empty set probably indicates a bug in the caller.
9420  */
test_ast_build(isl_ctx * ctx)9421 static int test_ast_build(isl_ctx *ctx)
9422 {
9423 	isl_set *set;
9424 	isl_ast_build *build;
9425 	isl_ast_expr *expr;
9426 
9427 	set = isl_set_universe(isl_space_params_alloc(ctx, 0));
9428 	build = isl_ast_build_from_context(set);
9429 
9430 	set = isl_set_empty(isl_space_params_alloc(ctx, 0));
9431 	expr = isl_ast_build_expr_from_set(build, set);
9432 
9433 	isl_ast_expr_free(expr);
9434 	isl_ast_build_free(build);
9435 
9436 	if (!expr)
9437 		return -1;
9438 
9439 	return 0;
9440 }
9441 
9442 /* Internal data structure for before_for and after_for callbacks.
9443  *
9444  * depth is the current depth
9445  * before is the number of times before_for has been called
9446  * after is the number of times after_for has been called
9447  */
9448 struct isl_test_codegen_data {
9449 	int depth;
9450 	int before;
9451 	int after;
9452 };
9453 
9454 /* This function is called before each for loop in the AST generated
9455  * from test_ast_gen1.
9456  *
9457  * Increment the number of calls and the depth.
9458  * Check that the space returned by isl_ast_build_get_schedule_space
9459  * matches the target space of the schedule returned by
9460  * isl_ast_build_get_schedule.
9461  * Return an isl_id that is checked by the corresponding call
9462  * to after_for.
9463  */
before_for(__isl_keep isl_ast_build * build,void * user)9464 static __isl_give isl_id *before_for(__isl_keep isl_ast_build *build,
9465 	void *user)
9466 {
9467 	struct isl_test_codegen_data *data = user;
9468 	isl_ctx *ctx;
9469 	isl_space *space;
9470 	isl_union_map *schedule;
9471 	isl_union_set *uset;
9472 	isl_set *set;
9473 	isl_bool empty;
9474 	isl_size n;
9475 	char name[] = "d0";
9476 
9477 	ctx = isl_ast_build_get_ctx(build);
9478 
9479 	if (data->before >= 3)
9480 		isl_die(ctx, isl_error_unknown,
9481 			"unexpected number of for nodes", return NULL);
9482 	if (data->depth < 0 || data->depth >= 2)
9483 		isl_die(ctx, isl_error_unknown,
9484 			"unexpected depth", return NULL);
9485 
9486 	snprintf(name, sizeof(name), "d%d", data->depth);
9487 	data->before++;
9488 	data->depth++;
9489 
9490 	schedule = isl_ast_build_get_schedule(build);
9491 	uset = isl_union_map_range(schedule);
9492 	n = isl_union_set_n_set(uset);
9493 	if (n != 1) {
9494 		isl_union_set_free(uset);
9495 		if (n < 0)
9496 			return NULL;
9497 		isl_die(ctx, isl_error_unknown,
9498 			"expecting single range space", return NULL);
9499 	}
9500 
9501 	space = isl_ast_build_get_schedule_space(build);
9502 	set = isl_union_set_extract_set(uset, space);
9503 	isl_union_set_free(uset);
9504 	empty = isl_set_is_empty(set);
9505 	isl_set_free(set);
9506 
9507 	if (empty < 0)
9508 		return NULL;
9509 	if (empty)
9510 		isl_die(ctx, isl_error_unknown,
9511 			"spaces don't match", return NULL);
9512 
9513 	return isl_id_alloc(ctx, name, NULL);
9514 }
9515 
9516 /* This function is called after each for loop in the AST generated
9517  * from test_ast_gen1.
9518  *
9519  * Increment the number of calls and decrement the depth.
9520  * Check that the annotation attached to the node matches
9521  * the isl_id returned by the corresponding call to before_for.
9522  */
after_for(__isl_take isl_ast_node * node,__isl_keep isl_ast_build * build,void * user)9523 static __isl_give isl_ast_node *after_for(__isl_take isl_ast_node *node,
9524 	__isl_keep isl_ast_build *build, void *user)
9525 {
9526 	struct isl_test_codegen_data *data = user;
9527 	isl_id *id;
9528 	const char *name;
9529 	int valid;
9530 
9531 	data->after++;
9532 	data->depth--;
9533 
9534 	if (data->after > data->before)
9535 		isl_die(isl_ast_node_get_ctx(node), isl_error_unknown,
9536 			"mismatch in number of for nodes",
9537 			return isl_ast_node_free(node));
9538 
9539 	id = isl_ast_node_get_annotation(node);
9540 	if (!id)
9541 		isl_die(isl_ast_node_get_ctx(node), isl_error_unknown,
9542 			"missing annotation", return isl_ast_node_free(node));
9543 
9544 	name = isl_id_get_name(id);
9545 	valid = name && atoi(name + 1) == data->depth;
9546 	isl_id_free(id);
9547 
9548 	if (!valid)
9549 		isl_die(isl_ast_node_get_ctx(node), isl_error_unknown,
9550 			"wrong annotation", return isl_ast_node_free(node));
9551 
9552 	return node;
9553 }
9554 
9555 /* Check that the before_each_for and after_each_for callbacks
9556  * are called for each for loop in the generated code,
9557  * that they are called in the right order and that the isl_id
9558  * returned from the before_each_for callback is attached to
9559  * the isl_ast_node passed to the corresponding after_each_for call.
9560  */
test_ast_gen1(isl_ctx * ctx)9561 static int test_ast_gen1(isl_ctx *ctx)
9562 {
9563 	const char *str;
9564 	isl_set *set;
9565 	isl_union_map *schedule;
9566 	isl_ast_build *build;
9567 	isl_ast_node *tree;
9568 	struct isl_test_codegen_data data;
9569 
9570 	str = "[N] -> { : N >= 10 }";
9571 	set = isl_set_read_from_str(ctx, str);
9572 	str = "[N] -> { A[i,j] -> S[8,i,3,j] : 0 <= i,j <= N; "
9573 		    "B[i,j] -> S[8,j,9,i] : 0 <= i,j <= N }";
9574 	schedule = isl_union_map_read_from_str(ctx, str);
9575 
9576 	data.before = 0;
9577 	data.after = 0;
9578 	data.depth = 0;
9579 	build = isl_ast_build_from_context(set);
9580 	build = isl_ast_build_set_before_each_for(build,
9581 			&before_for, &data);
9582 	build = isl_ast_build_set_after_each_for(build,
9583 			&after_for, &data);
9584 	tree = isl_ast_build_node_from_schedule_map(build, schedule);
9585 	isl_ast_build_free(build);
9586 	if (!tree)
9587 		return -1;
9588 
9589 	isl_ast_node_free(tree);
9590 
9591 	if (data.before != 3 || data.after != 3)
9592 		isl_die(ctx, isl_error_unknown,
9593 			"unexpected number of for nodes", return -1);
9594 
9595 	return 0;
9596 }
9597 
9598 /* Check that the AST generator handles domains that are integrally disjoint
9599  * but not rationally disjoint.
9600  */
test_ast_gen2(isl_ctx * ctx)9601 static int test_ast_gen2(isl_ctx *ctx)
9602 {
9603 	const char *str;
9604 	isl_set *set;
9605 	isl_union_map *schedule;
9606 	isl_union_map *options;
9607 	isl_ast_build *build;
9608 	isl_ast_node *tree;
9609 
9610 	str = "{ A[i,j] -> [i,j] : 0 <= i,j <= 1 }";
9611 	schedule = isl_union_map_read_from_str(ctx, str);
9612 	set = isl_set_universe(isl_space_params_alloc(ctx, 0));
9613 	build = isl_ast_build_from_context(set);
9614 
9615 	str = "{ [i,j] -> atomic[1] : i + j = 1; [i,j] -> unroll[1] : i = j }";
9616 	options = isl_union_map_read_from_str(ctx, str);
9617 	build = isl_ast_build_set_options(build, options);
9618 	tree = isl_ast_build_node_from_schedule_map(build, schedule);
9619 	isl_ast_build_free(build);
9620 	if (!tree)
9621 		return -1;
9622 	isl_ast_node_free(tree);
9623 
9624 	return 0;
9625 }
9626 
9627 /* Increment *user on each call.
9628  */
count_domains(__isl_take isl_ast_node * node,__isl_keep isl_ast_build * build,void * user)9629 static __isl_give isl_ast_node *count_domains(__isl_take isl_ast_node *node,
9630 	__isl_keep isl_ast_build *build, void *user)
9631 {
9632 	int *n = user;
9633 
9634 	(*n)++;
9635 
9636 	return node;
9637 }
9638 
9639 /* Test that unrolling tries to minimize the number of instances.
9640  * In particular, for the schedule given below, make sure it generates
9641  * 3 nodes (rather than 101).
9642  */
test_ast_gen3(isl_ctx * ctx)9643 static int test_ast_gen3(isl_ctx *ctx)
9644 {
9645 	const char *str;
9646 	isl_set *set;
9647 	isl_union_map *schedule;
9648 	isl_union_map *options;
9649 	isl_ast_build *build;
9650 	isl_ast_node *tree;
9651 	int n_domain = 0;
9652 
9653 	str = "[n] -> { A[i] -> [i] : 0 <= i <= 100 and n <= i <= n + 2 }";
9654 	schedule = isl_union_map_read_from_str(ctx, str);
9655 	set = isl_set_universe(isl_space_params_alloc(ctx, 0));
9656 
9657 	str = "{ [i] -> unroll[0] }";
9658 	options = isl_union_map_read_from_str(ctx, str);
9659 
9660 	build = isl_ast_build_from_context(set);
9661 	build = isl_ast_build_set_options(build, options);
9662 	build = isl_ast_build_set_at_each_domain(build,
9663 			&count_domains, &n_domain);
9664 	tree = isl_ast_build_node_from_schedule_map(build, schedule);
9665 	isl_ast_build_free(build);
9666 	if (!tree)
9667 		return -1;
9668 
9669 	isl_ast_node_free(tree);
9670 
9671 	if (n_domain != 3)
9672 		isl_die(ctx, isl_error_unknown,
9673 			"unexpected number of for nodes", return -1);
9674 
9675 	return 0;
9676 }
9677 
9678 /* Check that if the ast_build_exploit_nested_bounds options is set,
9679  * we do not get an outer if node in the generated AST,
9680  * while we do get such an outer if node if the options is not set.
9681  */
test_ast_gen4(isl_ctx * ctx)9682 static int test_ast_gen4(isl_ctx *ctx)
9683 {
9684 	const char *str;
9685 	isl_set *set;
9686 	isl_union_map *schedule;
9687 	isl_ast_build *build;
9688 	isl_ast_node *tree;
9689 	enum isl_ast_node_type type;
9690 	int enb;
9691 
9692 	enb = isl_options_get_ast_build_exploit_nested_bounds(ctx);
9693 	str = "[N,M] -> { A[i,j] -> [i,j] : 0 <= i <= N and 0 <= j <= M }";
9694 
9695 	isl_options_set_ast_build_exploit_nested_bounds(ctx, 1);
9696 
9697 	schedule = isl_union_map_read_from_str(ctx, str);
9698 	set = isl_set_universe(isl_space_params_alloc(ctx, 0));
9699 	build = isl_ast_build_from_context(set);
9700 	tree = isl_ast_build_node_from_schedule_map(build, schedule);
9701 	isl_ast_build_free(build);
9702 	if (!tree)
9703 		return -1;
9704 
9705 	type = isl_ast_node_get_type(tree);
9706 	isl_ast_node_free(tree);
9707 
9708 	if (type == isl_ast_node_if)
9709 		isl_die(ctx, isl_error_unknown,
9710 			"not expecting if node", return -1);
9711 
9712 	isl_options_set_ast_build_exploit_nested_bounds(ctx, 0);
9713 
9714 	schedule = isl_union_map_read_from_str(ctx, str);
9715 	set = isl_set_universe(isl_space_params_alloc(ctx, 0));
9716 	build = isl_ast_build_from_context(set);
9717 	tree = isl_ast_build_node_from_schedule_map(build, schedule);
9718 	isl_ast_build_free(build);
9719 	if (!tree)
9720 		return -1;
9721 
9722 	type = isl_ast_node_get_type(tree);
9723 	isl_ast_node_free(tree);
9724 
9725 	if (type != isl_ast_node_if)
9726 		isl_die(ctx, isl_error_unknown,
9727 			"expecting if node", return -1);
9728 
9729 	isl_options_set_ast_build_exploit_nested_bounds(ctx, enb);
9730 
9731 	return 0;
9732 }
9733 
9734 /* This function is called for each leaf in the AST generated
9735  * from test_ast_gen5.
9736  *
9737  * We finalize the AST generation by extending the outer schedule
9738  * with a zero-dimensional schedule.  If this results in any for loops,
9739  * then this means that we did not pass along enough information
9740  * about the outer schedule to the inner AST generation.
9741  */
create_leaf(__isl_take isl_ast_build * build,void * user)9742 static __isl_give isl_ast_node *create_leaf(__isl_take isl_ast_build *build,
9743 	void *user)
9744 {
9745 	isl_union_map *schedule, *extra;
9746 	isl_ast_node *tree;
9747 
9748 	schedule = isl_ast_build_get_schedule(build);
9749 	extra = isl_union_map_copy(schedule);
9750 	extra = isl_union_map_from_domain(isl_union_map_domain(extra));
9751 	schedule = isl_union_map_range_product(schedule, extra);
9752 	tree = isl_ast_build_node_from_schedule_map(build, schedule);
9753 	isl_ast_build_free(build);
9754 
9755 	if (!tree)
9756 		return NULL;
9757 
9758 	if (isl_ast_node_get_type(tree) == isl_ast_node_for)
9759 		isl_die(isl_ast_node_get_ctx(tree), isl_error_unknown,
9760 			"code should not contain any for loop",
9761 			return isl_ast_node_free(tree));
9762 
9763 	return tree;
9764 }
9765 
9766 /* Check that we do not lose any information when going back and
9767  * forth between internal and external schedule.
9768  *
9769  * In particular, we create an AST where we unroll the only
9770  * non-constant dimension in the schedule.  We therefore do
9771  * not expect any for loops in the AST.  However, older versions
9772  * of isl would not pass along enough information about the outer
9773  * schedule when performing an inner code generation from a create_leaf
9774  * callback, resulting in the inner code generation producing a for loop.
9775  */
test_ast_gen5(isl_ctx * ctx)9776 static int test_ast_gen5(isl_ctx *ctx)
9777 {
9778 	const char *str;
9779 	isl_set *set;
9780 	isl_union_map *schedule, *options;
9781 	isl_ast_build *build;
9782 	isl_ast_node *tree;
9783 
9784 	str = "{ A[] -> [1, 1, 2]; B[i] -> [1, i, 0] : i >= 1 and i <= 2 }";
9785 	schedule = isl_union_map_read_from_str(ctx, str);
9786 
9787 	str = "{ [a, b, c] -> unroll[1] : exists (e0 = [(a)/4]: "
9788 				"4e0 >= -1 + a - b and 4e0 <= -2 + a + b) }";
9789 	options = isl_union_map_read_from_str(ctx, str);
9790 
9791 	set = isl_set_universe(isl_space_params_alloc(ctx, 0));
9792 	build = isl_ast_build_from_context(set);
9793 	build = isl_ast_build_set_options(build, options);
9794         build = isl_ast_build_set_create_leaf(build, &create_leaf, NULL);
9795 	tree = isl_ast_build_node_from_schedule_map(build, schedule);
9796 	isl_ast_build_free(build);
9797 	isl_ast_node_free(tree);
9798 	if (!tree)
9799 		return -1;
9800 
9801 	return 0;
9802 }
9803 
9804 /* Check that the expression
9805  *
9806  *	[n] -> { [n/2] : n <= 0 and n % 2 = 0; [0] : n > 0 }
9807  *
9808  * is not combined into
9809  *
9810  *	min(n/2, 0)
9811  *
9812  * as this would result in n/2 being evaluated in parts of
9813  * the definition domain where n is not a multiple of 2.
9814  */
test_ast_expr(isl_ctx * ctx)9815 static int test_ast_expr(isl_ctx *ctx)
9816 {
9817 	const char *str;
9818 	isl_pw_aff *pa;
9819 	isl_ast_build *build;
9820 	isl_ast_expr *expr;
9821 	int min_max;
9822 	int is_min;
9823 
9824 	min_max = isl_options_get_ast_build_detect_min_max(ctx);
9825 	isl_options_set_ast_build_detect_min_max(ctx, 1);
9826 
9827 	str = "[n] -> { [n/2] : n <= 0 and n % 2 = 0; [0] : n > 0 }";
9828 	pa = isl_pw_aff_read_from_str(ctx, str);
9829 	build = isl_ast_build_alloc(ctx);
9830 	expr = isl_ast_build_expr_from_pw_aff(build, pa);
9831 	is_min = isl_ast_expr_get_type(expr) == isl_ast_expr_op &&
9832 		 isl_ast_expr_get_op_type(expr) == isl_ast_expr_op_min;
9833 	isl_ast_build_free(build);
9834 	isl_ast_expr_free(expr);
9835 
9836 	isl_options_set_ast_build_detect_min_max(ctx, min_max);
9837 
9838 	if (!expr)
9839 		return -1;
9840 	if (is_min)
9841 		isl_die(ctx, isl_error_unknown,
9842 			"expressions should not be combined", return -1);
9843 
9844 	return 0;
9845 }
9846 
test_ast_gen(isl_ctx * ctx)9847 static int test_ast_gen(isl_ctx *ctx)
9848 {
9849 	if (test_ast_gen1(ctx) < 0)
9850 		return -1;
9851 	if (test_ast_gen2(ctx) < 0)
9852 		return -1;
9853 	if (test_ast_gen3(ctx) < 0)
9854 		return -1;
9855 	if (test_ast_gen4(ctx) < 0)
9856 		return -1;
9857 	if (test_ast_gen5(ctx) < 0)
9858 		return -1;
9859 	if (test_ast_expr(ctx) < 0)
9860 		return -1;
9861 	return 0;
9862 }
9863 
9864 /* Check if dropping output dimensions from an isl_pw_multi_aff
9865  * works properly.
9866  */
test_pw_multi_aff(isl_ctx * ctx)9867 static int test_pw_multi_aff(isl_ctx *ctx)
9868 {
9869 	const char *str;
9870 	isl_pw_multi_aff *pma1, *pma2;
9871 	int equal;
9872 
9873 	str = "{ [i,j] -> [i+j, 4i-j] }";
9874 	pma1 = isl_pw_multi_aff_read_from_str(ctx, str);
9875 	str = "{ [i,j] -> [4i-j] }";
9876 	pma2 = isl_pw_multi_aff_read_from_str(ctx, str);
9877 
9878 	pma1 = isl_pw_multi_aff_drop_dims(pma1, isl_dim_out, 0, 1);
9879 
9880 	equal = isl_pw_multi_aff_plain_is_equal(pma1, pma2);
9881 
9882 	isl_pw_multi_aff_free(pma1);
9883 	isl_pw_multi_aff_free(pma2);
9884 	if (equal < 0)
9885 		return -1;
9886 	if (!equal)
9887 		isl_die(ctx, isl_error_unknown,
9888 			"expressions not equal", return -1);
9889 
9890 	return 0;
9891 }
9892 
9893 /* Check that we can properly parse multi piecewise affine expressions
9894  * where the piecewise affine expressions have different domains.
9895  */
test_multi_pw_aff_1(isl_ctx * ctx)9896 static int test_multi_pw_aff_1(isl_ctx *ctx)
9897 {
9898 	const char *str;
9899 	isl_set *dom, *dom2;
9900 	isl_multi_pw_aff *mpa1, *mpa2;
9901 	isl_pw_aff *pa;
9902 	int equal;
9903 	int equal_domain;
9904 
9905 	mpa1 = isl_multi_pw_aff_read_from_str(ctx, "{ [i] -> [i] }");
9906 	dom = isl_set_read_from_str(ctx, "{ [i] : i > 0 }");
9907 	mpa1 = isl_multi_pw_aff_intersect_domain(mpa1, dom);
9908 	mpa2 = isl_multi_pw_aff_read_from_str(ctx, "{ [i] -> [2i] }");
9909 	mpa2 = isl_multi_pw_aff_flat_range_product(mpa1, mpa2);
9910 	str = "{ [i] -> [(i : i > 0), 2i] }";
9911 	mpa1 = isl_multi_pw_aff_read_from_str(ctx, str);
9912 
9913 	equal = isl_multi_pw_aff_plain_is_equal(mpa1, mpa2);
9914 
9915 	pa = isl_multi_pw_aff_get_pw_aff(mpa1, 0);
9916 	dom = isl_pw_aff_domain(pa);
9917 	pa = isl_multi_pw_aff_get_pw_aff(mpa1, 1);
9918 	dom2 = isl_pw_aff_domain(pa);
9919 	equal_domain = isl_set_is_equal(dom, dom2);
9920 
9921 	isl_set_free(dom);
9922 	isl_set_free(dom2);
9923 	isl_multi_pw_aff_free(mpa1);
9924 	isl_multi_pw_aff_free(mpa2);
9925 
9926 	if (equal < 0)
9927 		return -1;
9928 	if (!equal)
9929 		isl_die(ctx, isl_error_unknown,
9930 			"expressions not equal", return -1);
9931 
9932 	if (equal_domain < 0)
9933 		return -1;
9934 	if (equal_domain)
9935 		isl_die(ctx, isl_error_unknown,
9936 			"domains unexpectedly equal", return -1);
9937 
9938 	return 0;
9939 }
9940 
9941 /* Check that the dimensions in the explicit domain
9942  * of a multi piecewise affine expression are properly
9943  * taken into account.
9944  */
test_multi_pw_aff_2(isl_ctx * ctx)9945 static int test_multi_pw_aff_2(isl_ctx *ctx)
9946 {
9947 	const char *str;
9948 	isl_bool involves1, involves2, involves3, equal;
9949 	isl_multi_pw_aff *mpa, *mpa1, *mpa2;
9950 
9951 	str = "{ A[x,y] -> B[] : x >= y }";
9952 	mpa = isl_multi_pw_aff_read_from_str(ctx, str);
9953 	involves1 = isl_multi_pw_aff_involves_dims(mpa, isl_dim_in, 0, 2);
9954 	mpa1 = isl_multi_pw_aff_copy(mpa);
9955 
9956 	mpa = isl_multi_pw_aff_insert_dims(mpa, isl_dim_in, 0, 1);
9957 	involves2 = isl_multi_pw_aff_involves_dims(mpa, isl_dim_in, 0, 1);
9958 	involves3 = isl_multi_pw_aff_involves_dims(mpa, isl_dim_in, 1, 2);
9959 	str = "{ [a,x,y] -> B[] : x >= y }";
9960 	mpa2 = isl_multi_pw_aff_read_from_str(ctx, str);
9961 	equal = isl_multi_pw_aff_plain_is_equal(mpa, mpa2);
9962 	isl_multi_pw_aff_free(mpa2);
9963 
9964 	mpa = isl_multi_pw_aff_drop_dims(mpa, isl_dim_in, 0, 1);
9965 	mpa = isl_multi_pw_aff_set_tuple_name(mpa, isl_dim_in, "A");
9966 	if (equal >= 0 && equal)
9967 		equal = isl_multi_pw_aff_plain_is_equal(mpa, mpa1);
9968 	isl_multi_pw_aff_free(mpa1);
9969 	isl_multi_pw_aff_free(mpa);
9970 
9971 	if (involves1 < 0 || involves2 < 0 || involves3 < 0 || equal < 0)
9972 		return -1;
9973 	if (!equal)
9974 		isl_die(ctx, isl_error_unknown,
9975 			"incorrect result of dimension insertion/removal",
9976 			return isl_stat_error);
9977 	if (!involves1 || involves2 || !involves3)
9978 		isl_die(ctx, isl_error_unknown,
9979 			"incorrect characterization of involved dimensions",
9980 			return isl_stat_error);
9981 
9982 	return 0;
9983 }
9984 
9985 /* Check that isl_multi_union_pw_aff_multi_val_on_domain
9986  * sets the explicit domain of a zero-dimensional result,
9987  * such that it can be converted to an isl_union_map.
9988  */
test_multi_pw_aff_3(isl_ctx * ctx)9989 static isl_stat test_multi_pw_aff_3(isl_ctx *ctx)
9990 {
9991 	isl_space *space;
9992 	isl_union_set *dom;
9993 	isl_multi_val *mv;
9994 	isl_multi_union_pw_aff *mupa;
9995 	isl_union_map *umap;
9996 
9997 	dom = isl_union_set_read_from_str(ctx, "{ A[]; B[] }");
9998 	space = isl_union_set_get_space(dom);
9999 	mv = isl_multi_val_zero(isl_space_set_from_params(space));
10000 	mupa = isl_multi_union_pw_aff_multi_val_on_domain(dom, mv);
10001 	umap = isl_union_map_from_multi_union_pw_aff(mupa);
10002 	isl_union_map_free(umap);
10003 	if (!umap)
10004 		return isl_stat_error;
10005 
10006 	return isl_stat_ok;
10007 }
10008 
10009 /* Perform some tests on multi piecewise affine expressions.
10010  */
test_multi_pw_aff(isl_ctx * ctx)10011 static int test_multi_pw_aff(isl_ctx *ctx)
10012 {
10013 	if (test_multi_pw_aff_1(ctx) < 0)
10014 		return -1;
10015 	if (test_multi_pw_aff_2(ctx) < 0)
10016 		return -1;
10017 	if (test_multi_pw_aff_3(ctx) < 0)
10018 		return -1;
10019 	return 0;
10020 }
10021 
10022 /* This is a regression test for a bug where isl_basic_map_simplify
10023  * would end up in an infinite loop.  In particular, we construct
10024  * an empty basic set that is not obviously empty.
10025  * isl_basic_set_is_empty marks the basic set as empty.
10026  * After projecting out i3, the variable can be dropped completely,
10027  * but isl_basic_map_simplify refrains from doing so if the basic set
10028  * is empty and would end up in an infinite loop if it didn't test
10029  * explicitly for empty basic maps in the outer loop.
10030  */
test_simplify_1(isl_ctx * ctx)10031 static int test_simplify_1(isl_ctx *ctx)
10032 {
10033 	const char *str;
10034 	isl_basic_set *bset;
10035 	int empty;
10036 
10037 	str = "{ [i0, i1, i2, i3] : i0 >= -2 and 6i2 <= 4 + i0 + 5i1 and "
10038 		"i2 <= 22 and 75i2 <= 111 + 13i0 + 60i1 and "
10039 		"25i2 >= 38 + 6i0 + 20i1 and i0 <= -1 and i2 >= 20 and "
10040 		"i3 >= i2 }";
10041 	bset = isl_basic_set_read_from_str(ctx, str);
10042 	empty = isl_basic_set_is_empty(bset);
10043 	bset = isl_basic_set_project_out(bset, isl_dim_set, 3, 1);
10044 	isl_basic_set_free(bset);
10045 	if (!bset)
10046 		return -1;
10047 	if (!empty)
10048 		isl_die(ctx, isl_error_unknown,
10049 			"basic set should be empty", return -1);
10050 
10051 	return 0;
10052 }
10053 
10054 /* Check that the equality in the set description below
10055  * is simplified away.
10056  */
test_simplify_2(isl_ctx * ctx)10057 static int test_simplify_2(isl_ctx *ctx)
10058 {
10059 	const char *str;
10060 	isl_basic_set *bset;
10061 	isl_bool universe;
10062 
10063 	str = "{ [a] : exists e0, e1: 32e1 = 31 + 31a + 31e0 }";
10064 	bset = isl_basic_set_read_from_str(ctx, str);
10065 	universe = isl_basic_set_plain_is_universe(bset);
10066 	isl_basic_set_free(bset);
10067 
10068 	if (universe < 0)
10069 		return -1;
10070 	if (!universe)
10071 		isl_die(ctx, isl_error_unknown,
10072 			"equality not simplified away", return -1);
10073 	return 0;
10074 }
10075 
10076 /* Some simplification tests.
10077  */
test_simplify(isl_ctx * ctx)10078 static int test_simplify(isl_ctx *ctx)
10079 {
10080 	if (test_simplify_1(ctx) < 0)
10081 		return -1;
10082 	if (test_simplify_2(ctx) < 0)
10083 		return -1;
10084 	return 0;
10085 }
10086 
10087 /* This is a regression test for a bug where isl_tab_basic_map_partial_lexopt
10088  * with gbr context would fail to disable the use of the shifted tableau
10089  * when transferring equalities for the input to the context, resulting
10090  * in invalid sample values.
10091  */
test_partial_lexmin(isl_ctx * ctx)10092 static int test_partial_lexmin(isl_ctx *ctx)
10093 {
10094 	const char *str;
10095 	isl_basic_set *bset;
10096 	isl_basic_map *bmap;
10097 	isl_map *map;
10098 
10099 	str = "{ [1, b, c, 1 - c] -> [e] : 2e <= -c and 2e >= -3 + c }";
10100 	bmap = isl_basic_map_read_from_str(ctx, str);
10101 	str = "{ [a, b, c, d] : c <= 1 and 2d >= 6 - 4b - c }";
10102 	bset = isl_basic_set_read_from_str(ctx, str);
10103 	map = isl_basic_map_partial_lexmin(bmap, bset, NULL);
10104 	isl_map_free(map);
10105 
10106 	if (!map)
10107 		return -1;
10108 
10109 	return 0;
10110 }
10111 
10112 /* Check that the variable compression performed on the existentially
10113  * quantified variables inside isl_basic_set_compute_divs is not confused
10114  * by the implicit equalities among the parameters.
10115  */
test_compute_divs(isl_ctx * ctx)10116 static int test_compute_divs(isl_ctx *ctx)
10117 {
10118 	const char *str;
10119 	isl_basic_set *bset;
10120 	isl_set *set;
10121 
10122 	str = "[a, b, c, d, e] -> { [] : exists (e0: 2d = b and a <= 124 and "
10123 		"b <= 2046 and b >= 0 and b <= 60 + 64a and 2e >= b + 2c and "
10124 		"2e >= b and 2e <= 1 + b and 2e <= 1 + b + 2c and "
10125 		"32768e0 >= -124 + a and 2097152e0 <= 60 + 64a - b) }";
10126 	bset = isl_basic_set_read_from_str(ctx, str);
10127 	set = isl_basic_set_compute_divs(bset);
10128 	isl_set_free(set);
10129 	if (!set)
10130 		return -1;
10131 
10132 	return 0;
10133 }
10134 
10135 /* Check that isl_schedule_get_map is not confused by a schedule tree
10136  * with divergent filter node parameters, as can result from a call
10137  * to isl_schedule_intersect_domain.
10138  */
test_schedule_tree(isl_ctx * ctx)10139 static int test_schedule_tree(isl_ctx *ctx)
10140 {
10141 	const char *str;
10142 	isl_union_set *uset;
10143 	isl_schedule *sched1, *sched2;
10144 	isl_union_map *umap;
10145 
10146 	uset = isl_union_set_read_from_str(ctx, "{ A[i] }");
10147 	sched1 = isl_schedule_from_domain(uset);
10148 	uset = isl_union_set_read_from_str(ctx, "{ B[] }");
10149 	sched2 = isl_schedule_from_domain(uset);
10150 
10151 	sched1 = isl_schedule_sequence(sched1, sched2);
10152 	str = "[n] -> { A[i] : 0 <= i < n; B[] }";
10153 	uset = isl_union_set_read_from_str(ctx, str);
10154 	sched1 = isl_schedule_intersect_domain(sched1, uset);
10155 	umap = isl_schedule_get_map(sched1);
10156 	isl_schedule_free(sched1);
10157 	isl_union_map_free(umap);
10158 	if (!umap)
10159 		return -1;
10160 
10161 	return 0;
10162 }
10163 
10164 /* Check that a zero-dimensional prefix schedule keeps track
10165  * of the domain and outer filters.
10166  */
test_schedule_tree_prefix(isl_ctx * ctx)10167 static int test_schedule_tree_prefix(isl_ctx *ctx)
10168 {
10169 	const char *str;
10170 	isl_bool equal;
10171 	isl_union_set *uset;
10172 	isl_union_set_list *filters;
10173 	isl_multi_union_pw_aff *mupa, *mupa2;
10174 	isl_schedule_node *node;
10175 
10176 	str = "{ S1[i,j] : 0 <= i,j < 10; S2[i,j] : 0 <= i,j < 10 }";
10177 	uset = isl_union_set_read_from_str(ctx, str);
10178 	node = isl_schedule_node_from_domain(uset);
10179 	node = isl_schedule_node_child(node, 0);
10180 
10181 	str = "{ S1[i,j] : i > j }";
10182 	uset = isl_union_set_read_from_str(ctx, str);
10183 	filters = isl_union_set_list_from_union_set(uset);
10184 	str = "{ S1[i,j] : i <= j; S2[i,j] }";
10185 	uset = isl_union_set_read_from_str(ctx, str);
10186 	filters = isl_union_set_list_add(filters, uset);
10187 	node = isl_schedule_node_insert_sequence(node, filters);
10188 
10189 	node = isl_schedule_node_child(node, 0);
10190 	node = isl_schedule_node_child(node, 0);
10191 	mupa = isl_schedule_node_get_prefix_schedule_multi_union_pw_aff(node);
10192 	str = "([] : { S1[i,j] : i > j })";
10193 	mupa2 = isl_multi_union_pw_aff_read_from_str(ctx, str);
10194 	equal = isl_multi_union_pw_aff_plain_is_equal(mupa, mupa2);
10195 	isl_multi_union_pw_aff_free(mupa2);
10196 	isl_multi_union_pw_aff_free(mupa);
10197 	isl_schedule_node_free(node);
10198 
10199 	if (equal < 0)
10200 		return -1;
10201 	if (!equal)
10202 		isl_die(ctx, isl_error_unknown, "unexpected prefix schedule",
10203 			return -1);
10204 
10205 	return 0;
10206 }
10207 
10208 /* Check that the reaching domain elements and the prefix schedule
10209  * at a leaf node are the same before and after grouping.
10210  */
test_schedule_tree_group_1(isl_ctx * ctx)10211 static int test_schedule_tree_group_1(isl_ctx *ctx)
10212 {
10213 	int equal;
10214 	const char *str;
10215 	isl_id *id;
10216 	isl_union_set *uset;
10217 	isl_multi_union_pw_aff *mupa;
10218 	isl_union_pw_multi_aff *upma1, *upma2;
10219 	isl_union_set *domain1, *domain2;
10220 	isl_union_map *umap1, *umap2;
10221 	isl_schedule_node *node;
10222 
10223 	str = "{ S1[i,j] : 0 <= i,j < 10; S2[i,j] : 0 <= i,j < 10 }";
10224 	uset = isl_union_set_read_from_str(ctx, str);
10225 	node = isl_schedule_node_from_domain(uset);
10226 	node = isl_schedule_node_child(node, 0);
10227 	str = "[{ S1[i,j] -> [i]; S2[i,j] -> [9 - i] }]";
10228 	mupa = isl_multi_union_pw_aff_read_from_str(ctx, str);
10229 	node = isl_schedule_node_insert_partial_schedule(node, mupa);
10230 	node = isl_schedule_node_child(node, 0);
10231 	str = "[{ S1[i,j] -> [j]; S2[i,j] -> [j] }]";
10232 	mupa = isl_multi_union_pw_aff_read_from_str(ctx, str);
10233 	node = isl_schedule_node_insert_partial_schedule(node, mupa);
10234 	node = isl_schedule_node_child(node, 0);
10235 	umap1 = isl_schedule_node_get_prefix_schedule_union_map(node);
10236 	upma1 = isl_schedule_node_get_prefix_schedule_union_pw_multi_aff(node);
10237 	domain1 = isl_schedule_node_get_domain(node);
10238 	id = isl_id_alloc(ctx, "group", NULL);
10239 	node = isl_schedule_node_parent(node);
10240 	node = isl_schedule_node_group(node, id);
10241 	node = isl_schedule_node_child(node, 0);
10242 	umap2 = isl_schedule_node_get_prefix_schedule_union_map(node);
10243 	upma2 = isl_schedule_node_get_prefix_schedule_union_pw_multi_aff(node);
10244 	domain2 = isl_schedule_node_get_domain(node);
10245 	equal = isl_union_pw_multi_aff_plain_is_equal(upma1, upma2);
10246 	if (equal >= 0 && equal)
10247 		equal = isl_union_set_is_equal(domain1, domain2);
10248 	if (equal >= 0 && equal)
10249 		equal = isl_union_map_is_equal(umap1, umap2);
10250 	isl_union_map_free(umap1);
10251 	isl_union_map_free(umap2);
10252 	isl_union_set_free(domain1);
10253 	isl_union_set_free(domain2);
10254 	isl_union_pw_multi_aff_free(upma1);
10255 	isl_union_pw_multi_aff_free(upma2);
10256 	isl_schedule_node_free(node);
10257 
10258 	if (equal < 0)
10259 		return -1;
10260 	if (!equal)
10261 		isl_die(ctx, isl_error_unknown,
10262 			"expressions not equal", return -1);
10263 
10264 	return 0;
10265 }
10266 
10267 /* Check that we can have nested groupings and that the union map
10268  * schedule representation is the same before and after the grouping.
10269  * Note that after the grouping, the union map representation contains
10270  * the domain constraints from the ranges of the expansion nodes,
10271  * while they are missing from the union map representation of
10272  * the tree without expansion nodes.
10273  *
10274  * Also check that the global expansion is as expected.
10275  */
test_schedule_tree_group_2(isl_ctx * ctx)10276 static int test_schedule_tree_group_2(isl_ctx *ctx)
10277 {
10278 	int equal, equal_expansion;
10279 	const char *str;
10280 	isl_id *id;
10281 	isl_union_set *uset;
10282 	isl_union_map *umap1, *umap2;
10283 	isl_union_map *expansion1, *expansion2;
10284 	isl_union_set_list *filters;
10285 	isl_multi_union_pw_aff *mupa;
10286 	isl_schedule *schedule;
10287 	isl_schedule_node *node;
10288 
10289 	str = "{ S1[i,j] : 0 <= i,j < 10; S2[i,j] : 0 <= i,j < 10; "
10290 		"S3[i,j] : 0 <= i,j < 10 }";
10291 	uset = isl_union_set_read_from_str(ctx, str);
10292 	node = isl_schedule_node_from_domain(uset);
10293 	node = isl_schedule_node_child(node, 0);
10294 	str = "[{ S1[i,j] -> [i]; S2[i,j] -> [i]; S3[i,j] -> [i] }]";
10295 	mupa = isl_multi_union_pw_aff_read_from_str(ctx, str);
10296 	node = isl_schedule_node_insert_partial_schedule(node, mupa);
10297 	node = isl_schedule_node_child(node, 0);
10298 	str = "{ S1[i,j] }";
10299 	uset = isl_union_set_read_from_str(ctx, str);
10300 	filters = isl_union_set_list_from_union_set(uset);
10301 	str = "{ S2[i,j]; S3[i,j] }";
10302 	uset = isl_union_set_read_from_str(ctx, str);
10303 	filters = isl_union_set_list_add(filters, uset);
10304 	node = isl_schedule_node_insert_sequence(node, filters);
10305 	node = isl_schedule_node_child(node, 1);
10306 	node = isl_schedule_node_child(node, 0);
10307 	str = "{ S2[i,j] }";
10308 	uset = isl_union_set_read_from_str(ctx, str);
10309 	filters = isl_union_set_list_from_union_set(uset);
10310 	str = "{ S3[i,j] }";
10311 	uset = isl_union_set_read_from_str(ctx, str);
10312 	filters = isl_union_set_list_add(filters, uset);
10313 	node = isl_schedule_node_insert_sequence(node, filters);
10314 
10315 	schedule = isl_schedule_node_get_schedule(node);
10316 	umap1 = isl_schedule_get_map(schedule);
10317 	uset = isl_schedule_get_domain(schedule);
10318 	umap1 = isl_union_map_intersect_domain(umap1, uset);
10319 	isl_schedule_free(schedule);
10320 
10321 	node = isl_schedule_node_parent(node);
10322 	node = isl_schedule_node_parent(node);
10323 	id = isl_id_alloc(ctx, "group1", NULL);
10324 	node = isl_schedule_node_group(node, id);
10325 	node = isl_schedule_node_child(node, 1);
10326 	node = isl_schedule_node_child(node, 0);
10327 	id = isl_id_alloc(ctx, "group2", NULL);
10328 	node = isl_schedule_node_group(node, id);
10329 
10330 	schedule = isl_schedule_node_get_schedule(node);
10331 	umap2 = isl_schedule_get_map(schedule);
10332 	isl_schedule_free(schedule);
10333 
10334 	node = isl_schedule_node_root(node);
10335 	node = isl_schedule_node_child(node, 0);
10336 	expansion1 = isl_schedule_node_get_subtree_expansion(node);
10337 	isl_schedule_node_free(node);
10338 
10339 	str = "{ group1[i] -> S1[i,j] : 0 <= i,j < 10; "
10340 		"group1[i] -> S2[i,j] : 0 <= i,j < 10; "
10341 		"group1[i] -> S3[i,j] : 0 <= i,j < 10 }";
10342 
10343 	expansion2 = isl_union_map_read_from_str(ctx, str);
10344 
10345 	equal = isl_union_map_is_equal(umap1, umap2);
10346 	equal_expansion = isl_union_map_is_equal(expansion1, expansion2);
10347 
10348 	isl_union_map_free(umap1);
10349 	isl_union_map_free(umap2);
10350 	isl_union_map_free(expansion1);
10351 	isl_union_map_free(expansion2);
10352 
10353 	if (equal < 0 || equal_expansion < 0)
10354 		return -1;
10355 	if (!equal)
10356 		isl_die(ctx, isl_error_unknown,
10357 			"expressions not equal", return -1);
10358 	if (!equal_expansion)
10359 		isl_die(ctx, isl_error_unknown,
10360 			"unexpected expansion", return -1);
10361 
10362 	return 0;
10363 }
10364 
10365 /* Some tests for the isl_schedule_node_group function.
10366  */
test_schedule_tree_group(isl_ctx * ctx)10367 static int test_schedule_tree_group(isl_ctx *ctx)
10368 {
10369 	if (test_schedule_tree_group_1(ctx) < 0)
10370 		return -1;
10371 	if (test_schedule_tree_group_2(ctx) < 0)
10372 		return -1;
10373 	return 0;
10374 }
10375 
10376 struct {
10377 	const char *set;
10378 	const char *dual;
10379 } coef_tests[] = {
10380 	{ "{ rat: [i] : 0 <= i <= 10 }",
10381 	  "{ rat: coefficients[[cst] -> [a]] : cst >= 0 and 10a + cst >= 0 }" },
10382 	{ "{ rat: [i] : FALSE }",
10383 	  "{ rat: coefficients[[cst] -> [a]] }" },
10384 	{ "{ rat: [i] : }",
10385 	  "{ rat: coefficients[[cst] -> [0]] : cst >= 0 }" },
10386 	{ "{ [0:,1,2:3] }",
10387 	  "{ rat: coefficients[[c_cst] -> [a, b, c]] : "
10388 		"a >= 0 and 2c >= -c_cst - b and 3c >= -c_cst - b }" },
10389 	{ "[M, N] -> { [x = (1 - N):-1, -4x:(M - 4x)] }",
10390 	  "{ rat: coefficients[[c_cst, c_M = 0:, c_N = 0:] -> [a, b = -c_M:]] :"
10391 		"4b >= -c_N + a and 4b >= -c_cst - 2c_N + a }" },
10392 	{ "{ rat : [x, y] : 1 <= 2x <= 9 and 2 <= 3y <= 16 }",
10393 	  "{ rat: coefficients[[c_cst] -> [c_x, c_y]] : "
10394 		"4c_y >= -6c_cst - 3c_x and 4c_y >= -6c_cst - 27c_x and "
10395 		"32c_y >= -6c_cst - 3c_x and 32c_y >= -6c_cst - 27c_x }" },
10396 	{ "{ [x, y, z] : 3y <= 2x - 2 and y >= -2 + 2x and 2y >= 2 - x }",
10397 	  "{ rat: coefficients[[cst] -> [a, b, c]] }" },
10398 };
10399 
10400 struct {
10401 	const char *set;
10402 	const char *dual;
10403 } sol_tests[] = {
10404 	{ "{ rat: coefficients[[cst] -> [a]] : cst >= 0 and 10a + cst >= 0 }",
10405 	  "{ rat: [i] : 0 <= i <= 10 }" },
10406 	{ "{ rat: coefficients[[cst] -> [a]] : FALSE }",
10407 	  "{ rat: [i] }" },
10408 	{ "{ rat: coefficients[[cst] -> [a]] }",
10409 	  "{ rat: [i] : FALSE }" },
10410 };
10411 
10412 /* Test the basic functionality of isl_basic_set_coefficients and
10413  * isl_basic_set_solutions.
10414  */
test_dual(isl_ctx * ctx)10415 static int test_dual(isl_ctx *ctx)
10416 {
10417 	int i;
10418 
10419 	for (i = 0; i < ARRAY_SIZE(coef_tests); ++i) {
10420 		int equal;
10421 		isl_basic_set *bset1, *bset2;
10422 
10423 		bset1 = isl_basic_set_read_from_str(ctx, coef_tests[i].set);
10424 		bset2 = isl_basic_set_read_from_str(ctx, coef_tests[i].dual);
10425 		bset1 = isl_basic_set_coefficients(bset1);
10426 		equal = isl_basic_set_is_equal(bset1, bset2);
10427 		isl_basic_set_free(bset1);
10428 		isl_basic_set_free(bset2);
10429 		if (equal < 0)
10430 			return -1;
10431 		if (!equal)
10432 			isl_die(ctx, isl_error_unknown,
10433 				"incorrect dual", return -1);
10434 	}
10435 
10436 	for (i = 0; i < ARRAY_SIZE(sol_tests); ++i) {
10437 		int equal;
10438 		isl_basic_set *bset1, *bset2;
10439 
10440 		bset1 = isl_basic_set_read_from_str(ctx, sol_tests[i].set);
10441 		bset2 = isl_basic_set_read_from_str(ctx, sol_tests[i].dual);
10442 		bset1 = isl_basic_set_solutions(bset1);
10443 		equal = isl_basic_set_is_equal(bset1, bset2);
10444 		isl_basic_set_free(bset1);
10445 		isl_basic_set_free(bset2);
10446 		if (equal < 0)
10447 			return -1;
10448 		if (!equal)
10449 			isl_die(ctx, isl_error_unknown,
10450 				"incorrect dual", return -1);
10451 	}
10452 
10453 	return 0;
10454 }
10455 
10456 struct {
10457 	int scale_tile;
10458 	int shift_point;
10459 	const char *domain;
10460 	const char *schedule;
10461 	const char *sizes;
10462 	const char *tile;
10463 	const char *point;
10464 } tile_tests[] = {
10465 	{ 0, 0, "[n] -> { S[i,j] : 0 <= i,j < n }",
10466 	  "[{ S[i,j] -> [i] }, { S[i,j] -> [j] }]",
10467 	  "{ [32,32] }",
10468 	  "[{ S[i,j] -> [floor(i/32)] }, { S[i,j] -> [floor(j/32)] }]",
10469 	  "[{ S[i,j] -> [i] }, { S[i,j] -> [j] }]",
10470 	},
10471 	{ 1, 0, "[n] -> { S[i,j] : 0 <= i,j < n }",
10472 	  "[{ S[i,j] -> [i] }, { S[i,j] -> [j] }]",
10473 	  "{ [32,32] }",
10474 	  "[{ S[i,j] -> [32*floor(i/32)] }, { S[i,j] -> [32*floor(j/32)] }]",
10475 	  "[{ S[i,j] -> [i] }, { S[i,j] -> [j] }]",
10476 	},
10477 	{ 0, 1, "[n] -> { S[i,j] : 0 <= i,j < n }",
10478 	  "[{ S[i,j] -> [i] }, { S[i,j] -> [j] }]",
10479 	  "{ [32,32] }",
10480 	  "[{ S[i,j] -> [floor(i/32)] }, { S[i,j] -> [floor(j/32)] }]",
10481 	  "[{ S[i,j] -> [i%32] }, { S[i,j] -> [j%32] }]",
10482 	},
10483 	{ 1, 1, "[n] -> { S[i,j] : 0 <= i,j < n }",
10484 	  "[{ S[i,j] -> [i] }, { S[i,j] -> [j] }]",
10485 	  "{ [32,32] }",
10486 	  "[{ S[i,j] -> [32*floor(i/32)] }, { S[i,j] -> [32*floor(j/32)] }]",
10487 	  "[{ S[i,j] -> [i%32] }, { S[i,j] -> [j%32] }]",
10488 	},
10489 };
10490 
10491 /* Basic tiling tests.  Create a schedule tree with a domain and a band node,
10492  * tile the band and then check if the tile and point bands have the
10493  * expected partial schedule.
10494  */
test_tile(isl_ctx * ctx)10495 static int test_tile(isl_ctx *ctx)
10496 {
10497 	int i;
10498 	int scale;
10499 	int shift;
10500 
10501 	scale = isl_options_get_tile_scale_tile_loops(ctx);
10502 	shift = isl_options_get_tile_shift_point_loops(ctx);
10503 
10504 	for (i = 0; i < ARRAY_SIZE(tile_tests); ++i) {
10505 		int opt;
10506 		int equal;
10507 		const char *str;
10508 		isl_union_set *domain;
10509 		isl_multi_union_pw_aff *mupa, *mupa2;
10510 		isl_schedule_node *node;
10511 		isl_multi_val *sizes;
10512 
10513 		opt = tile_tests[i].scale_tile;
10514 		isl_options_set_tile_scale_tile_loops(ctx, opt);
10515 		opt = tile_tests[i].shift_point;
10516 		isl_options_set_tile_shift_point_loops(ctx, opt);
10517 
10518 		str = tile_tests[i].domain;
10519 		domain = isl_union_set_read_from_str(ctx, str);
10520 		node = isl_schedule_node_from_domain(domain);
10521 		node = isl_schedule_node_child(node, 0);
10522 		str = tile_tests[i].schedule;
10523 		mupa = isl_multi_union_pw_aff_read_from_str(ctx, str);
10524 		node = isl_schedule_node_insert_partial_schedule(node, mupa);
10525 		str = tile_tests[i].sizes;
10526 		sizes = isl_multi_val_read_from_str(ctx, str);
10527 		node = isl_schedule_node_band_tile(node, sizes);
10528 
10529 		str = tile_tests[i].tile;
10530 		mupa = isl_multi_union_pw_aff_read_from_str(ctx, str);
10531 		mupa2 = isl_schedule_node_band_get_partial_schedule(node);
10532 		equal = isl_multi_union_pw_aff_plain_is_equal(mupa, mupa2);
10533 		isl_multi_union_pw_aff_free(mupa);
10534 		isl_multi_union_pw_aff_free(mupa2);
10535 
10536 		node = isl_schedule_node_child(node, 0);
10537 
10538 		str = tile_tests[i].point;
10539 		mupa = isl_multi_union_pw_aff_read_from_str(ctx, str);
10540 		mupa2 = isl_schedule_node_band_get_partial_schedule(node);
10541 		if (equal >= 0 && equal)
10542 			equal = isl_multi_union_pw_aff_plain_is_equal(mupa,
10543 									mupa2);
10544 		isl_multi_union_pw_aff_free(mupa);
10545 		isl_multi_union_pw_aff_free(mupa2);
10546 
10547 		isl_schedule_node_free(node);
10548 
10549 		if (equal < 0)
10550 			return -1;
10551 		if (!equal)
10552 			isl_die(ctx, isl_error_unknown,
10553 				"unexpected result", return -1);
10554 	}
10555 
10556 	isl_options_set_tile_scale_tile_loops(ctx, scale);
10557 	isl_options_set_tile_shift_point_loops(ctx, shift);
10558 
10559 	return 0;
10560 }
10561 
10562 /* Check that the domain hash of a space is equal to the hash
10563  * of the domain of the space.
10564  */
test_domain_hash(isl_ctx * ctx)10565 static int test_domain_hash(isl_ctx *ctx)
10566 {
10567 	isl_map *map;
10568 	isl_space *space;
10569 	uint32_t hash1, hash2;
10570 
10571 	map = isl_map_read_from_str(ctx, "[n] -> { A[B[x] -> C[]] -> D[] }");
10572 	space = isl_map_get_space(map);
10573 	isl_map_free(map);
10574 	hash1 = isl_space_get_domain_hash(space);
10575 	space = isl_space_domain(space);
10576 	hash2 = isl_space_get_hash(space);
10577 	isl_space_free(space);
10578 
10579 	if (!space)
10580 		return -1;
10581 	if (hash1 != hash2)
10582 		isl_die(ctx, isl_error_unknown,
10583 			"domain hash not equal to hash of domain", return -1);
10584 
10585 	return 0;
10586 }
10587 
10588 /* Check that a universe basic set that is not obviously equal to the universe
10589  * is still recognized as being equal to the universe.
10590  */
test_universe(isl_ctx * ctx)10591 static int test_universe(isl_ctx *ctx)
10592 {
10593 	const char *s;
10594 	isl_basic_set *bset;
10595 	isl_bool is_univ;
10596 
10597 	s = "{ [] : exists x, y : 3y <= 2x and y >= -3 + 2x and 2y >= 2 - x }";
10598 	bset = isl_basic_set_read_from_str(ctx, s);
10599 	is_univ = isl_basic_set_is_universe(bset);
10600 	isl_basic_set_free(bset);
10601 
10602 	if (is_univ < 0)
10603 		return -1;
10604 	if (!is_univ)
10605 		isl_die(ctx, isl_error_unknown,
10606 			"not recognized as universe set", return -1);
10607 
10608 	return 0;
10609 }
10610 
10611 /* Sets for which chambers are computed and checked.
10612  */
10613 const char *chambers_tests[] = {
10614 	"[A, B, C] -> { [x, y, z] : x >= 0 and y >= 0 and y <= A - x and "
10615 				"z >= 0 and z <= C - y and z <= B - x - y }",
10616 };
10617 
10618 /* Add the domain of "cell" to "cells".
10619  */
add_cell(__isl_take isl_cell * cell,void * user)10620 static isl_stat add_cell(__isl_take isl_cell *cell, void *user)
10621 {
10622 	isl_basic_set_list **cells = user;
10623 	isl_basic_set *dom;
10624 
10625 	dom = isl_cell_get_domain(cell);
10626 	isl_cell_free(cell);
10627 	*cells = isl_basic_set_list_add(*cells, dom);
10628 
10629 	return *cells ? isl_stat_ok : isl_stat_error;
10630 }
10631 
10632 /* Check that the elements of "list" are pairwise disjoint.
10633  */
check_pairwise_disjoint(__isl_keep isl_basic_set_list * list)10634 static isl_stat check_pairwise_disjoint(__isl_keep isl_basic_set_list *list)
10635 {
10636 	int i, j;
10637 	isl_size n;
10638 
10639 	n = isl_basic_set_list_n_basic_set(list);
10640 	if (n < 0)
10641 		return isl_stat_error;
10642 
10643 	for (i = 0; i < n; ++i) {
10644 		isl_basic_set *bset_i;
10645 
10646 		bset_i = isl_basic_set_list_get_basic_set(list, i);
10647 		for (j = i + 1; j < n; ++j) {
10648 			isl_basic_set *bset_j;
10649 			isl_bool disjoint;
10650 
10651 			bset_j = isl_basic_set_list_get_basic_set(list, j);
10652 			disjoint = isl_basic_set_is_disjoint(bset_i, bset_j);
10653 			isl_basic_set_free(bset_j);
10654 			if (!disjoint)
10655 				isl_die(isl_basic_set_list_get_ctx(list),
10656 					isl_error_unknown, "not disjoint",
10657 					break);
10658 			if (disjoint < 0 || !disjoint)
10659 				break;
10660 		}
10661 		isl_basic_set_free(bset_i);
10662 		if (j < n)
10663 			return isl_stat_error;
10664 	}
10665 
10666 	return isl_stat_ok;
10667 }
10668 
10669 /* Check that the chambers computed by isl_vertices_foreach_disjoint_cell
10670  * are pairwise disjoint.
10671  */
test_chambers(isl_ctx * ctx)10672 static int test_chambers(isl_ctx *ctx)
10673 {
10674 	int i;
10675 
10676 	for (i = 0; i < ARRAY_SIZE(chambers_tests); ++i) {
10677 		isl_basic_set *bset;
10678 		isl_vertices *vertices;
10679 		isl_basic_set_list *cells;
10680 		isl_stat ok;
10681 
10682 		bset = isl_basic_set_read_from_str(ctx, chambers_tests[i]);
10683 		vertices = isl_basic_set_compute_vertices(bset);
10684 		cells = isl_basic_set_list_alloc(ctx, 0);
10685 		if (isl_vertices_foreach_disjoint_cell(vertices, &add_cell,
10686 							&cells) < 0)
10687 			cells = isl_basic_set_list_free(cells);
10688 		ok = check_pairwise_disjoint(cells);
10689 		isl_basic_set_list_free(cells);
10690 		isl_vertices_free(vertices);
10691 		isl_basic_set_free(bset);
10692 
10693 		if (ok < 0)
10694 			return -1;
10695 	}
10696 
10697 	return 0;
10698 }
10699 
10700 struct {
10701 	const char *name;
10702 	int (*fn)(isl_ctx *ctx);
10703 } tests [] = {
10704 	{ "universe", &test_universe },
10705 	{ "domain hash", &test_domain_hash },
10706 	{ "dual", &test_dual },
10707 	{ "dependence analysis", &test_flow },
10708 	{ "val", &test_val },
10709 	{ "compute divs", &test_compute_divs },
10710 	{ "partial lexmin", &test_partial_lexmin },
10711 	{ "simplify", &test_simplify },
10712 	{ "curry", &test_curry },
10713 	{ "piecewise multi affine expressions", &test_pw_multi_aff },
10714 	{ "multi piecewise affine expressions", &test_multi_pw_aff },
10715 	{ "conversion", &test_conversion },
10716 	{ "list", &test_list },
10717 	{ "align parameters", &test_align_parameters },
10718 	{ "drop unused parameters", &test_drop_unused_parameters },
10719 	{ "preimage", &test_preimage },
10720 	{ "pullback", &test_pullback },
10721 	{ "AST", &test_ast },
10722 	{ "AST build", &test_ast_build },
10723 	{ "AST generation", &test_ast_gen },
10724 	{ "eliminate", &test_eliminate },
10725 	{ "deltas_map", &test_deltas_map },
10726 	{ "residue class", &test_residue_class },
10727 	{ "div", &test_div },
10728 	{ "slice", &test_slice },
10729 	{ "fixed power", &test_fixed_power },
10730 	{ "sample", &test_sample },
10731 	{ "output", &test_output },
10732 	{ "vertices", &test_vertices },
10733 	{ "chambers", &test_chambers },
10734 	{ "fixed", &test_fixed },
10735 	{ "equal", &test_equal },
10736 	{ "disjoint", &test_disjoint },
10737 	{ "product", &test_product },
10738 	{ "dim_max", &test_dim_max },
10739 	{ "affine", &test_aff },
10740 	{ "injective", &test_injective },
10741 	{ "schedule (whole component)", &test_schedule_whole },
10742 	{ "schedule (incremental)", &test_schedule_incremental },
10743 	{ "schedule tree", &test_schedule_tree },
10744 	{ "schedule tree prefix", &test_schedule_tree_prefix },
10745 	{ "schedule tree grouping", &test_schedule_tree_group },
10746 	{ "tile", &test_tile },
10747 	{ "union map", &test_union_map },
10748 	{ "union_pw", &test_union_pw },
10749 	{ "locus", &test_locus },
10750 	{ "eval", &test_eval },
10751 	{ "parse", &test_parse },
10752 	{ "single-valued", &test_sv },
10753 	{ "recession cone", &test_recession_cone },
10754 	{ "affine hull", &test_affine_hull },
10755 	{ "simple_hull", &test_simple_hull },
10756 	{ "box hull", &test_box_hull },
10757 	{ "coalesce", &test_coalesce },
10758 	{ "factorize", &test_factorize },
10759 	{ "subset", &test_subset },
10760 	{ "subtract", &test_subtract },
10761 	{ "intersect", &test_intersect },
10762 	{ "lexmin", &test_lexmin },
10763 	{ "min", &test_min },
10764 	{ "gist", &test_gist },
10765 	{ "piecewise quasi-polynomials", &test_pwqp },
10766 	{ "lift", &test_lift },
10767 	{ "bind parameters", &test_bind },
10768 	{ "unbind parameters", &test_unbind },
10769 	{ "bound", &test_bound },
10770 	{ "get lists", &test_get_list },
10771 	{ "union", &test_union },
10772 	{ "split periods", &test_split_periods },
10773 	{ "lexicographic order", &test_lex },
10774 	{ "bijectivity", &test_bijective },
10775 	{ "dataflow analysis", &test_dep },
10776 	{ "reading", &test_read },
10777 	{ "bounded", &test_bounded },
10778 	{ "construction", &test_construction },
10779 	{ "dimension manipulation", &test_dim },
10780 	{ "map application", &test_application },
10781 	{ "convex hull", &test_convex_hull },
10782 	{ "transitive closure", &test_closure },
10783 	{ "isl_bool", &test_isl_bool},
10784 };
10785 
main(int argc,char ** argv)10786 int main(int argc, char **argv)
10787 {
10788 	int i;
10789 	struct isl_ctx *ctx;
10790 	struct isl_options *options;
10791 
10792 	options = isl_options_new_with_defaults();
10793 	assert(options);
10794 	argc = isl_options_parse(options, argc, argv, ISL_ARG_ALL);
10795 
10796 	ctx = isl_ctx_alloc_with_options(&isl_options_args, options);
10797 	for (i = 0; i < ARRAY_SIZE(tests); ++i) {
10798 		printf("%s\n", tests[i].name);
10799 		if (tests[i].fn(ctx) < 0)
10800 			goto error;
10801 	}
10802 	isl_ctx_free(ctx);
10803 	return 0;
10804 error:
10805 	isl_ctx_free(ctx);
10806 	return -1;
10807 }
10808