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 *dim;
547 	isl_local_space *ls;
548 	isl_basic_set *bset;
549 	isl_constraint *c;
550 
551 	dim = isl_space_set_alloc(ctx, 1, 1);
552 	bset = isl_basic_set_universe(isl_space_copy(dim));
553 	ls = isl_local_space_from_space(dim);
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 *dim;
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 	dim = isl_space_set_alloc(ctx, 0, 3);
959 	bset = isl_basic_set_universe(isl_space_copy(dim));
960 	ls = isl_local_space_from_space(dim);
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 	dim = isl_space_set_alloc(ctx, 0, 3);
982 	bset = isl_basic_set_universe(isl_space_copy(dim));
983 	ls = isl_local_space_from_space(dim);
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 	dim = isl_space_set_alloc(ctx, 0, 3);
1005 	bset = isl_basic_set_universe(isl_space_copy(dim));
1006 	ls = isl_local_space_from_space(dim);
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 	dim = isl_space_set_alloc(ctx, 0, 3);
1028 	bset = isl_basic_set_universe(isl_space_copy(dim));
1029 	ls = isl_local_space_from_space(dim);
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 	dim = isl_space_set_alloc(ctx, 0, 3);
1051 	bset = isl_basic_set_universe(isl_space_copy(dim));
1052 	ls = isl_local_space_from_space(dim);
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 	dim = isl_space_set_alloc(ctx, 0, 3);
1072 	bset = isl_basic_set_universe(isl_space_copy(dim));
1073 	ls = isl_local_space_from_space(dim);
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 	dim = isl_space_set_alloc(ctx, 0, 4);
1102 	bset = isl_basic_set_universe(isl_space_copy(dim));
1103 	ls = isl_local_space_from_space(dim);
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 	dim = isl_space_set_alloc(ctx, 0, 5);
1123 	bset = isl_basic_set_universe(isl_space_copy(dim));
1124 	ls = isl_local_space_from_space(dim);
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 	dim = isl_space_set_alloc(ctx, 0, 4);
1150 	bset = isl_basic_set_universe(isl_space_copy(dim));
1151 	ls = isl_local_space_from_space(dim);
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 	dim = isl_space_set_alloc(ctx, 0, 3);
1176 	bset = isl_basic_set_universe(isl_space_copy(dim));
1177 	ls = isl_local_space_from_space(dim);
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 /* Pairs of maps and the corresponding expected results of
1378  * isl_map_plain_unshifted_simple_hull.
1379  */
1380 struct {
1381 	const char *map;
1382 	const char *hull;
1383 } plain_unshifted_simple_hull_tests[] = {
1384 	{ "{ [i] -> [j] : i >= 1 and j >= 1 or i >= 2 and j <= 10 }",
1385 	  "{ [i] -> [j] : i >= 1 }" },
1386 	{ "{ [n] -> [i,j,k] : (i mod 3 = 2 and j mod 4 = 2) or "
1387 		"(j mod 4 = 2 and k mod 6 = n) }",
1388 	  "{ [n] -> [i,j,k] : j mod 4 = 2 }" },
1389 };
1390 
1391 /* Basic tests for isl_map_plain_unshifted_simple_hull.
1392  */
test_plain_unshifted_simple_hull(isl_ctx * ctx)1393 static int test_plain_unshifted_simple_hull(isl_ctx *ctx)
1394 {
1395 	int i;
1396 	isl_map *map;
1397 	isl_basic_map *hull, *expected;
1398 	isl_bool equal;
1399 
1400 	for (i = 0; i < ARRAY_SIZE(plain_unshifted_simple_hull_tests); ++i) {
1401 		const char *str;
1402 		str = plain_unshifted_simple_hull_tests[i].map;
1403 		map = isl_map_read_from_str(ctx, str);
1404 		str = plain_unshifted_simple_hull_tests[i].hull;
1405 		expected = isl_basic_map_read_from_str(ctx, str);
1406 		hull = isl_map_plain_unshifted_simple_hull(map);
1407 		equal = isl_basic_map_is_equal(hull, expected);
1408 		isl_basic_map_free(hull);
1409 		isl_basic_map_free(expected);
1410 		if (equal < 0)
1411 			return -1;
1412 		if (!equal)
1413 			isl_die(ctx, isl_error_unknown, "unexpected hull",
1414 				return -1);
1415 	}
1416 
1417 	return 0;
1418 }
1419 
1420 /* Pairs of sets and the corresponding expected results of
1421  * isl_set_unshifted_simple_hull.
1422  */
1423 struct {
1424 	const char *set;
1425 	const char *hull;
1426 } unshifted_simple_hull_tests[] = {
1427 	{ "{ [0,x,y] : x <= -1; [1,x,y] : x <= y <= -x; [2,x,y] : x <= 1 }",
1428 	  "{ [t,x,y] : 0 <= t <= 2 and x <= 1 }" },
1429 };
1430 
1431 /* Basic tests for isl_set_unshifted_simple_hull.
1432  */
test_unshifted_simple_hull(isl_ctx * ctx)1433 static int test_unshifted_simple_hull(isl_ctx *ctx)
1434 {
1435 	int i;
1436 	isl_set *set;
1437 	isl_basic_set *hull, *expected;
1438 	isl_bool equal;
1439 
1440 	for (i = 0; i < ARRAY_SIZE(unshifted_simple_hull_tests); ++i) {
1441 		const char *str;
1442 		str = unshifted_simple_hull_tests[i].set;
1443 		set = isl_set_read_from_str(ctx, str);
1444 		str = unshifted_simple_hull_tests[i].hull;
1445 		expected = isl_basic_set_read_from_str(ctx, str);
1446 		hull = isl_set_unshifted_simple_hull(set);
1447 		equal = isl_basic_set_is_equal(hull, expected);
1448 		isl_basic_set_free(hull);
1449 		isl_basic_set_free(expected);
1450 		if (equal < 0)
1451 			return -1;
1452 		if (!equal)
1453 			isl_die(ctx, isl_error_unknown, "unexpected hull",
1454 				return -1);
1455 	}
1456 
1457 	return 0;
1458 }
1459 
test_simple_hull(struct isl_ctx * ctx)1460 static int test_simple_hull(struct isl_ctx *ctx)
1461 {
1462 	const char *str;
1463 	isl_set *set;
1464 	isl_basic_set *bset;
1465 	isl_bool is_empty;
1466 
1467 	str = "{ [x, y] : 3y <= 2x and y >= -2 + 2x and 2y >= 2 - x;"
1468 		"[y, x] : 3y <= 2x and y >= -2 + 2x and 2y >= 2 - x }";
1469 	set = isl_set_read_from_str(ctx, str);
1470 	bset = isl_set_simple_hull(set);
1471 	is_empty = isl_basic_set_is_empty(bset);
1472 	isl_basic_set_free(bset);
1473 
1474 	if (is_empty == isl_bool_error)
1475 		return -1;
1476 
1477 	if (is_empty == isl_bool_false)
1478 		isl_die(ctx, isl_error_unknown, "Empty set should be detected",
1479 			return -1);
1480 
1481 	if (test_plain_unshifted_simple_hull(ctx) < 0)
1482 		return -1;
1483 	if (test_unshifted_simple_hull(ctx) < 0)
1484 		return -1;
1485 
1486 	return 0;
1487 }
1488 
1489 /* Inputs for isl_set_get_simple_fixed_box_hull tests.
1490  * "set" is the input set.
1491  * "offset" is the expected box offset.
1492  * "size" is the expected box size.
1493  */
1494 static struct {
1495 	const char *set;
1496 	const char *offset;
1497 	const char *size;
1498 } box_hull_tests[] = {
1499 	{ "{ S[x, y] : 0 <= x, y < 10 }", "{ S[0, 0] }", "{ S[10, 10] }" },
1500 	{ "[N] -> { S[x, y] : N <= x, y < N + 10 }",
1501 	  "[N] -> { S[N, N] }", "{ S[10, 10] }" },
1502 	{ "{ S[x, y] : 0 <= x + y, x - y < 10 }",
1503 	  "{ S[0, -4] }", "{ S[10, 9] }" },
1504 };
1505 
1506 /* Perform basic isl_set_get_simple_fixed_box_hull tests.
1507  */
test_box_hull(struct isl_ctx * ctx)1508 static int test_box_hull(struct isl_ctx *ctx)
1509 {
1510 	int i;
1511 
1512 	for (i = 0; i < ARRAY_SIZE(box_hull_tests); ++i) {
1513 		const char *str;
1514 		isl_stat r;
1515 		isl_set *set;
1516 		isl_multi_aff *offset;
1517 		isl_multi_val *size;
1518 		isl_fixed_box *box;
1519 
1520 		set = isl_set_read_from_str(ctx, box_hull_tests[i].set);
1521 		box = isl_set_get_simple_fixed_box_hull(set);
1522 		offset = isl_fixed_box_get_offset(box);
1523 		size = isl_fixed_box_get_size(box);
1524 		str = box_hull_tests[i].offset;
1525 		r = multi_aff_check_plain_equal(offset, str);
1526 		str = box_hull_tests[i].size;
1527 		if (r >= 0)
1528 			r = multi_val_check_plain_equal(size, str);
1529 		isl_multi_aff_free(offset);
1530 		isl_multi_val_free(size);
1531 		isl_fixed_box_free(box);
1532 		isl_set_free(set);
1533 		if (r < 0)
1534 			return -1;
1535 	}
1536 
1537 	return 0;
1538 }
1539 
test_convex_hull_case(struct isl_ctx * ctx,const char * name)1540 void test_convex_hull_case(struct isl_ctx *ctx, const char *name)
1541 {
1542 	char *filename;
1543 	FILE *input;
1544 	struct isl_basic_set *bset1, *bset2;
1545 	struct isl_set *set;
1546 
1547 	filename = get_filename(ctx, name, "polylib");
1548 	assert(filename);
1549 	input = fopen(filename, "r");
1550 	assert(input);
1551 
1552 	bset1 = isl_basic_set_read_from_file(ctx, input);
1553 	bset2 = isl_basic_set_read_from_file(ctx, input);
1554 
1555 	set = isl_basic_set_union(bset1, bset2);
1556 	bset1 = isl_set_convex_hull(set);
1557 
1558 	bset2 = isl_basic_set_read_from_file(ctx, input);
1559 
1560 	assert(isl_basic_set_is_equal(bset1, bset2) == 1);
1561 
1562 	isl_basic_set_free(bset1);
1563 	isl_basic_set_free(bset2);
1564 	free(filename);
1565 
1566 	fclose(input);
1567 }
1568 
1569 struct {
1570 	const char *set;
1571 	const char *hull;
1572 } convex_hull_tests[] = {
1573 	{ "{ [i0, i1, i2] : (i2 = 1 and i0 = 0 and i1 >= 0) or "
1574 	       "(i0 = 1 and i1 = 0 and i2 = 1) or "
1575 	       "(i0 = 0 and i1 = 0 and i2 = 0) }",
1576 	  "{ [i0, i1, i2] : i0 >= 0 and i2 >= i0 and i2 <= 1 and i1 >= 0 }" },
1577 	{ "[n] -> { [i0, i1, i0] : i0 <= -4 + n; "
1578 	    "[i0, i0, i2] : n = 6 and i0 >= 0 and i2 <= 7 - i0 and "
1579 	    "i2 <= 5 and i2 >= 4; "
1580 	    "[3, i1, 3] : n = 5 and i1 <= 2 and i1 >= 0 }",
1581 	  "[n] -> { [i0, i1, i2] : i2 <= -1 + n and 2i2 <= -6 + 3n - i0 and "
1582 	    "i2 <= 5 + i0 and i2 >= i0 }" },
1583 	{ "{ [x, y] : 3y <= 2x and y >= -2 + 2x and 2y >= 2 - x }",
1584 	    "{ [x, y] : 1 = 0 }" },
1585 	{ "{ [x, y, z] : 0 <= x, y, z <= 10; [x, y, 0] : x >= 0 and y > 0; "
1586 	    "[x, y, 0] : x >= 0 and y < 0 }",
1587 	    "{ [x, y, z] : x >= 0 and 0 <= z <= 10 }" },
1588 	{ "{ [a, b, c] : a <= 1 and -a < b <= 1 and 0 <= c <= 2 - a - b and "
1589 			    "c <= a; "
1590 	    "[0, 2, 0]; [3, 1, 0] }",
1591 	    "{ [a, b, c] : b > -a and 2b >= -1 + a and 0 <= c <= a and "
1592 			    "5c <= 6 - a - 3b }" },
1593 };
1594 
test_convex_hull_algo(isl_ctx * ctx,int convex)1595 static int test_convex_hull_algo(isl_ctx *ctx, int convex)
1596 {
1597 	int i;
1598 	int orig_convex = ctx->opt->convex;
1599 	ctx->opt->convex = convex;
1600 
1601 	test_convex_hull_case(ctx, "convex0");
1602 	test_convex_hull_case(ctx, "convex1");
1603 	test_convex_hull_case(ctx, "convex2");
1604 	test_convex_hull_case(ctx, "convex3");
1605 	test_convex_hull_case(ctx, "convex4");
1606 	test_convex_hull_case(ctx, "convex5");
1607 	test_convex_hull_case(ctx, "convex6");
1608 	test_convex_hull_case(ctx, "convex7");
1609 	test_convex_hull_case(ctx, "convex8");
1610 	test_convex_hull_case(ctx, "convex9");
1611 	test_convex_hull_case(ctx, "convex10");
1612 	test_convex_hull_case(ctx, "convex11");
1613 	test_convex_hull_case(ctx, "convex12");
1614 	test_convex_hull_case(ctx, "convex13");
1615 	test_convex_hull_case(ctx, "convex14");
1616 	test_convex_hull_case(ctx, "convex15");
1617 
1618 	for (i = 0; i < ARRAY_SIZE(convex_hull_tests); ++i) {
1619 		isl_set *set1, *set2;
1620 		int equal;
1621 
1622 		set1 = isl_set_read_from_str(ctx, convex_hull_tests[i].set);
1623 		set2 = isl_set_read_from_str(ctx, convex_hull_tests[i].hull);
1624 		set1 = isl_set_from_basic_set(isl_set_convex_hull(set1));
1625 		equal = isl_set_is_equal(set1, set2);
1626 		isl_set_free(set1);
1627 		isl_set_free(set2);
1628 
1629 		if (equal < 0)
1630 			return -1;
1631 		if (!equal)
1632 			isl_die(ctx, isl_error_unknown,
1633 				"unexpected convex hull", return -1);
1634 	}
1635 
1636 	ctx->opt->convex = orig_convex;
1637 
1638 	return 0;
1639 }
1640 
test_convex_hull(isl_ctx * ctx)1641 static int test_convex_hull(isl_ctx *ctx)
1642 {
1643 	if (test_convex_hull_algo(ctx, ISL_CONVEX_HULL_FM) < 0)
1644 		return -1;
1645 	if (test_convex_hull_algo(ctx, ISL_CONVEX_HULL_WRAP) < 0)
1646 		return -1;
1647 	return 0;
1648 }
1649 
test_gist_case(struct isl_ctx * ctx,const char * name)1650 void test_gist_case(struct isl_ctx *ctx, const char *name)
1651 {
1652 	char *filename;
1653 	FILE *input;
1654 	struct isl_basic_set *bset1, *bset2;
1655 
1656 	filename = get_filename(ctx, name, "polylib");
1657 	assert(filename);
1658 	input = fopen(filename, "r");
1659 	assert(input);
1660 
1661 	bset1 = isl_basic_set_read_from_file(ctx, input);
1662 	bset2 = isl_basic_set_read_from_file(ctx, input);
1663 
1664 	bset1 = isl_basic_set_gist(bset1, bset2);
1665 
1666 	bset2 = isl_basic_set_read_from_file(ctx, input);
1667 
1668 	assert(isl_basic_set_is_equal(bset1, bset2) == 1);
1669 
1670 	isl_basic_set_free(bset1);
1671 	isl_basic_set_free(bset2);
1672 	free(filename);
1673 
1674 	fclose(input);
1675 }
1676 
1677 /* Inputs to isl_map_plain_gist_basic_map, along with the expected output.
1678  */
1679 struct {
1680 	const char *map;
1681 	const char *context;
1682 	const char *gist;
1683 } plain_gist_tests[] = {
1684 	{ "{ [i] -> [j] : i >= 1 and j >= 1 or i >= 2 and j <= 10 }",
1685 	  "{ [i] -> [j] : i >= 1 }",
1686 	  "{ [i] -> [j] : j >= 1 or i >= 2 and j <= 10 }" },
1687 	{ "{ [n] -> [i,j,k] : (i mod 3 = 2 and j mod 4 = 2) or "
1688 		"(j mod 4 = 2 and k mod 6 = n) }",
1689 	  "{ [n] -> [i,j,k] : j mod 4 = 2 }",
1690 	  "{ [n] -> [i,j,k] : (i mod 3 = 2) or (k mod 6 = n) }" },
1691 	{ "{ [i] -> [j] : i > j and (exists a,b : i <= 2a + 5b <= 2) }",
1692 	  "{ [i] -> [j] : i > j }",
1693 	  "{ [i] -> [j] : exists a,b : i <= 2a + 5b <= 2 }" },
1694 };
1695 
1696 /* Basic tests for isl_map_plain_gist_basic_map.
1697  */
test_plain_gist(isl_ctx * ctx)1698 static int test_plain_gist(isl_ctx *ctx)
1699 {
1700 	int i;
1701 
1702 	for (i = 0; i < ARRAY_SIZE(plain_gist_tests); ++i) {
1703 		const char *str;
1704 		int equal;
1705 		isl_map *map, *gist;
1706 		isl_basic_map *context;
1707 
1708 		map = isl_map_read_from_str(ctx, plain_gist_tests[i].map);
1709 		str = plain_gist_tests[i].context;
1710 		context = isl_basic_map_read_from_str(ctx, str);
1711 		map = isl_map_plain_gist_basic_map(map, context);
1712 		gist = isl_map_read_from_str(ctx, plain_gist_tests[i].gist);
1713 		equal = isl_map_is_equal(map, gist);
1714 		isl_map_free(map);
1715 		isl_map_free(gist);
1716 		if (equal < 0)
1717 			return -1;
1718 		if (!equal)
1719 			isl_die(ctx, isl_error_unknown,
1720 				"incorrect gist result", return -1);
1721 	}
1722 
1723 	return 0;
1724 }
1725 
1726 /* Inputs for isl_basic_set_gist tests that are expected to fail.
1727  */
1728 struct {
1729 	const char *set;
1730 	const char *context;
1731 } gist_fail_tests[] = {
1732 	{ "{ [i] : exists (e0, e1: 3e1 >= 1 + 2e0 and "
1733 	    "8e1 <= -1 + 5i - 5e0 and 2e1 >= 1 + 2i - 5e0) }",
1734 	  "{ [i] : i >= 0 }" },
1735 };
1736 
1737 /* Check that isl_basic_set_gist fails (gracefully) when expected.
1738  * In particular, the user should be able to recover from the failure.
1739  */
test_gist_fail(struct isl_ctx * ctx)1740 static isl_stat test_gist_fail(struct isl_ctx *ctx)
1741 {
1742 	int i, n;
1743 	int on_error;
1744 
1745 	on_error = isl_options_get_on_error(ctx);
1746 	isl_options_set_on_error(ctx, ISL_ON_ERROR_CONTINUE);
1747 	n = ARRAY_SIZE(gist_fail_tests);
1748 	for (i = 0; i < n; ++i) {
1749 		const char *str;
1750 		isl_basic_set *bset, *context;
1751 
1752 		bset = isl_basic_set_read_from_str(ctx, gist_fail_tests[i].set);
1753 		str = gist_fail_tests[i].context;
1754 		context = isl_basic_set_read_from_str(ctx, str);
1755 		bset = isl_basic_set_gist(bset, context);
1756 		isl_basic_set_free(bset);
1757 		if (bset)
1758 			break;
1759 	}
1760 	isl_options_set_on_error(ctx, on_error);
1761 	if (i < n)
1762 		isl_die(ctx, isl_error_unknown,
1763 			"operation not expected to succeed",
1764 			return isl_stat_error);
1765 
1766 	return isl_stat_ok;
1767 }
1768 
1769 struct {
1770 	const char *set;
1771 	const char *context;
1772 	const char *gist;
1773 } gist_tests[] = {
1774 	{ "{ [a, b, c] : a <= 15 and a >= 1 }",
1775 	  "{ [a, b, c] : exists (e0 = floor((-1 + a)/16): a >= 1 and "
1776 			"c <= 30 and 32e0 >= -62 + 2a + 2b - c and b >= 0) }",
1777 	  "{ [a, b, c] : a <= 15 }" },
1778 	{ "{ : }", "{ : 1 = 0 }", "{ : }" },
1779 	{ "{ : 1 = 0 }", "{ : 1 = 0 }", "{ : }" },
1780 	{ "[M] -> { [x] : exists (e0 = floor((-2 + x)/3): 3e0 = -2 + x) }",
1781 	  "[M] -> { [3M] }" , "[M] -> { [x] : 1 = 0 }" },
1782 	{ "{ [m, n, a, b] : a <= 2147 + n }",
1783 	  "{ [m, n, a, b] : (m >= 1 and n >= 1 and a <= 2148 - m and "
1784 			"b <= 2148 - n and b >= 0 and b >= 2149 - n - a) or "
1785 			"(n >= 1 and a >= 0 and b <= 2148 - n - a and "
1786 			"b >= 0) }",
1787 	  "{ [m, n, ku, kl] }" },
1788 	{ "{ [a, a, b] : a >= 10 }",
1789 	  "{ [a, b, c] : c >= a and c <= b and c >= 2 }",
1790 	  "{ [a, a, b] : a >= 10 }" },
1791 	{ "{ [i, j] : i >= 0 and i + j >= 0 }", "{ [i, j] : i <= 0 }",
1792 	  "{ [0, j] : j >= 0 }" },
1793 	/* Check that no constraints on i6 are introduced in the gist */
1794 	{ "[t1] -> { [i4, i6] : exists (e0 = floor((1530 - 4t1 - 5i4)/20): "
1795 		"20e0 <= 1530 - 4t1 - 5i4 and 20e0 >= 1511 - 4t1 - 5i4 and "
1796 		"5e0 <= 381 - t1 and i4 <= 1) }",
1797 	  "[t1] -> { [i4, i6] : exists (e0 = floor((-t1 + i6)/5): "
1798 		"5e0 = -t1 + i6 and i6 <= 6 and i6 >= 3) }",
1799 	  "[t1] -> { [i4, i6] : exists (e0 = floor((1530 - 4t1 - 5i4)/20): "
1800 		"i4 <= 1 and 5e0 <= 381 - t1 and 20e0 <= 1530 - 4t1 - 5i4 and "
1801 		"20e0 >= 1511 - 4t1 - 5i4) }" },
1802 	/* Check that no constraints on i6 are introduced in the gist */
1803 	{ "[t1, t2] -> { [i4, i5, i6] : exists (e0 = floor((1 + i4)/2), "
1804 		"e1 = floor((1530 - 4t1 - 5i4)/20), "
1805 		"e2 = floor((-4t1 - 5i4 + 10*floor((1 + i4)/2))/20), "
1806 		"e3 = floor((-1 + i4)/2): t2 = 0 and 2e3 = -1 + i4 and "
1807 			"20e2 >= -19 - 4t1 - 5i4 + 10e0 and 5e2 <= 1 - t1 and "
1808 			"2e0 <= 1 + i4 and 2e0 >= i4 and "
1809 			"20e1 <= 1530 - 4t1 - 5i4 and "
1810 			"20e1 >= 1511 - 4t1 - 5i4 and i4 <= 1 and "
1811 			"5e1 <= 381 - t1 and 20e2 <= -4t1 - 5i4 + 10e0) }",
1812 	  "[t1, t2] -> { [i4, i5, i6] : exists (e0 = floor((-17 + i4)/2), "
1813 		"e1 = floor((-t1 + i6)/5): 5e1 = -t1 + i6 and "
1814 			"2e0 <= -17 + i4 and 2e0 >= -18 + i4 and "
1815 			"10e0 <= -91 + 5i4 + 4i6 and "
1816 			"10e0 >= -105 + 5i4 + 4i6) }",
1817 	  "[t1, t2] -> { [i4, i5, i6] : exists (e0 = floor((381 - t1)/5), "
1818 		"e1 = floor((-1 + i4)/2): t2 = 0 and 2e1 = -1 + i4 and "
1819 		"i4 <= 1 and 5e0 <= 381 - t1 and 20e0 >= 1511 - 4t1 - 5i4) }" },
1820 	{ "{ [0, 0, q, p] : -5 <= q <= 5 and p >= 0 }",
1821 	  "{ [a, b, q, p] : b >= 1 + a }",
1822 	  "{ [a, b, q, p] : false }" },
1823 	{ "[n] -> { [x] : x = n && x mod 32 = 0 }",
1824 	  "[n] -> { [x] : x mod 32 = 0 }",
1825 	  "[n] -> { [x = n] }" },
1826 	{ "{ [x] : x mod 6 = 0 }", "{ [x] : x mod 3 = 0 }",
1827 	  "{ [x] : x mod 2 = 0 }" },
1828 	{ "{ [x] : x mod 3200 = 0 }", "{ [x] : x mod 10000 = 0 }",
1829 	  "{ [x] : x mod 128 = 0 }" },
1830 	{ "{ [x] : x mod 3200 = 0 }", "{ [x] : x mod 10 = 0 }",
1831 	  "{ [x] : x mod 3200 = 0 }" },
1832 	{ "{ [a, b, c] : a mod 2 = 0 and a = c }",
1833 	  "{ [a, b, c] : b mod 2 = 0 and b = c }",
1834 	  "{ [a, b, c = a] }" },
1835 	{ "{ [a, b, c] : a mod 6 = 0 and a = c }",
1836 	  "{ [a, b, c] : b mod 2 = 0 and b = c }",
1837 	  "{ [a, b, c = a] : a mod 3 = 0 }" },
1838 	{ "{ [x] : 0 <= x <= 4 or 6 <= x <= 9 }",
1839 	  "{ [x] : 1 <= x <= 3 or 7 <= x <= 8 }",
1840 	  "{ [x] }" },
1841 	{ "{ [x,y] : x < 0 and 0 <= y <= 4 or x >= -2 and -x <= y <= 10 + x }",
1842 	  "{ [x,y] : 1 <= y <= 3 }",
1843 	  "{ [x,y] }" },
1844 };
1845 
1846 /* Check that isl_set_gist behaves as expected.
1847  *
1848  * For the test cases in gist_tests, besides checking that the result
1849  * is as expected, also check that applying the gist operation does
1850  * not modify the input set (an earlier version of isl would do that) and
1851  * that the test case is consistent, i.e., that the gist has the same
1852  * intersection with the context as the input set.
1853  */
test_gist(struct isl_ctx * ctx)1854 static int test_gist(struct isl_ctx *ctx)
1855 {
1856 	int i;
1857 	const char *str;
1858 	isl_basic_set *bset1, *bset2;
1859 	isl_map *map1, *map2;
1860 	isl_bool equal;
1861 	isl_size n_div;
1862 
1863 	for (i = 0; i < ARRAY_SIZE(gist_tests); ++i) {
1864 		isl_bool equal_input, equal_intersection;
1865 		isl_set *set1, *set2, *copy, *context;
1866 
1867 		set1 = isl_set_read_from_str(ctx, gist_tests[i].set);
1868 		context = isl_set_read_from_str(ctx, gist_tests[i].context);
1869 		copy = isl_set_copy(set1);
1870 		set1 = isl_set_gist(set1, isl_set_copy(context));
1871 		set2 = isl_set_read_from_str(ctx, gist_tests[i].gist);
1872 		equal = isl_set_is_equal(set1, set2);
1873 		isl_set_free(set1);
1874 		set1 = isl_set_read_from_str(ctx, gist_tests[i].set);
1875 		equal_input = isl_set_is_equal(set1, copy);
1876 		isl_set_free(copy);
1877 		set1 = isl_set_intersect(set1, isl_set_copy(context));
1878 		set2 = isl_set_intersect(set2, context);
1879 		equal_intersection = isl_set_is_equal(set1, set2);
1880 		isl_set_free(set2);
1881 		isl_set_free(set1);
1882 		if (equal < 0 || equal_input < 0 || equal_intersection < 0)
1883 			return -1;
1884 		if (!equal)
1885 			isl_die(ctx, isl_error_unknown,
1886 				"incorrect gist result", return -1);
1887 		if (!equal_input)
1888 			isl_die(ctx, isl_error_unknown,
1889 				"gist modified input", return -1);
1890 		if (!equal_input)
1891 			isl_die(ctx, isl_error_unknown,
1892 				"inconsistent gist test case", return -1);
1893 	}
1894 
1895 	if (test_gist_fail(ctx) < 0)
1896 		return -1;
1897 
1898 	test_gist_case(ctx, "gist1");
1899 
1900 	str = "[p0, p2, p3, p5, p6, p10] -> { [] : "
1901 	    "exists (e0 = [(15 + p0 + 15p6 + 15p10)/16], e1 = [(p5)/8], "
1902 	    "e2 = [(p6)/128], e3 = [(8p2 - p5)/128], "
1903 	    "e4 = [(128p3 - p6)/4096]: 8e1 = p5 and 128e2 = p6 and "
1904 	    "128e3 = 8p2 - p5 and 4096e4 = 128p3 - p6 and p2 >= 0 and "
1905 	    "16e0 >= 16 + 16p6 + 15p10 and  p2 <= 15 and p3 >= 0 and "
1906 	    "p3 <= 31 and  p6 >= 128p3 and p5 >= 8p2 and p10 >= 0 and "
1907 	    "16e0 <= 15 + p0 + 15p6 + 15p10 and 16e0 >= p0 + 15p6 + 15p10 and "
1908 	    "p10 <= 15 and p10 <= -1 + p0 - p6) }";
1909 	bset1 = isl_basic_set_read_from_str(ctx, str);
1910 	str = "[p0, p2, p3, p5, p6, p10] -> { [] : exists (e0 = [(p5)/8], "
1911 	    "e1 = [(p6)/128], e2 = [(8p2 - p5)/128], "
1912 	    "e3 = [(128p3 - p6)/4096]: 8e0 = p5 and 128e1 = p6 and "
1913 	    "128e2 = 8p2 - p5 and 4096e3 = 128p3 - p6 and p5 >= -7 and "
1914 	    "p2 >= 0 and 8p2 <= -1 + p0 and p2 <= 15 and p3 >= 0 and "
1915 	    "p3 <= 31 and 128p3 <= -1 + p0 and p6 >= -127 and "
1916 	    "p5 <= -1 + p0 and p6 <= -1 + p0 and p6 >= 128p3 and "
1917 	    "p0 >= 1 and p5 >= 8p2 and p10 >= 0 and p10 <= 15 ) }";
1918 	bset2 = isl_basic_set_read_from_str(ctx, str);
1919 	bset1 = isl_basic_set_gist(bset1, bset2);
1920 	assert(bset1 && bset1->n_div == 0);
1921 	isl_basic_set_free(bset1);
1922 
1923 	/* Check that the integer divisions of the second disjunct
1924 	 * do not spread to the first disjunct.
1925 	 */
1926 	str = "[t1] -> { S_0[] -> A[o0] : (exists (e0 = [(-t1 + o0)/16]: "
1927 		"16e0 = -t1 + o0 and o0 >= 0 and o0 <= 15 and t1 >= 0)) or "
1928 		"(exists (e0 = [(-1 + t1)/16], "
1929 			"e1 = [(-16 + t1 - 16e0)/4294967296]: "
1930 			"4294967296e1 = -16 + t1 - o0 - 16e0 and "
1931 			"16e0 <= -1 + t1 and 16e0 >= -16 + t1 and o0 >= 0 and "
1932 			"o0 <= 4294967295 and t1 <= -1)) }";
1933 	map1 = isl_map_read_from_str(ctx, str);
1934 	str = "[t1] -> { S_0[] -> A[o0] : t1 >= 0 and t1 <= 4294967295 }";
1935 	map2 = isl_map_read_from_str(ctx, str);
1936 	map1 = isl_map_gist(map1, map2);
1937 	if (!map1)
1938 		return -1;
1939 	if (map1->n != 1)
1940 		isl_die(ctx, isl_error_unknown, "expecting single disjunct",
1941 			isl_map_free(map1); return -1);
1942 	n_div = isl_basic_map_dim(map1->p[0], isl_dim_div);
1943 	isl_map_free(map1);
1944 	if (n_div < 0)
1945 		return -1;
1946 	if (n_div != 1)
1947 		isl_die(ctx, isl_error_unknown, "expecting single div",
1948 			return -1);
1949 
1950 	if (test_plain_gist(ctx) < 0)
1951 		return -1;
1952 
1953 	return 0;
1954 }
1955 
test_coalesce_set(isl_ctx * ctx,const char * str,int check_one)1956 int test_coalesce_set(isl_ctx *ctx, const char *str, int check_one)
1957 {
1958 	isl_set *set, *set2;
1959 	int equal;
1960 	int one;
1961 
1962 	set = isl_set_read_from_str(ctx, str);
1963 	set = isl_set_coalesce(set);
1964 	set2 = isl_set_read_from_str(ctx, str);
1965 	equal = isl_set_is_equal(set, set2);
1966 	one = set && set->n == 1;
1967 	isl_set_free(set);
1968 	isl_set_free(set2);
1969 
1970 	if (equal < 0)
1971 		return -1;
1972 	if (!equal)
1973 		isl_die(ctx, isl_error_unknown,
1974 			"coalesced set not equal to input", return -1);
1975 	if (check_one && !one)
1976 		isl_die(ctx, isl_error_unknown,
1977 			"coalesced set should not be a union", return -1);
1978 
1979 	return 0;
1980 }
1981 
1982 /* Inputs for coalescing tests with unbounded wrapping.
1983  * "str" is a string representation of the input set.
1984  * "single_disjunct" is set if we expect the result to consist of
1985  *	a single disjunct.
1986  */
1987 struct {
1988 	int single_disjunct;
1989 	const char *str;
1990 } coalesce_unbounded_tests[] = {
1991 	{ 1, "{ [x,y,z] : y + 2 >= 0 and x - y + 1 >= 0 and "
1992 			"-x - y + 1 >= 0 and -3 <= z <= 3;"
1993 		"[x,y,z] : -x+z + 20 >= 0 and -x-z + 20 >= 0 and "
1994 			"x-z + 20 >= 0 and x+z + 20 >= 0 and "
1995 			"-10 <= y <= 0}" },
1996 	{ 1, "{ [x,y] : 0 <= x,y <= 10; [5,y]: 4 <= y <= 11 }" },
1997 	{ 1, "{ [x,0,0] : -5 <= x <= 5; [0,y,1] : -5 <= y <= 5 }" },
1998 	{ 1, "{ [x,y] : 0 <= x <= 10 and 0 >= y >= -1 and x+y >= 0; [0,1] }" },
1999 	{ 1, "{ [x,y] : (0 <= x,y <= 4) or (2 <= x,y <= 5 and x + y <= 9) }" },
2000 	{ 0, "{ [x, y, z] : 0 <= x,y,z <= 100 and 0 < z <= 2 + 2x + 2y; "
2001 		"[x, y, 0] : x,y <= 100 and y <= 9 + 11x and x <= 9 + 11y }" },
2002 };
2003 
2004 /* Test the functionality of isl_set_coalesce with the bounded wrapping
2005  * option turned off.
2006  */
test_coalesce_unbounded_wrapping(isl_ctx * ctx)2007 int test_coalesce_unbounded_wrapping(isl_ctx *ctx)
2008 {
2009 	int i;
2010 	int r = 0;
2011 	int bounded;
2012 
2013 	bounded = isl_options_get_coalesce_bounded_wrapping(ctx);
2014 	isl_options_set_coalesce_bounded_wrapping(ctx, 0);
2015 
2016 	for (i = 0; i < ARRAY_SIZE(coalesce_unbounded_tests); ++i) {
2017 		const char *str = coalesce_unbounded_tests[i].str;
2018 		int check_one = coalesce_unbounded_tests[i].single_disjunct;
2019 		if (test_coalesce_set(ctx, str, check_one) >= 0)
2020 			continue;
2021 		r = -1;
2022 		break;
2023 	}
2024 
2025 	isl_options_set_coalesce_bounded_wrapping(ctx, bounded);
2026 
2027 	return r;
2028 }
2029 
2030 /* Inputs for coalescing tests.
2031  * "str" is a string representation of the input set.
2032  * "single_disjunct" is set if we expect the result to consist of
2033  *	a single disjunct.
2034  */
2035 struct {
2036 	int single_disjunct;
2037 	const char *str;
2038 } coalesce_tests[] = {
2039 	{ 1, "{[x,y]: x >= 0 & x <= 10 & y >= 0 & y <= 10 or "
2040 		       "y >= x & x >= 2 & 5 >= y }" },
2041 	{ 1, "{[x,y]: y >= 0 & 2x + y <= 30 & y <= 10 & x >= 0 or "
2042 		       "x + y >= 10 & y <= x & x + y <= 20 & y >= 0}" },
2043 	{ 0, "{[x,y]: y >= 0 & 2x + y <= 30 & y <= 10 & x >= 0 or "
2044 		       "x + y >= 10 & y <= x & x + y <= 19 & y >= 0}" },
2045 	{ 1, "{[x,y]: y >= 0 & x <= 5 & y <= x or "
2046 		       "y >= 0 & x >= 6 & x <= 10 & y <= x}" },
2047 	{ 0, "{[x,y]: y >= 0 & x <= 5 & y <= x or "
2048 		       "y >= 0 & x >= 7 & x <= 10 & y <= x}" },
2049 	{ 0, "{[x,y]: y >= 0 & x <= 5 & y <= x or "
2050 		       "y >= 0 & x >= 6 & x <= 10 & y + 1 <= x}" },
2051 	{ 1, "{[x,y]: y >= 0 & x <= 5 & y <= x or y >= 0 & x = 6 & y <= 6}" },
2052 	{ 0, "{[x,y]: y >= 0 & x <= 5 & y <= x or y >= 0 & x = 7 & y <= 6}" },
2053 	{ 1, "{[x,y]: y >= 0 & x <= 5 & y <= x or y >= 0 & x = 6 & y <= 5}" },
2054 	{ 0, "{[x,y]: y >= 0 & x <= 5 & y <= x or y >= 0 & x = 6 & y <= 7}" },
2055 	{ 1, "[n] -> { [i] : i = 1 and n >= 2 or 2 <= i and i <= n }" },
2056 	{ 0, "{[x,y] : x >= 0 and y >= 0 or 0 <= y and y <= 5 and x = -1}" },
2057 	{ 1, "[n] -> { [i] : 1 <= i and i <= n - 1 or 2 <= i and i <= n }" },
2058 	{ 0, "[n] -> { [[i0] -> [o0]] : exists (e0 = [(i0)/4], e1 = [(o0)/4], "
2059 		"e2 = [(n)/2], e3 = [(-2 + i0)/4], e4 = [(-2 + o0)/4], "
2060 		"e5 = [(-2n + i0)/4]: 2e2 = n and 4e3 = -2 + i0 and "
2061 		"4e4 = -2 + o0 and i0 >= 8 + 2n and o0 >= 2 + i0 and "
2062 		"o0 <= 56 + 2n and o0 <= -12 + 4n and i0 <= 57 + 2n and "
2063 		"i0 <= -11 + 4n and o0 >= 6 + 2n and 4e0 <= i0 and "
2064 		"4e0 >= -3 + i0 and 4e1 <= o0 and 4e1 >= -3 + o0 and "
2065 		"4e5 <= -2n + i0 and 4e5 >= -3 - 2n + i0);"
2066 		"[[i0] -> [o0]] : exists (e0 = [(i0)/4], e1 = [(o0)/4], "
2067 		"e2 = [(n)/2], e3 = [(-2 + i0)/4], e4 = [(-2 + o0)/4], "
2068 		"e5 = [(-2n + i0)/4]: 2e2 = n and 4e3 = -2 + i0 and "
2069 		"4e4 = -2 + o0 and 2e0 >= 3 + n and e0 <= -4 + n and "
2070 		"2e0 <= 27 + n and e1 <= -4 + n and 2e1 <= 27 + n and "
2071 		"2e1 >= 2 + n and e1 >= 1 + e0 and i0 >= 7 + 2n and "
2072 		"i0 <= -11 + 4n and i0 <= 57 + 2n and 4e0 <= -2 + i0 and "
2073 		"4e0 >= -3 + i0 and o0 >= 6 + 2n and o0 <= -11 + 4n and "
2074 		"o0 <= 57 + 2n and 4e1 <= -2 + o0 and 4e1 >= -3 + o0 and "
2075 		"4e5 <= -2n + i0 and 4e5 >= -3 - 2n + i0 ) }" },
2076 	{ 0, "[n, m] -> { [o0, o2, o3] : (o3 = 1 and o0 >= 1 + m and "
2077 	      "o0 <= n + m and o2 <= m and o0 >= 2 + n and o2 >= 3) or "
2078 	      "(o0 >= 2 + n and o0 >= 1 + m and o0 <= n + m and n >= 1 and "
2079 	      "o3 <= -1 + o2 and o3 >= 1 - m + o2 and o3 >= 2 and o3 <= n) }" },
2080 	{ 0, "[M, N] -> { [[i0, i1, i2, i3, i4, i5, i6] -> "
2081 	  "[o0, o1, o2, o3, o4, o5, o6]] : "
2082 	  "(o6 <= -4 + 2M - 2N + i0 + i1 - i2 + i6 - o0 - o1 + o2 and "
2083 	  "o3 <= -2 + i3 and o6 >= 2 + i0 + i3 + i6 - o0 - o3 and "
2084 	  "o6 >= 2 - M + N + i3 + i4 + i6 - o3 - o4 and o0 <= -1 + i0 and "
2085 	  "o4 >= 4 - 3M + 3N - i0 - i1 + i2 + 2i3 + i4 + o0 + o1 - o2 - 2o3 "
2086 	  "and o6 <= -3 + 2M - 2N + i3 + i4 - i5 + i6 - o3 - o4 + o5 and "
2087 	  "2o6 <= -5 + 5M - 5N + 2i0 + i1 - i2 - i5 + 2i6 - 2o0 - o1 + o2 + o5 "
2088 	  "and o6 >= 2i0 + i1 + i6 - 2o0 - o1 and "
2089 	  "3o6 <= -5 + 4M - 4N + 2i0 + i1 - i2 + 2i3 + i4 - i5 + 3i6 "
2090 	  "- 2o0 - o1 + o2 - 2o3 - o4 + o5) or "
2091 	  "(N >= 2 and o3 <= -1 + i3 and o0 <= -1 + i0 and "
2092 	  "o6 >= i3 + i6 - o3 and M >= 0 and "
2093 	  "2o6 >= 1 + i0 + i3 + 2i6 - o0 - o3 and "
2094 	  "o6 >= 1 - M + i0 + i6 - o0 and N >= 2M and o6 >= i0 + i6 - o0) }" },
2095 	{ 0, "[M, N] -> { [o0] : (o0 = 0 and M >= 1 and N >= 2) or "
2096 		"(o0 = 0 and M >= 1 and N >= 2M and N >= 2 + M) or "
2097 		"(o0 = 0 and M >= 2 and N >= 3) or "
2098 		"(M = 0 and o0 = 0 and N >= 3) }" },
2099 	{ 0, "{ [i0, i1, i2, i3] : (i1 = 10i0 and i0 >= 1 and 10i0 <= 100 and "
2100 	    "i3 <= 9 + 10 i2 and i3 >= 1 + 10i2 and i3 >= 0) or "
2101 	    "(i1 <= 9 + 10i0 and i1 >= 1 + 10i0 and i2 >= 0 and "
2102 	    "i0 >= 0 and i1 <= 100 and i3 <= 9 + 10i2 and i3 >= 1 + 10i2) }" },
2103 	{ 0, "[M] -> { [i1] : (i1 >= 2 and i1 <= M) or (i1 = M and M >= 1) }" },
2104 	{ 0, "{[x,y] : x,y >= 0; [x,y] : 10 <= x <= 20 and y >= -1 }" },
2105 	{ 1, "{ [x, y] : (x >= 1 and y >= 1 and x <= 2 and y <= 2) or "
2106 		"(y = 3 and x = 1) }" },
2107 	{ 1, "[M] -> { [i0, i1, i2, i3, i4] : (i1 >= 3 and i4 >= 2 + i2 and "
2108 		"i2 >= 2 and i0 >= 2 and i3 >= 1 + i2 and i0 <= M and "
2109 		"i1 <= M and i3 <= M and i4 <= M) or "
2110 		"(i1 >= 2 and i4 >= 1 + i2 and i2 >= 2 and i0 >= 2 and "
2111 		"i3 >= 1 + i2 and i0 <= M and i1 <= -1 + M and i3 <= M and "
2112 		"i4 <= -1 + M) }" },
2113 	{ 1, "{ [x, y] : (x >= 0 and y >= 0 and x <= 10 and y <= 10) or "
2114 		"(x >= 1 and y >= 1 and x <= 11 and y <= 11) }" },
2115 	{ 0, "{[x,0] : x >= 0; [x,1] : x <= 20}" },
2116 	{ 1, "{ [x, 1 - x] : 0 <= x <= 1; [0,0] }" },
2117 	{ 1, "{ [0,0]; [i,i] : 1 <= i <= 10 }" },
2118 	{ 0, "{ [0,0]; [i,j] : 1 <= i,j <= 10 }" },
2119 	{ 1, "{ [0,0]; [i,2i] : 1 <= i <= 10 }" },
2120 	{ 0, "{ [0,0]; [i,2i] : 2 <= i <= 10 }" },
2121 	{ 0, "{ [1,0]; [i,2i] : 1 <= i <= 10 }" },
2122 	{ 0, "{ [0,1]; [i,2i] : 1 <= i <= 10 }" },
2123 	{ 0, "{ [a, b] : exists e : 2e = a and "
2124 		    "a >= 0 and (a <= 3 or (b <= 0 and b >= -4 + a)) }" },
2125 	{ 0, "{ [i, j, i', j'] : i <= 2 and j <= 2 and "
2126 			"j' >= -1 + 2i + j - 2i' and i' <= -1 + i and "
2127 			"j >= 1 and j' <= i + j - i' and i >= 1; "
2128 		"[1, 1, 1, 1] }" },
2129 	{ 1, "{ [i,j] : exists a,b : i = 2a and j = 3b; "
2130 		 "[i,j] : exists a : j = 3a }" },
2131 	{ 1, "{ [a, b, c] : (c <= 7 - b and b <= 1 and b >= 0 and "
2132 			"c >= 3 + b and b <= 3 + 8a and b >= -26 + 8a and "
2133 			"a >= 3) or "
2134 		    "(b <= 1 and c <= 7 and b >= 0 and c >= 4 + b and "
2135 			"b <= 3 + 8a and b >= -26 + 8a and a >= 3) }" },
2136 	{ 1, "{ [a, 0, c] : c >= 1 and c <= 29 and c >= -1 + 8a and "
2137 				"c <= 6 + 8a and a >= 3; "
2138 		"[a, -1, c] : c >= 1 and c <= 30 and c >= 8a and "
2139 				"c <= 7 + 8a and a >= 3 and a <= 4 }" },
2140 	{ 1, "{ [x,y] : 0 <= x <= 2 and y >= 0 and x + 2y <= 4; "
2141 		"[x,0] : 3 <= x <= 4 }" },
2142 	{ 1, "{ [x,y] : 0 <= x <= 3 and y >= 0 and x + 3y <= 6; "
2143 		"[x,0] : 4 <= x <= 5 }" },
2144 	{ 0, "{ [x,y] : 0 <= x <= 2 and y >= 0 and x + 2y <= 4; "
2145 		"[x,0] : 3 <= x <= 5 }" },
2146 	{ 0, "{ [x,y] : 0 <= x <= 2 and y >= 0 and x + y <= 4; "
2147 		"[x,0] : 3 <= x <= 4 }" },
2148 	{ 1, "{ [i0, i1] : i0 <= 122 and i0 >= 1 and 128i1 >= -249 + i0 and "
2149 			"i1 <= 0; "
2150 		"[i0, 0] : i0 >= 123 and i0 <= 124 }" },
2151 	{ 1, "{ [0,0]; [1,1] }" },
2152 	{ 1, "[n] -> { [k] : 16k <= -1 + n and k >= 1; [0] : n >= 2 }" },
2153 	{ 1, "{ [k, ii, k - ii] : ii >= -6 + k and ii <= 6 and ii >= 1 and "
2154 				"ii <= k;"
2155 		"[k, 0, k] : k <= 6 and k >= 1 }" },
2156 	{ 1, "{ [i,j] : i = 4 j and 0 <= i <= 100;"
2157 		"[i,j] : 1 <= i <= 100 and i >= 4j + 1 and i <= 4j + 2 }" },
2158 	{ 1, "{ [x,y] : x % 2 = 0 and y % 2 = 0; [x,x] : x % 2 = 0 }" },
2159 	{ 1, "[n] -> { [1] : n >= 0;"
2160 		    "[x] : exists (e0 = floor((x)/2): x >= 2 and "
2161 			"2e0 >= -1 + x and 2e0 <= x and 2e0 <= n) }" },
2162 	{ 1, "[n] -> { [x, y] : exists (e0 = floor((x)/2), e1 = floor((y)/3): "
2163 			"3e1 = y and x >= 2 and 2e0 >= -1 + x and "
2164 			"2e0 <= x and 2e0 <= n);"
2165 		    "[1, y] : exists (e0 = floor((y)/3): 3e0 = y and "
2166 			"n >= 0) }" },
2167 	{ 1, "[t1] -> { [i0] : (exists (e0 = floor((63t1)/64): "
2168 				"128e0 >= -134 + 127t1 and t1 >= 2 and "
2169 				"64e0 <= 63t1 and 64e0 >= -63 + 63t1)) or "
2170 				"t1 = 1 }" },
2171 	{ 1, "{ [i, i] : exists (e0 = floor((1 + 2i)/3): 3e0 <= 2i and "
2172 				"3e0 >= -1 + 2i and i <= 9 and i >= 1);"
2173 		"[0, 0] }" },
2174 	{ 1, "{ [t1] : exists (e0 = floor((-11 + t1)/2): 2e0 = -11 + t1 and "
2175 				"t1 >= 13 and t1 <= 16);"
2176 		"[t1] : t1 <= 15 and t1 >= 12 }" },
2177 	{ 1, "{ [x,y] : x = 3y and 0 <= y <= 2; [-3,-1] }" },
2178 	{ 1, "{ [x,y] : 2x = 3y and 0 <= y <= 4; [-3,-2] }" },
2179 	{ 0, "{ [x,y] : 2x = 3y and 0 <= y <= 4; [-2,-2] }" },
2180 	{ 0, "{ [x,y] : 2x = 3y and 0 <= y <= 4; [-3,-1] }" },
2181 	{ 1, "{ [i] : exists j : i = 4 j and 0 <= i <= 100;"
2182 		"[i] : exists j : 1 <= i <= 100 and i >= 4j + 1 and "
2183 				"i <= 4j + 2 }" },
2184 	{ 1, "{ [c0] : (exists (e0 : c0 - 1 <= 3e0 <= c0)) or "
2185 		"(exists (e0 : 3e0 = -2 + c0)) }" },
2186 	{ 0, "[n, b0, t0] -> "
2187 		"{ [i0, i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11, i12] : "
2188 		"(exists (e0 = floor((-32b0 + i4)/1048576), "
2189 		"e1 = floor((i8)/32): 1048576e0 = -32b0 + i4 and 32e1 = i8 and "
2190 		"n <= 2147483647 and b0 <= 32767 and b0 >= 0 and "
2191 		"32b0 <= -2 + n and t0 <= 31 and t0 >= 0 and i0 >= 8 + n and "
2192 		"3i4 <= -96 + 3t0 + i0 and 3i4 >= -95 - n + 3t0 + i0 and "
2193 		"i8 >= -157 + i0 - 4i4 and i8 >= 0 and "
2194 		"i8 <= -33 + i0 - 4i4 and 3i8 <= -91 + 4n - i0)) or "
2195 		"(exists (e0 = floor((-32b0 + i4)/1048576), "
2196 		"e1 = floor((i8)/32): 1048576e0 = -32b0 + i4 and 32e1 = i8 and "
2197 		"n <= 2147483647 and b0 <= 32767 and b0 >= 0 and "
2198 		"32b0 <= -2 + n and t0 <= 31 and t0 >= 0 and i0 <= 7 + n and "
2199 		"4i4 <= -3 + i0 and 3i4 <= -96 + 3t0 + i0 and "
2200 		"3i4 >= -95 - n + 3t0 + i0 and i8 >= -157 + i0 - 4i4 and "
2201 		"i8 >= 0 and i8 <= -4 + i0 - 3i4 and i8 <= -41 + i0));"
2202 		"[i0, i1, i2, i3, 0, i5, i6, i7, i8, i9, i10, i11, i12] : "
2203 		"(exists (e0 = floor((i8)/32): b0 = 0 and 32e0 = i8 and "
2204 		"n <= 2147483647 and t0 <= 31 and t0 >= 0 and i0 >= 11 and "
2205 		"i0 >= 96 - 3t0 and i0 <= 95 + n - 3t0 and i0 <= 7 + n and "
2206 		"i8 >= -40 + i0 and i8 <= -10 + i0)) }" },
2207 	{ 0, "{ [i0, i1, i2] : "
2208 		"(exists (e0, e1 = floor((i0)/32), e2 = floor((i1)/32): "
2209 		"32e1 = i0 and 32e2 = i1 and i1 >= -31 + i0 and "
2210 		"i1 <= 31 + i0 and i2 >= -30 + i0 and i2 >= -30 + i1 and "
2211 		"32e0 >= -30 + i0 and 32e0 >= -30 + i1 and "
2212 		"32e0 >= -31 + i2 and 32e0 <= 30 + i2 and 32e0 <= 31 + i1 and "
2213 		"32e0 <= 31 + i0)) or "
2214 		"i0 >= 0 }" },
2215 	{ 1, "{ [a, b, c] : 2b = 1 + a and 2c = 2 + a; [0, 0, 0] }" },
2216 	{ 1, "{ [a, a, b, c] : 32*floor((a)/32) = a and 2*floor((b)/2) = b and "
2217 				"2*floor((c)/2) = c and 0 <= a <= 192;"
2218 		"[224, 224, b, c] : 2*floor((b)/2) = b and 2*floor((c)/2) = c }"
2219 	},
2220 	{ 1, "[n] -> { [a,b] : (exists e : 1 <= a <= 7e and 9e <= b <= n) or "
2221 				"(0 <= a <= b <= n) }" },
2222 	{ 1, "{ [a, b] : 0 <= a <= 2 and b >= 0 and "
2223 		"((0 < b <= 13) or (2*floor((a + b)/2) >= -5 + a + 2b)) }" },
2224 	{ 1, "{ [a] : (2 <= a <= 5) or (a mod 2 = 1 and 1 <= a <= 5) }" },
2225 	{ 1, "{ [a, b, c] : (b = -1 + a and 0 < a <= 3 and "
2226 				"9*floor((-4a + 2c)/9) <= -3 - 4a + 2c) or "
2227 			"(exists (e0 = floor((-16 + 2c)/9): a = 4 and "
2228 				"b = 3 and 9e0 <= -19 + 2c)) }" },
2229 	{ 1, "{ [a, b, c] : (b = -1 + a and 0 < a <= 3 and "
2230 				"9*floor((-4a + 2c)/9) <= -3 - 4a + 2c) or "
2231 			"(a = 4 and b = 3 and "
2232 				"9*floor((-16 + 2c)/9) <= -19 + 2c) }" },
2233 	{ 0, "{ [a, b, c] : (b <= 2 and b <= -2 + a) or "
2234 			"(b = -1 + a and 0 < a <= 3 and "
2235 				"9*floor((-4a + 2c)/9) <= -3 - 4a + 2c) or "
2236 			"(exists (e0 = floor((-16 + 2c)/9): a = 4 and "
2237 				"b = 3 and 9e0 <= -19 + 2c)) }" },
2238 	{ 1, "{ [y, x] : (x - y) mod 3 = 2 and 2 <= y <= 200 and 0 <= x <= 2;"
2239 		"[1, 0] }" },
2240 	{ 1, "{ [x, y] : (x - y) mod 3 = 2 and 2 <= y <= 200 and 0 <= x <= 2;"
2241 		"[0, 1] }" },
2242 	{ 1, "{ [1, y] : -1 <= y <= 1; [x, -x] : 0 <= x <= 1 }" },
2243 	{ 1, "{ [1, y] : 0 <= y <= 1; [x, -x] : 0 <= x <= 1 }" },
2244 	{ 1, "{ [x, y] : 0 <= x <= 10 and x - 4*floor(x/4) <= 1 and y <= 0; "
2245 	       "[x, y] : 0 <= x <= 10 and x - 4*floor(x/4) > 1 and y <= 0; "
2246 	       "[x, y] : 0 <= x <= 10 and x - 5*floor(x/5) <= 1 and 0 < y; "
2247 	       "[x, y] : 0 <= x <= 10 and x - 5*floor(x/5) > 1 and 0 < y }" },
2248 	{ 1, "{ [x, 0] : 0 <= x <= 10 and x mod 2 = 0; "
2249 	       "[x, 0] : 0 <= x <= 10 and x mod 2 = 1; "
2250 	       "[x, y] : 0 <= x <= 10 and 1 <= y <= 10 }" },
2251 	{ 1, "{ [a] : a <= 8 and "
2252 			"(a mod 10 = 7 or a mod 10 = 8 or a mod 10 = 9) }" },
2253 	{ 1, "{ [x, y] : 2y = -x and x <= 0 or "
2254 			"x <= -1 and 2y <= -x - 1 and 2y >= x - 1 }" },
2255 	{ 0, "{ [x, y] : 2y = -x and x <= 0 or "
2256 			"x <= -2 and 2y <= -x - 1 and 2y >= x - 1 }" },
2257 	{ 1, "{ [a] : (a <= 0 and 3*floor((a)/3) = a) or "
2258 			"(a < 0 and 3*floor((a)/3) < a) }" },
2259 	{ 1, "{ [a] : (a <= 0 and 3*floor((a)/3) = a) or "
2260 			"(a < -1 and 3*floor((a)/3) < a) }" },
2261 	{ 1, "{ [a, b] : a <= 1024 and b >= 0 and "
2262 		"((-31 - a + b <= 32*floor((-1 - a)/32) <= -33 + b and "
2263 		  "32*floor((-1 - a)/32) <= -16 + b + 16*floor((-1 - a)/16))"
2264 		"or (2 <= a <= 15 and b < a)) }" },
2265 	{ 1, "{ [a] : a > 0 and ((16*floor((a)/16) < a and "
2266 			"32*floor((a)/32) < a) or a <= 15) }" },
2267 	{ 1, "{ [a, b, c, d] : (-a + d) mod 64 = 0 and a <= 8 and b <= 1 and "
2268 			"10 - a <= c <= 3 and d >= 5 and 9 - 64b <= d <= 70;"
2269 	    "[a, b = 1, c, d] : (-a + d) mod 64 = 0 and a <= 8 and c >= 4 and "
2270 			"10 - a <= c <= 5 and 5 <= d <= 73 - c }" },
2271 	{ 1, "[n, m] -> { S_0[i] : (-n + i) mod 3 = 0 and m >= 3 + n and "
2272 			    "i >= n and 3*floor((2 + n + 2m)/3) <= n + 3m - i; "
2273 			 "S_0[n] : n <= m <= 2 + n }" },
2274 	{ 1, "{ [a, b] : exists (e0: 0 <= a <= 1 and b >= 0 and "
2275 			"2e0 >= -5 + a + 2b and 2e0 >= -1 + a + b and "
2276 			"2e0 <= a + b); "
2277 		"[a, b] : exists (e0: 0 <= a <= 1 and 2e0 >= -5 + a + 2b and "
2278 			"2e0 >= -1 - a + b and 2e0 <= -a + b and "
2279 			"2e0 < -a + 2b) }" },
2280 	{ 1, "{ [i, j, i - 8j] : 8 <= i <= 63 and -7 + i <= 8j <= i; "
2281 		"[i, 0, i] : 0 <= i <= 7 }" },
2282 	{ 1, "{ [a, b] : a >= 0 and 0 <= b <= 1 - a; [1, 1] }" },
2283 	{ 0, "{ [a, b] : a >= 0 and 0 <= b <= 1 - a; [0, 2] }" },
2284 	{ 0, "{ [a, b] : a >= 0 and 0 <= b <= 1 - a; [-1, 3] }" },
2285 	{ 1, "{ [a, b] : a, b >= 0 and a + 2b <= 2; [1, 1] }" },
2286 	{ 0, "{ [a, b] : a, b >= 0 and a + 2b <= 2; [2, 1] }" },
2287 	{ 0, "{ [a, c] : (2 + a) mod 4 = 0 or "
2288 		"(c = 4 + a and 4 * floor((a)/4) = a and a >= 0 and a <= 4) or "
2289 		"(c = 3 + a and 4 * floor((-1 + a)/4) = -1 + a and "
2290 		    "a > 0 and a <= 5) }" },
2291 	{ 1, "{ [1, 0, 0]; [a, b, c] : -1 <= -a < b <= 0 and 2c > b }" },
2292 	{ 0, "{ [j, a, l] : a mod 2 = 0 and j <= 29 and a >= 2 and "
2293 			"2a <= -5 + j and 32j + 2a + 2 <= 4l < 33j; "
2294 		"[j, 0, l] : 4 <= j <= 29 and -3 + 33j <= 4l <= 33j }" },
2295 };
2296 
2297 /* A specialized coalescing test case that would result
2298  * in a segmentation fault or a failed assertion in earlier versions of isl.
2299  */
test_coalesce_special(struct isl_ctx * ctx)2300 static int test_coalesce_special(struct isl_ctx *ctx)
2301 {
2302 	const char *str;
2303 	isl_map *map1, *map2;
2304 
2305 	str = "[y] -> { [S_L220_OUT[] -> T7[]] -> "
2306 	    "[[S_L309_IN[] -> T11[]] -> ce_imag2[1, o1]] : "
2307 	    "(y = 201 and o1 <= 239 and o1 >= 212) or "
2308 	    "(exists (e0 = [(y)/3]: 3e0 = y and y <= 198 and y >= 3 and "
2309 		"o1 <= 239 and o1 >= 212)) or "
2310 	    "(exists (e0 = [(y)/3]: 3e0 = y and y <= 201 and y >= 3 and "
2311 		"o1 <= 241 and o1 >= 240));"
2312 	    "[S_L220_OUT[] -> T7[]] -> "
2313 	    "[[S_L309_IN[] -> T11[]] -> ce_imag2[0, o1]] : "
2314 	    "(y = 2 and o1 <= 241 and o1 >= 212) or "
2315 	    "(exists (e0 = [(-2 + y)/3]: 3e0 = -2 + y and y <= 200 and "
2316 		"y >= 5 and o1 <= 241 and o1 >= 212)) }";
2317 	map1 = isl_map_read_from_str(ctx, str);
2318 	map1 = isl_map_align_divs_internal(map1);
2319 	map1 = isl_map_coalesce(map1);
2320 	str = "[y] -> { [S_L220_OUT[] -> T7[]] -> "
2321 	    "[[S_L309_IN[] -> T11[]] -> ce_imag2[o0, o1]] : "
2322 	    "exists (e0 = [(-1 - y + o0)/3]: 3e0 = -1 - y + o0 and "
2323 		"y <= 201 and o0 <= 2 and o1 >= 212 and o1 <= 241 and "
2324 		"o0 >= 3 - y and o0 <= -2 + y and o0 >= 0) }";
2325 	map2 = isl_map_read_from_str(ctx, str);
2326 	map2 = isl_map_union(map2, map1);
2327 	map2 = isl_map_align_divs_internal(map2);
2328 	map2 = isl_map_coalesce(map2);
2329 	isl_map_free(map2);
2330 	if (!map2)
2331 		return -1;
2332 
2333 	return 0;
2334 }
2335 
2336 /* A specialized coalescing test case that would result in an assertion
2337  * in an earlier version of isl.
2338  * The explicit call to isl_basic_set_union prevents the implicit
2339  * equality constraints in the first basic map from being detected prior
2340  * to the call to isl_set_coalesce, at least at the point
2341  * where this test case was introduced.
2342  */
test_coalesce_special2(struct isl_ctx * ctx)2343 static int test_coalesce_special2(struct isl_ctx *ctx)
2344 {
2345 	const char *str;
2346 	isl_basic_set *bset1, *bset2;
2347 	isl_set *set;
2348 
2349 	str = "{ [x, y] : x, y >= 0 and x + 2y <= 1 and 2x + y <= 1 }";
2350 	bset1 = isl_basic_set_read_from_str(ctx, str);
2351 	str = "{ [x,0] : -1 <= x <= 1 and x mod 2 = 1 }" ;
2352 	bset2 = isl_basic_set_read_from_str(ctx, str);
2353 	set = isl_basic_set_union(bset1, bset2);
2354 	set = isl_set_coalesce(set);
2355 	isl_set_free(set);
2356 
2357 	if (!set)
2358 		return -1;
2359 	return 0;
2360 }
2361 
2362 /* Check that calling isl_set_coalesce does not leave other sets
2363  * that may share some information with the input to isl_set_coalesce
2364  * in an inconsistent state.
2365  * In particular, older versions of isl would modify all copies
2366  * of the basic sets in the isl_set_coalesce input in a way
2367  * that could leave them in an inconsistent state.
2368  * The result of printing any other set containing one of these
2369  * basic sets would then result in an invalid set description.
2370  */
test_coalesce_special3(isl_ctx * ctx)2371 static int test_coalesce_special3(isl_ctx *ctx)
2372 {
2373 	const char *str;
2374 	char *s;
2375 	isl_set *set1, *set2;
2376 	isl_printer *p;
2377 
2378 	set1 = isl_set_read_from_str(ctx, "{ [0, 0, 0] }");
2379 	str = "{ [a, b, a + b] : a >= 0 and b >= 0 and 0 < a + b }";
2380 	set2 = isl_set_read_from_str(ctx, str);
2381 	set1 = isl_set_union(set1, isl_set_copy(set2));
2382 	set1 = isl_set_coalesce(set1);
2383 	isl_set_free(set1);
2384 
2385 	p = isl_printer_to_str(ctx);
2386 	p = isl_printer_print_set(p, set2);
2387 	isl_set_free(set2);
2388 	s = isl_printer_get_str(p);
2389 	isl_printer_free(p);
2390 	set1 = isl_set_read_from_str(ctx, s);
2391 	free(s);
2392 	isl_set_free(set1);
2393 
2394 	if (!set1)
2395 		return -1;
2396 
2397 	return 0;
2398 }
2399 
2400 /* Check that calling isl_set_coalesce on the intersection of
2401  * the sets described by "s1" and "s2" does not leave other sets
2402  * that may share some information with the input to isl_set_coalesce
2403  * in an inconsistent state.
2404  * In particular, when isl_set_coalesce detects equality constraints,
2405  * it does not immediately perform Gaussian elimination on them,
2406  * but then it needs to ensure that it is performed at some point.
2407  * The input set has implicit equality constraints in the first disjunct.
2408  * It is constructed as an intersection, because otherwise
2409  * those equality constraints would already be detected during parsing.
2410  */
test_coalesce_intersection(isl_ctx * ctx,const char * s1,const char * s2)2411 static isl_stat test_coalesce_intersection(isl_ctx *ctx,
2412 	const char *s1, const char *s2)
2413 {
2414 	isl_set *set1, *set2;
2415 
2416 	set1 = isl_set_read_from_str(ctx, s1);
2417 	set2 = isl_set_read_from_str(ctx, s2);
2418 	set1 = isl_set_intersect(set1, set2);
2419 	isl_set_free(isl_set_coalesce(isl_set_copy(set1)));
2420 	set1 = isl_set_coalesce(set1);
2421 	isl_set_free(set1);
2422 
2423 	if (!set1)
2424 		return isl_stat_error;
2425 
2426 	return isl_stat_ok;
2427 }
2428 
2429 /* Check that calling isl_set_coalesce does not leave other sets
2430  * that may share some information with the input to isl_set_coalesce
2431  * in an inconsistent state, for the case where one disjunct
2432  * is a subset of the other.
2433  */
test_coalesce_special4(isl_ctx * ctx)2434 static isl_stat test_coalesce_special4(isl_ctx *ctx)
2435 {
2436 	const char *s1, *s2;
2437 
2438 	s1 = "{ [a, b] : b <= 0 or a <= 1 }";
2439 	s2 = "{ [a, b] : -1 <= -a < b }";
2440 	return test_coalesce_intersection(ctx, s1, s2);
2441 }
2442 
2443 /* Check that calling isl_set_coalesce does not leave other sets
2444  * that may share some information with the input to isl_set_coalesce
2445  * in an inconsistent state, for the case where two disjuncts
2446  * can be fused.
2447  */
test_coalesce_special5(isl_ctx * ctx)2448 static isl_stat test_coalesce_special5(isl_ctx *ctx)
2449 {
2450 	const char *s1, *s2;
2451 
2452 	s1 = "{ [a, b, c] : b <= 0 }";
2453 	s2 = "{ [a, b, c] : -1 <= -a < b and (c >= 0 or c < 0) }";
2454 	return test_coalesce_intersection(ctx, s1, s2);
2455 }
2456 
2457 /* Check that calling isl_set_coalesce does not leave other sets
2458  * that may share some information with the input to isl_set_coalesce
2459  * in an inconsistent state, for the case where two disjuncts
2460  * can be fused and where both disjuncts have implicit equality constraints.
2461  */
test_coalesce_special6(isl_ctx * ctx)2462 static isl_stat test_coalesce_special6(isl_ctx *ctx)
2463 {
2464 	const char *s1, *s2;
2465 
2466 	s1 = "{ [a, b, c] : c <= 0 }";
2467 	s2 = "{ [a, b, c] : 0 <= a <= b <= c or (0 <= b <= c and a > 0) }";
2468 	return test_coalesce_intersection(ctx, s1, s2);
2469 }
2470 
2471 /* Test the functionality of isl_set_coalesce.
2472  * That is, check that the output is always equal to the input
2473  * and in some cases that the result consists of a single disjunct.
2474  */
test_coalesce(struct isl_ctx * ctx)2475 static int test_coalesce(struct isl_ctx *ctx)
2476 {
2477 	int i;
2478 
2479 	for (i = 0; i < ARRAY_SIZE(coalesce_tests); ++i) {
2480 		const char *str = coalesce_tests[i].str;
2481 		int check_one = coalesce_tests[i].single_disjunct;
2482 		if (test_coalesce_set(ctx, str, check_one) < 0)
2483 			return -1;
2484 	}
2485 
2486 	if (test_coalesce_unbounded_wrapping(ctx) < 0)
2487 		return -1;
2488 	if (test_coalesce_special(ctx) < 0)
2489 		return -1;
2490 	if (test_coalesce_special2(ctx) < 0)
2491 		return -1;
2492 	if (test_coalesce_special3(ctx) < 0)
2493 		return -1;
2494 	if (test_coalesce_special4(ctx) < 0)
2495 		return -1;
2496 	if (test_coalesce_special5(ctx) < 0)
2497 		return -1;
2498 	if (test_coalesce_special6(ctx) < 0)
2499 		return -1;
2500 
2501 
2502 	return 0;
2503 }
2504 
2505 /* Construct a representation of the graph on the right of Figure 1
2506  * in "Computing the Transitive Closure of a Union of
2507  * Affine Integer Tuple Relations".
2508  */
cocoa_fig_1_right_graph(isl_ctx * ctx)2509 static __isl_give isl_map *cocoa_fig_1_right_graph(isl_ctx *ctx)
2510 {
2511 	isl_set *dom;
2512 	isl_map *up, *right;
2513 
2514 	dom = isl_set_read_from_str(ctx,
2515 		"{ [x,y] : x >= 0 and -2 x + 3 y >= 0 and x <= 3 and "
2516 			"2 x - 3 y + 3 >= 0 }");
2517 	right = isl_map_read_from_str(ctx,
2518 		"{ [x,y] -> [x2,y2] : x2 = x + 1 and y2 = y }");
2519 	up = isl_map_read_from_str(ctx,
2520 		"{ [x,y] -> [x2,y2] : x2 = x and y2 = y + 1 }");
2521 	right = isl_map_intersect_domain(right, isl_set_copy(dom));
2522 	right = isl_map_intersect_range(right, isl_set_copy(dom));
2523 	up = isl_map_intersect_domain(up, isl_set_copy(dom));
2524 	up = isl_map_intersect_range(up, dom);
2525 	return isl_map_union(up, right);
2526 }
2527 
2528 /* Construct a representation of the power of the graph
2529  * on the right of Figure 1 in "Computing the Transitive Closure of
2530  * a Union of Affine Integer Tuple Relations".
2531  */
cocoa_fig_1_right_power(isl_ctx * ctx)2532 static __isl_give isl_map *cocoa_fig_1_right_power(isl_ctx *ctx)
2533 {
2534 	return isl_map_read_from_str(ctx,
2535 		"{ [1] -> [[0,0] -> [0,1]]; [2] -> [[0,0] -> [1,1]]; "
2536 		"  [1] -> [[0,1] -> [1,1]]; [1] -> [[2,2] -> [3,2]]; "
2537 		"  [2] -> [[2,2] -> [3,3]]; [1] -> [[3,2] -> [3,3]] }");
2538 }
2539 
2540 /* Construct a representation of the transitive closure of the graph
2541  * on the right of Figure 1 in "Computing the Transitive Closure of
2542  * a Union of Affine Integer Tuple Relations".
2543  */
cocoa_fig_1_right_tc(isl_ctx * ctx)2544 static __isl_give isl_map *cocoa_fig_1_right_tc(isl_ctx *ctx)
2545 {
2546 	return isl_set_unwrap(isl_map_range(cocoa_fig_1_right_power(ctx)));
2547 }
2548 
test_closure(isl_ctx * ctx)2549 static int test_closure(isl_ctx *ctx)
2550 {
2551 	const char *str;
2552 	isl_map *map, *map2;
2553 	isl_bool exact, equal;
2554 
2555 	/* COCOA example 1 */
2556 	map = isl_map_read_from_str(ctx,
2557 		"[n] -> { [i,j] -> [i2,j2] : i2 = i + 1 and j2 = j + 1 and "
2558 			"1 <= i and i < n and 1 <= j and j < n or "
2559 			"i2 = i + 1 and j2 = j - 1 and "
2560 			"1 <= i and i < n and 2 <= j and j <= n }");
2561 	map = isl_map_power(map, &exact);
2562 	assert(exact);
2563 	isl_map_free(map);
2564 
2565 	/* COCOA example 1 */
2566 	map = isl_map_read_from_str(ctx,
2567 		"[n] -> { [i,j] -> [i2,j2] : i2 = i + 1 and j2 = j + 1 and "
2568 			"1 <= i and i < n and 1 <= j and j < n or "
2569 			"i2 = i + 1 and j2 = j - 1 and "
2570 			"1 <= i and i < n and 2 <= j and j <= n }");
2571 	map = isl_map_transitive_closure(map, &exact);
2572 	assert(exact);
2573 	map2 = isl_map_read_from_str(ctx,
2574 		"[n] -> { [i,j] -> [i2,j2] : exists (k1,k2,k : "
2575 			"1 <= i and i < n and 1 <= j and j <= n and "
2576 			"2 <= i2 and i2 <= n and 1 <= j2 and j2 <= n and "
2577 			"i2 = i + k1 + k2 and j2 = j + k1 - k2 and "
2578 			"k1 >= 0 and k2 >= 0 and k1 + k2 = k and k >= 1 )}");
2579 	assert(isl_map_is_equal(map, map2));
2580 	isl_map_free(map2);
2581 	isl_map_free(map);
2582 
2583 	map = isl_map_read_from_str(ctx,
2584 		"[n] -> { [x] -> [y] : y = x + 1 and 0 <= x and x <= n and "
2585 				     " 0 <= y and y <= n }");
2586 	map = isl_map_transitive_closure(map, &exact);
2587 	map2 = isl_map_read_from_str(ctx,
2588 		"[n] -> { [x] -> [y] : y > x and 0 <= x and x <= n and "
2589 				     " 0 <= y and y <= n }");
2590 	assert(isl_map_is_equal(map, map2));
2591 	isl_map_free(map2);
2592 	isl_map_free(map);
2593 
2594 	/* COCOA example 2 */
2595 	map = isl_map_read_from_str(ctx,
2596 		"[n] -> { [i,j] -> [i2,j2] : i2 = i + 2 and j2 = j + 2 and "
2597 			"1 <= i and i < n - 1 and 1 <= j and j < n - 1 or "
2598 			"i2 = i + 2 and j2 = j - 2 and "
2599 			"1 <= i and i < n - 1 and 3 <= j and j <= n }");
2600 	map = isl_map_transitive_closure(map, &exact);
2601 	assert(exact);
2602 	map2 = isl_map_read_from_str(ctx,
2603 		"[n] -> { [i,j] -> [i2,j2] : exists (k1,k2,k : "
2604 			"1 <= i and i < n - 1 and 1 <= j and j <= n and "
2605 			"3 <= i2 and i2 <= n and 1 <= j2 and j2 <= n and "
2606 			"i2 = i + 2 k1 + 2 k2 and j2 = j + 2 k1 - 2 k2 and "
2607 			"k1 >= 0 and k2 >= 0 and k1 + k2 = k and k >= 1) }");
2608 	assert(isl_map_is_equal(map, map2));
2609 	isl_map_free(map);
2610 	isl_map_free(map2);
2611 
2612 	/* COCOA Fig.2 left */
2613 	map = isl_map_read_from_str(ctx,
2614 		"[n] -> { [i,j] -> [i2,j2] : i2 = i + 2 and j2 = j and "
2615 			"i <= 2 j - 3 and i <= n - 2 and j <= 2 i - 1 and "
2616 			"j <= n or "
2617 			"i2 = i and j2 = j + 2 and i <= 2 j - 1 and i <= n and "
2618 			"j <= 2 i - 3 and j <= n - 2 or "
2619 			"i2 = i + 1 and j2 = j + 1 and i <= 2 j - 1 and "
2620 			"i <= n - 1 and j <= 2 i - 1 and j <= n - 1 }");
2621 	map = isl_map_transitive_closure(map, &exact);
2622 	assert(exact);
2623 	isl_map_free(map);
2624 
2625 	/* COCOA Fig.2 right */
2626 	map = isl_map_read_from_str(ctx,
2627 		"[n] -> { [i,j] -> [i2,j2] : i2 = i + 3 and j2 = j and "
2628 			"i <= 2 j - 4 and i <= n - 3 and j <= 2 i - 1 and "
2629 			"j <= n or "
2630 			"i2 = i and j2 = j + 3 and i <= 2 j - 1 and i <= n and "
2631 			"j <= 2 i - 4 and j <= n - 3 or "
2632 			"i2 = i + 1 and j2 = j + 1 and i <= 2 j - 1 and "
2633 			"i <= n - 1 and j <= 2 i - 1 and j <= n - 1 }");
2634 	map = isl_map_power(map, &exact);
2635 	assert(exact);
2636 	isl_map_free(map);
2637 
2638 	/* COCOA Fig.2 right */
2639 	map = isl_map_read_from_str(ctx,
2640 		"[n] -> { [i,j] -> [i2,j2] : i2 = i + 3 and j2 = j and "
2641 			"i <= 2 j - 4 and i <= n - 3 and j <= 2 i - 1 and "
2642 			"j <= n or "
2643 			"i2 = i and j2 = j + 3 and i <= 2 j - 1 and i <= n and "
2644 			"j <= 2 i - 4 and j <= n - 3 or "
2645 			"i2 = i + 1 and j2 = j + 1 and i <= 2 j - 1 and "
2646 			"i <= n - 1 and j <= 2 i - 1 and j <= n - 1 }");
2647 	map = isl_map_transitive_closure(map, &exact);
2648 	assert(exact);
2649 	map2 = isl_map_read_from_str(ctx,
2650 		"[n] -> { [i,j] -> [i2,j2] : exists (k1,k2,k3,k : "
2651 			"i <= 2 j - 1 and i <= n and j <= 2 i - 1 and "
2652 			"j <= n and 3 + i + 2 j <= 3 n and "
2653 			"3 + 2 i + j <= 3n and i2 <= 2 j2 -1 and i2 <= n and "
2654 			"i2 <= 3 j2 - 4 and j2 <= 2 i2 -1 and j2 <= n and "
2655 			"13 + 4 j2 <= 11 i2 and i2 = i + 3 k1 + k3 and "
2656 			"j2 = j + 3 k2 + k3 and k1 >= 0 and k2 >= 0 and "
2657 			"k3 >= 0 and k1 + k2 + k3 = k and k > 0) }");
2658 	assert(isl_map_is_equal(map, map2));
2659 	isl_map_free(map2);
2660 	isl_map_free(map);
2661 
2662 	map = cocoa_fig_1_right_graph(ctx);
2663 	map = isl_map_transitive_closure(map, &exact);
2664 	assert(exact);
2665 	map2 = cocoa_fig_1_right_tc(ctx);
2666 	assert(isl_map_is_equal(map, map2));
2667 	isl_map_free(map2);
2668 	isl_map_free(map);
2669 
2670 	map = cocoa_fig_1_right_graph(ctx);
2671 	map = isl_map_power(map, &exact);
2672 	map2 = cocoa_fig_1_right_power(ctx);
2673 	equal = isl_map_is_equal(map, map2);
2674 	isl_map_free(map2);
2675 	isl_map_free(map);
2676 	if (equal < 0)
2677 		return -1;
2678 	if (!exact)
2679 		isl_die(ctx, isl_error_unknown, "power not exact", return -1);
2680 	if (!equal)
2681 		isl_die(ctx, isl_error_unknown, "unexpected power", return -1);
2682 
2683 	/* COCOA Theorem 1 counter example */
2684 	map = isl_map_read_from_str(ctx,
2685 		"{ [i,j] -> [i2,j2] : i = 0 and 0 <= j and j <= 1 and "
2686 			"i2 = 1 and j2 = j or "
2687 			"i = 0 and j = 0 and i2 = 0 and j2 = 1 }");
2688 	map = isl_map_transitive_closure(map, &exact);
2689 	assert(exact);
2690 	isl_map_free(map);
2691 
2692 	map = isl_map_read_from_str(ctx,
2693 		"[m,n] -> { [i,j] -> [i2,j2] : i2 = i and j2 = j + 2 and "
2694 			"1 <= i,i2 <= n and 1 <= j,j2 <= m or "
2695 			"i2 = i + 1 and 3 <= j2 - j <= 4 and "
2696 			"1 <= i,i2 <= n and 1 <= j,j2 <= m }");
2697 	map = isl_map_transitive_closure(map, &exact);
2698 	assert(exact);
2699 	isl_map_free(map);
2700 
2701 	/* Kelly et al 1996, fig 12 */
2702 	map = isl_map_read_from_str(ctx,
2703 		"[n] -> { [i,j] -> [i2,j2] : i2 = i and j2 = j + 1 and "
2704 			"1 <= i,j,j+1 <= n or "
2705 			"j = n and j2 = 1 and i2 = i + 1 and "
2706 			"1 <= i,i+1 <= n }");
2707 	map = isl_map_transitive_closure(map, &exact);
2708 	assert(exact);
2709 	map2 = isl_map_read_from_str(ctx,
2710 		"[n] -> { [i,j] -> [i2,j2] : 1 <= j < j2 <= n and "
2711 			"1 <= i <= n and i = i2 or "
2712 			"1 <= i < i2 <= n and 1 <= j <= n and "
2713 			"1 <= j2 <= n }");
2714 	assert(isl_map_is_equal(map, map2));
2715 	isl_map_free(map2);
2716 	isl_map_free(map);
2717 
2718 	/* Omega's closure4 */
2719 	map = isl_map_read_from_str(ctx,
2720 		"[m,n] -> { [x,y] -> [x2,y2] : x2 = x and y2 = y + 1 and "
2721 			"1 <= x,y <= 10 or "
2722 			"x2 = x + 1 and y2 = y and "
2723 			"1 <= x <= 20 && 5 <= y <= 15 }");
2724 	map = isl_map_transitive_closure(map, &exact);
2725 	assert(exact);
2726 	isl_map_free(map);
2727 
2728 	map = isl_map_read_from_str(ctx,
2729 		"[n] -> { [x] -> [y]: 1 <= n <= y - x <= 10 }");
2730 	map = isl_map_transitive_closure(map, &exact);
2731 	assert(!exact);
2732 	map2 = isl_map_read_from_str(ctx,
2733 		"[n] -> { [x] -> [y] : 1 <= n <= 10 and y >= n + x }");
2734 	assert(isl_map_is_equal(map, map2));
2735 	isl_map_free(map);
2736 	isl_map_free(map2);
2737 
2738 	str = "[n, m] -> { [i0, i1, i2, i3] -> [o0, o1, o2, o3] : "
2739 	    "i3 = 1 and o0 = i0 and o1 = -1 + i1 and o2 = -1 + i2 and "
2740 	    "o3 = -2 + i2 and i1 <= -1 + i0 and i1 >= 1 - m + i0 and "
2741 	    "i1 >= 2 and i1 <= n and i2 >= 3 and i2 <= 1 + n and i2 <= m }";
2742 	map = isl_map_read_from_str(ctx, str);
2743 	map = isl_map_transitive_closure(map, &exact);
2744 	assert(exact);
2745 	map2 = isl_map_read_from_str(ctx, str);
2746 	assert(isl_map_is_equal(map, map2));
2747 	isl_map_free(map);
2748 	isl_map_free(map2);
2749 
2750 	str = "{[0] -> [1]; [2] -> [3]}";
2751 	map = isl_map_read_from_str(ctx, str);
2752 	map = isl_map_transitive_closure(map, &exact);
2753 	assert(exact);
2754 	map2 = isl_map_read_from_str(ctx, str);
2755 	assert(isl_map_is_equal(map, map2));
2756 	isl_map_free(map);
2757 	isl_map_free(map2);
2758 
2759 	str = "[n] -> { [[i0, i1, 1, 0, i0] -> [i5, 1]] -> "
2760 	    "[[i0, -1 + i1, 2, 0, i0] -> [-1 + i5, 2]] : "
2761 	    "exists (e0 = [(3 - n)/3]: i5 >= 2 and i1 >= 2 and "
2762 	    "3i0 <= -1 + n and i1 <= -1 + n and i5 <= -1 + n and "
2763 	    "3e0 >= 1 - n and 3e0 <= 2 - n and 3i0 >= -2 + n); "
2764 	    "[[i0, i1, 2, 0, i0] -> [i5, 1]] -> "
2765 	    "[[i0, i1, 1, 0, i0] -> [-1 + i5, 2]] : "
2766 	    "exists (e0 = [(3 - n)/3]: i5 >= 2 and i1 >= 1 and "
2767 	    "3i0 <= -1 + n and i1 <= -1 + n and i5 <= -1 + n and "
2768 	    "3e0 >= 1 - n and 3e0 <= 2 - n and 3i0 >= -2 + n); "
2769 	    "[[i0, i1, 1, 0, i0] -> [i5, 2]] -> "
2770 	    "[[i0, -1 + i1, 2, 0, i0] -> [i5, 1]] : "
2771 	    "exists (e0 = [(3 - n)/3]: i1 >= 2 and i5 >= 1 and "
2772 	    "3i0 <= -1 + n and i1 <= -1 + n and i5 <= -1 + n and "
2773 	    "3e0 >= 1 - n and 3e0 <= 2 - n and 3i0 >= -2 + n); "
2774 	    "[[i0, i1, 2, 0, i0] -> [i5, 2]] -> "
2775 	    "[[i0, i1, 1, 0, i0] -> [i5, 1]] : "
2776 	    "exists (e0 = [(3 - n)/3]: i5 >= 1 and i1 >= 1 and "
2777 	    "3i0 <= -1 + n and i1 <= -1 + n and i5 <= -1 + n and "
2778 	    "3e0 >= 1 - n and 3e0 <= 2 - n and 3i0 >= -2 + n) }";
2779 	map = isl_map_read_from_str(ctx, str);
2780 	map = isl_map_transitive_closure(map, NULL);
2781 	assert(map);
2782 	isl_map_free(map);
2783 
2784 	return 0;
2785 }
2786 
2787 /* Check that the actual result of a boolean operation is equal
2788  * to the expected result.
2789  */
check_bool(isl_ctx * ctx,isl_bool actual,isl_bool expected)2790 static isl_stat check_bool(isl_ctx *ctx, isl_bool actual, isl_bool expected)
2791 {
2792 	if (actual != expected)
2793 		isl_die(ctx, isl_error_unknown,
2794 			"incorrect boolean operation", return isl_stat_error);
2795 	return isl_stat_ok;
2796 }
2797 
2798 /* Test operations on isl_bool values.
2799  *
2800  * This tests:
2801  *
2802  * 	isl_bool_not
2803  * 	isl_bool_ok
2804  */
test_isl_bool(isl_ctx * ctx)2805 static int test_isl_bool(isl_ctx *ctx)
2806 {
2807 	if (check_bool(ctx, isl_bool_not(isl_bool_true), isl_bool_false) < 0)
2808 		return -1;
2809 	if (check_bool(ctx, isl_bool_not(isl_bool_false), isl_bool_true) < 0)
2810 		return -1;
2811 	if (check_bool(ctx, isl_bool_not(isl_bool_error), isl_bool_error) < 0)
2812 		return -1;
2813 	if (check_bool(ctx, isl_bool_ok(0), isl_bool_false) < 0)
2814 		return -1;
2815 	if (check_bool(ctx, isl_bool_ok(1), isl_bool_true) < 0)
2816 		return -1;
2817 	if (check_bool(ctx, isl_bool_ok(-1), isl_bool_true) < 0)
2818 		return -1;
2819 	if (check_bool(ctx, isl_bool_ok(2), isl_bool_true) < 0)
2820 		return -1;
2821 	if (check_bool(ctx, isl_bool_ok(-2), isl_bool_true) < 0)
2822 		return -1;
2823 
2824 	return 0;
2825 }
2826 
test_lex(struct isl_ctx * ctx)2827 static int test_lex(struct isl_ctx *ctx)
2828 {
2829 	isl_space *dim;
2830 	isl_map *map;
2831 	int empty;
2832 
2833 	dim = isl_space_set_alloc(ctx, 0, 0);
2834 	map = isl_map_lex_le(dim);
2835 	empty = isl_map_is_empty(map);
2836 	isl_map_free(map);
2837 
2838 	if (empty < 0)
2839 		return -1;
2840 	if (empty)
2841 		isl_die(ctx, isl_error_unknown,
2842 			"expecting non-empty result", return -1);
2843 
2844 	return 0;
2845 }
2846 
2847 /* Inputs for isl_map_lexmin tests.
2848  * "map" is the input and "lexmin" is the expected result.
2849  */
2850 struct {
2851 	const char *map;
2852 	const char *lexmin;
2853 } lexmin_tests [] = {
2854 	{ "{ [x] -> [y] : x <= y <= 10; [x] -> [5] : -8 <= x <= 8 }",
2855 	  "{ [x] -> [5] : 6 <= x <= 8; "
2856 	    "[x] -> [x] : x <= 5 or (9 <= x <= 10) }" },
2857 	{ "{ [x] -> [y] : 4y = x or 4y = -1 + x or 4y = -2 + x }",
2858 	  "{ [x] -> [y] : 4y = x or 4y = -1 + x or 4y = -2 + x }" },
2859 	{ "{ [x] -> [y] : x = 4y; [x] -> [y] : x = 2y }",
2860 	  "{ [x] -> [y] : (4y = x and x >= 0) or "
2861 		"(exists (e0 = [(x)/4], e1 = [(-2 + x)/4]: 2y = x and "
2862 		"4e1 = -2 + x and 4e0 <= -1 + x and 4e0 >= -3 + x)) or "
2863 		"(exists (e0 = [(x)/4]: 2y = x and 4e0 = x and x <= -4)) }" },
2864 	{ "{ T[a] -> S[b, c] : a = 4b-2c and c >= b }",
2865 	  "{ T[a] -> S[b, c] : 2b = a and 2c = a }" },
2866 	/* Check that empty pieces are properly combined. */
2867 	{ "[K, N] -> { [x, y] -> [a, b] : K+2<=N<=K+4 and x>=4 and "
2868 		"2N-6<=x<K+N and N-1<=a<=K+N-1 and N+b-6<=a<=2N-4 and "
2869 		"b<=2N-3K+a and 3b<=4N-K+1 and b>=N and a>=x+1 }",
2870 	  "[K, N] -> { [x, y] -> [1 + x, N] : x >= -6 + 2N and "
2871 		"x <= -5 + 2N and x >= -1 + 3K - N and x <= -2 + K + N and "
2872 		"x >= 4 }" },
2873 	{ "{ [i, k, j] -> [a, b, c, d] : 8*floor((b)/8) = b and k <= 255 and "
2874 		"a <= 255 and c <= 255 and d <= 255 - j and "
2875 		"255 - j <= 7d <= 7 - i and 240d <= 239 + a and "
2876 		"247d <= 247 + k - j and 247d <= 247 + k - b and "
2877 		"247d <= 247 + i and 248 - b <= 248d <= c and "
2878 		"254d >= i - a + b and 254d >= -a + b and "
2879 		"255d >= -i + a - b and 1792d >= -63736 + 257b }",
2880 	  "{ [i, k, j] -> "
2881 	    "[-127762 + i + 502j, -62992 + 248j, 63240 - 248j, 255 - j] : "
2882 		"k <= 255 and 7j >= 1778 + i and 246j >= 62738 - k and "
2883 		"247j >= 62738 - i and 509j <= 129795 + i and "
2884 		"742j >= 188724 - i; "
2885 	    "[0, k, j] -> [1, 0, 248, 1] : k <= 255 and 248 <= j <= 254, k }" },
2886 	{ "{ [a] -> [b] : 0 <= b <= 255 and -509 + a <= 512b < a and "
2887 			"16*floor((8 + b)/16) <= 7 + b; "
2888 	    "[a] -> [1] }",
2889 	  "{ [a] -> [b = 1] : a >= 510 or a <= 0; "
2890 	    "[a] -> [b = 0] : 0 < a <= 509 }" },
2891 	{ "{ rat: [i] : 1 <= 2i <= 9 }", "{ rat: [i] : 2i = 1 }" },
2892 	{ "{ rat: [i] : 1 <= 2i <= 9 or i >= 10 }", "{ rat: [i] : 2i = 1 }" },
2893 };
2894 
test_lexmin(struct isl_ctx * ctx)2895 static int test_lexmin(struct isl_ctx *ctx)
2896 {
2897 	int i;
2898 	int equal;
2899 	const char *str;
2900 	isl_basic_map *bmap;
2901 	isl_map *map, *map2;
2902 	isl_set *set;
2903 	isl_set *set2;
2904 	isl_pw_multi_aff *pma;
2905 
2906 	str = "[p0, p1] -> { [] -> [] : "
2907 	    "exists (e0 = [(2p1)/3], e1, e2, e3 = [(3 - p1 + 3e0)/3], "
2908 	    "e4 = [(p1)/3], e5 = [(p1 + 3e4)/3]: "
2909 	    "3e0 >= -2 + 2p1 and 3e0 >= p1 and 3e3 >= 1 - p1 + 3e0 and "
2910 	    "3e0 <= 2p1 and 3e3 >= -2 + p1 and 3e3 <= -1 + p1 and p1 >= 3 and "
2911 	    "3e5 >= -2 + 2p1 and 3e5 >= p1 and 3e5 <= -1 + p1 + 3e4 and "
2912 	    "3e4 <= p1 and 3e4 >= -2 + p1 and e3 <= -1 + e0 and "
2913 	    "3e4 >= 6 - p1 + 3e1 and 3e1 >= p1 and 3e5 >= -2 + p1 + 3e4 and "
2914 	    "2e4 >= 3 - p1 + 2e1 and e4 <= e1 and 3e3 <= 2 - p1 + 3e0 and "
2915 	    "e5 >= 1 + e1 and 3e4 >= 6 - 2p1 + 3e1 and "
2916 	    "p0 >= 2 and p1 >= p0 and 3e2 >= p1 and 3e4 >= 6 - p1 + 3e2 and "
2917 	    "e2 <= e1 and e3 >= 1 and e4 <= e2) }";
2918 	map = isl_map_read_from_str(ctx, str);
2919 	map = isl_map_lexmin(map);
2920 	isl_map_free(map);
2921 	if (!map)
2922 		return -1;
2923 
2924 	str = "[C] -> { [obj,a,b,c] : obj <= 38 a + 7 b + 10 c and "
2925 	    "a + b <= 1 and c <= 10 b and c <= C and a,b,c,C >= 0 }";
2926 	set = isl_set_read_from_str(ctx, str);
2927 	set = isl_set_lexmax(set);
2928 	str = "[C] -> { [obj,a,b,c] : C = 8 }";
2929 	set2 = isl_set_read_from_str(ctx, str);
2930 	set = isl_set_intersect(set, set2);
2931 	assert(!isl_set_is_empty(set));
2932 	isl_set_free(set);
2933 
2934 	for (i = 0; i < ARRAY_SIZE(lexmin_tests); ++i) {
2935 		map = isl_map_read_from_str(ctx, lexmin_tests[i].map);
2936 		map = isl_map_lexmin(map);
2937 		map2 = isl_map_read_from_str(ctx, lexmin_tests[i].lexmin);
2938 		equal = isl_map_is_equal(map, map2);
2939 		isl_map_free(map);
2940 		isl_map_free(map2);
2941 
2942 		if (equal < 0)
2943 			return -1;
2944 		if (!equal)
2945 			isl_die(ctx, isl_error_unknown,
2946 				"unexpected result", return -1);
2947 	}
2948 
2949 	str = "{ [i] -> [i', j] : j = i - 8i' and i' >= 0 and i' <= 7 and "
2950 				" 8i' <= i and 8i' >= -7 + i }";
2951 	bmap = isl_basic_map_read_from_str(ctx, str);
2952 	pma = isl_basic_map_lexmin_pw_multi_aff(isl_basic_map_copy(bmap));
2953 	map2 = isl_map_from_pw_multi_aff(pma);
2954 	map = isl_map_from_basic_map(bmap);
2955 	assert(isl_map_is_equal(map, map2));
2956 	isl_map_free(map);
2957 	isl_map_free(map2);
2958 
2959 	str = "[i] -> { [i', j] : j = i - 8i' and i' >= 0 and i' <= 7 and "
2960 				" 8i' <= i and 8i' >= -7 + i }";
2961 	set = isl_set_read_from_str(ctx, str);
2962 	pma = isl_set_lexmin_pw_multi_aff(isl_set_copy(set));
2963 	set2 = isl_set_from_pw_multi_aff(pma);
2964 	equal = isl_set_is_equal(set, set2);
2965 	isl_set_free(set);
2966 	isl_set_free(set2);
2967 	if (equal < 0)
2968 		return -1;
2969 	if (!equal)
2970 		isl_die(ctx, isl_error_unknown,
2971 			"unexpected difference between set and "
2972 			"piecewise affine expression", return -1);
2973 
2974 	return 0;
2975 }
2976 
2977 /* A specialized isl_set_min_val test case that would return the wrong result
2978  * in earlier versions of isl.
2979  * The explicit call to isl_basic_set_union prevents the second basic set
2980  * from being determined to be empty prior to the call to isl_set_min_val,
2981  * at least at the point where this test case was introduced.
2982  */
test_min_special(isl_ctx * ctx)2983 static int test_min_special(isl_ctx *ctx)
2984 {
2985 	const char *str;
2986 	isl_basic_set *bset1, *bset2;
2987 	isl_set *set;
2988 	isl_aff *obj;
2989 	isl_val *res;
2990 	int ok;
2991 
2992 	str = "{ [a, b] : a >= 2 and b >= 0 and 14 - a <= b <= 9 }";
2993 	bset1 = isl_basic_set_read_from_str(ctx, str);
2994 	str = "{ [a, b] : 1 <= a, b and a + b <= 1 }";
2995 	bset2 = isl_basic_set_read_from_str(ctx, str);
2996 	set = isl_basic_set_union(bset1, bset2);
2997 	obj = isl_aff_read_from_str(ctx, "{ [a, b] -> [a] }");
2998 
2999 	res = isl_set_min_val(set, obj);
3000 	ok = isl_val_cmp_si(res, 5) == 0;
3001 
3002 	isl_aff_free(obj);
3003 	isl_set_free(set);
3004 	isl_val_free(res);
3005 
3006 	if (!res)
3007 		return -1;
3008 	if (!ok)
3009 		isl_die(ctx, isl_error_unknown, "unexpected minimum",
3010 			return -1);
3011 
3012 	return 0;
3013 }
3014 
3015 /* A specialized isl_set_min_val test case that would return an error
3016  * in earlier versions of isl.
3017  */
test_min_special2(isl_ctx * ctx)3018 static int test_min_special2(isl_ctx *ctx)
3019 {
3020 	const char *str;
3021 	isl_basic_set *bset;
3022 	isl_aff *obj;
3023 	isl_val *res;
3024 
3025 	str = "{ [i, j, k] : 2j = i and 2k = i + 1 and i >= 2 }";
3026 	bset = isl_basic_set_read_from_str(ctx, str);
3027 
3028 	obj = isl_aff_read_from_str(ctx, "{ [i, j, k] -> [i] }");
3029 
3030 	res = isl_basic_set_max_val(bset, obj);
3031 
3032 	isl_basic_set_free(bset);
3033 	isl_aff_free(obj);
3034 	isl_val_free(res);
3035 
3036 	if (!res)
3037 		return -1;
3038 
3039 	return 0;
3040 }
3041 
3042 struct {
3043 	const char *set;
3044 	const char *obj;
3045 	__isl_give isl_val *(*fn)(__isl_keep isl_set *set,
3046 		__isl_keep isl_aff *obj);
3047 	const char *res;
3048 } opt_tests[] = {
3049 	{ "{ [-1]; [1] }", "{ [x] -> [x] }", &isl_set_min_val, "-1" },
3050 	{ "{ [-1]; [1] }", "{ [x] -> [x] }", &isl_set_max_val, "1" },
3051 	{ "{ [a, b] : 0 <= a, b <= 100 and b mod 2 = 0}",
3052 	  "{ [a, b] -> [floor((b - 2*floor((-a)/4))/5)] }",
3053 	  &isl_set_max_val, "30" },
3054 
3055 };
3056 
3057 /* Perform basic isl_set_min_val and isl_set_max_val tests.
3058  * In particular, check the results on non-convex inputs.
3059  */
test_min(struct isl_ctx * ctx)3060 static int test_min(struct isl_ctx *ctx)
3061 {
3062 	int i;
3063 	isl_set *set;
3064 	isl_aff *obj;
3065 	isl_val *val, *res;
3066 	isl_bool ok;
3067 
3068 	for (i = 0; i < ARRAY_SIZE(opt_tests); ++i) {
3069 		set = isl_set_read_from_str(ctx, opt_tests[i].set);
3070 		obj = isl_aff_read_from_str(ctx, opt_tests[i].obj);
3071 		res = isl_val_read_from_str(ctx, opt_tests[i].res);
3072 		val = opt_tests[i].fn(set, obj);
3073 		ok = isl_val_eq(res, val);
3074 		isl_val_free(res);
3075 		isl_val_free(val);
3076 		isl_aff_free(obj);
3077 		isl_set_free(set);
3078 
3079 		if (ok < 0)
3080 			return -1;
3081 		if (!ok)
3082 			isl_die(ctx, isl_error_unknown,
3083 				"unexpected optimum", return -1);
3084 	}
3085 
3086 	if (test_min_special(ctx) < 0)
3087 		return -1;
3088 	if (test_min_special2(ctx) < 0)
3089 		return -1;
3090 
3091 	return 0;
3092 }
3093 
3094 struct must_may {
3095 	isl_map *must;
3096 	isl_map *may;
3097 };
3098 
collect_must_may(__isl_take isl_map * dep,int must,void * dep_user,void * user)3099 static isl_stat collect_must_may(__isl_take isl_map *dep, int must,
3100 	void *dep_user, void *user)
3101 {
3102 	struct must_may *mm = (struct must_may *)user;
3103 
3104 	if (must)
3105 		mm->must = isl_map_union(mm->must, dep);
3106 	else
3107 		mm->may = isl_map_union(mm->may, dep);
3108 
3109 	return isl_stat_ok;
3110 }
3111 
common_space(void * first,void * second)3112 static int common_space(void *first, void *second)
3113 {
3114 	int depth = *(int *)first;
3115 	return 2 * depth;
3116 }
3117 
map_is_equal(__isl_keep isl_map * map,const char * str)3118 static int map_is_equal(__isl_keep isl_map *map, const char *str)
3119 {
3120 	isl_map *map2;
3121 	int equal;
3122 
3123 	if (!map)
3124 		return -1;
3125 
3126 	map2 = isl_map_read_from_str(map->ctx, str);
3127 	equal = isl_map_is_equal(map, map2);
3128 	isl_map_free(map2);
3129 
3130 	return equal;
3131 }
3132 
map_check_equal(__isl_keep isl_map * map,const char * str)3133 static int map_check_equal(__isl_keep isl_map *map, const char *str)
3134 {
3135 	int equal;
3136 
3137 	equal = map_is_equal(map, str);
3138 	if (equal < 0)
3139 		return -1;
3140 	if (!equal)
3141 		isl_die(isl_map_get_ctx(map), isl_error_unknown,
3142 			"result not as expected", return -1);
3143 	return 0;
3144 }
3145 
3146 /* Is "set" equal to the set described by "str"?
3147  */
set_is_equal(__isl_keep isl_set * set,const char * str)3148 static isl_bool set_is_equal(__isl_keep isl_set *set, const char *str)
3149 {
3150 	isl_set *set2;
3151 	isl_bool equal;
3152 
3153 	if (!set)
3154 		return isl_bool_error;
3155 
3156 	set2 = isl_set_read_from_str(isl_set_get_ctx(set), str);
3157 	equal = isl_set_is_equal(set, set2);
3158 	isl_set_free(set2);
3159 
3160 	return equal;
3161 }
3162 
3163 /* Check that "set" is equal to the set described by "str".
3164  */
set_check_equal(__isl_keep isl_set * set,const char * str)3165 static isl_stat set_check_equal(__isl_keep isl_set *set, const char *str)
3166 {
3167 	isl_bool equal;
3168 
3169 	equal = set_is_equal(set, str);
3170 	if (equal < 0)
3171 		return isl_stat_error;
3172 	if (!equal)
3173 		isl_die(isl_set_get_ctx(set), isl_error_unknown,
3174 			"result not as expected", return isl_stat_error);
3175 	return isl_stat_ok;
3176 }
3177 
3178 /* Is "uset" equal to the union set described by "str"?
3179  */
uset_is_equal(__isl_keep isl_union_set * uset,const char * str)3180 static isl_bool uset_is_equal(__isl_keep isl_union_set *uset, const char *str)
3181 {
3182 	isl_union_set *uset2;
3183 	isl_bool equal;
3184 
3185 	if (!uset)
3186 		return isl_bool_error;
3187 
3188 	uset2 = isl_union_set_read_from_str(isl_union_set_get_ctx(uset), str);
3189 	equal = isl_union_set_is_equal(uset, uset2);
3190 	isl_union_set_free(uset2);
3191 
3192 	return equal;
3193 }
3194 
3195 /* Check that "uset" is equal to the union set described by "str".
3196  */
uset_check_equal(__isl_keep isl_union_set * uset,const char * str)3197 static isl_stat uset_check_equal(__isl_keep isl_union_set *uset,
3198 	const char *str)
3199 {
3200 	isl_bool equal;
3201 
3202 	equal = uset_is_equal(uset, str);
3203 	if (equal < 0)
3204 		return isl_stat_error;
3205 	if (!equal)
3206 		isl_die(isl_union_set_get_ctx(uset), isl_error_unknown,
3207 			"result not as expected", return isl_stat_error);
3208 	return isl_stat_ok;
3209 }
3210 
test_dep(struct isl_ctx * ctx)3211 static int test_dep(struct isl_ctx *ctx)
3212 {
3213 	const char *str;
3214 	isl_space *dim;
3215 	isl_map *map;
3216 	isl_access_info *ai;
3217 	isl_flow *flow;
3218 	int depth;
3219 	struct must_may mm;
3220 
3221 	depth = 3;
3222 
3223 	str = "{ [2,i,0] -> [i] : 0 <= i <= 10 }";
3224 	map = isl_map_read_from_str(ctx, str);
3225 	ai = isl_access_info_alloc(map, &depth, &common_space, 2);
3226 
3227 	str = "{ [0,i,0] -> [i] : 0 <= i <= 10 }";
3228 	map = isl_map_read_from_str(ctx, str);
3229 	ai = isl_access_info_add_source(ai, map, 1, &depth);
3230 
3231 	str = "{ [1,i,0] -> [5] : 0 <= i <= 10 }";
3232 	map = isl_map_read_from_str(ctx, str);
3233 	ai = isl_access_info_add_source(ai, map, 1, &depth);
3234 
3235 	flow = isl_access_info_compute_flow(ai);
3236 	dim = isl_space_alloc(ctx, 0, 3, 3);
3237 	mm.must = isl_map_empty(isl_space_copy(dim));
3238 	mm.may = isl_map_empty(dim);
3239 
3240 	isl_flow_foreach(flow, collect_must_may, &mm);
3241 
3242 	str = "{ [0,i,0] -> [2,i,0] : (0 <= i <= 4) or (6 <= i <= 10); "
3243 	      "  [1,10,0] -> [2,5,0] }";
3244 	assert(map_is_equal(mm.must, str));
3245 	str = "{ [i,j,k] -> [l,m,n] : 1 = 0 }";
3246 	assert(map_is_equal(mm.may, str));
3247 
3248 	isl_map_free(mm.must);
3249 	isl_map_free(mm.may);
3250 	isl_flow_free(flow);
3251 
3252 
3253 	str = "{ [2,i,0] -> [i] : 0 <= i <= 10 }";
3254 	map = isl_map_read_from_str(ctx, str);
3255 	ai = isl_access_info_alloc(map, &depth, &common_space, 2);
3256 
3257 	str = "{ [0,i,0] -> [i] : 0 <= i <= 10 }";
3258 	map = isl_map_read_from_str(ctx, str);
3259 	ai = isl_access_info_add_source(ai, map, 1, &depth);
3260 
3261 	str = "{ [1,i,0] -> [5] : 0 <= i <= 10 }";
3262 	map = isl_map_read_from_str(ctx, str);
3263 	ai = isl_access_info_add_source(ai, map, 0, &depth);
3264 
3265 	flow = isl_access_info_compute_flow(ai);
3266 	dim = isl_space_alloc(ctx, 0, 3, 3);
3267 	mm.must = isl_map_empty(isl_space_copy(dim));
3268 	mm.may = isl_map_empty(dim);
3269 
3270 	isl_flow_foreach(flow, collect_must_may, &mm);
3271 
3272 	str = "{ [0,i,0] -> [2,i,0] : (0 <= i <= 4) or (6 <= i <= 10) }";
3273 	assert(map_is_equal(mm.must, str));
3274 	str = "{ [0,5,0] -> [2,5,0]; [1,i,0] -> [2,5,0] : 0 <= i <= 10 }";
3275 	assert(map_is_equal(mm.may, str));
3276 
3277 	isl_map_free(mm.must);
3278 	isl_map_free(mm.may);
3279 	isl_flow_free(flow);
3280 
3281 
3282 	str = "{ [2,i,0] -> [i] : 0 <= i <= 10 }";
3283 	map = isl_map_read_from_str(ctx, str);
3284 	ai = isl_access_info_alloc(map, &depth, &common_space, 2);
3285 
3286 	str = "{ [0,i,0] -> [i] : 0 <= i <= 10 }";
3287 	map = isl_map_read_from_str(ctx, str);
3288 	ai = isl_access_info_add_source(ai, map, 0, &depth);
3289 
3290 	str = "{ [1,i,0] -> [5] : 0 <= i <= 10 }";
3291 	map = isl_map_read_from_str(ctx, str);
3292 	ai = isl_access_info_add_source(ai, map, 0, &depth);
3293 
3294 	flow = isl_access_info_compute_flow(ai);
3295 	dim = isl_space_alloc(ctx, 0, 3, 3);
3296 	mm.must = isl_map_empty(isl_space_copy(dim));
3297 	mm.may = isl_map_empty(dim);
3298 
3299 	isl_flow_foreach(flow, collect_must_may, &mm);
3300 
3301 	str = "{ [0,i,0] -> [2,i,0] : 0 <= i <= 10; "
3302 	      "  [1,i,0] -> [2,5,0] : 0 <= i <= 10 }";
3303 	assert(map_is_equal(mm.may, str));
3304 	str = "{ [i,j,k] -> [l,m,n] : 1 = 0 }";
3305 	assert(map_is_equal(mm.must, str));
3306 
3307 	isl_map_free(mm.must);
3308 	isl_map_free(mm.may);
3309 	isl_flow_free(flow);
3310 
3311 
3312 	str = "{ [0,i,2] -> [i] : 0 <= i <= 10 }";
3313 	map = isl_map_read_from_str(ctx, str);
3314 	ai = isl_access_info_alloc(map, &depth, &common_space, 2);
3315 
3316 	str = "{ [0,i,0] -> [i] : 0 <= i <= 10 }";
3317 	map = isl_map_read_from_str(ctx, str);
3318 	ai = isl_access_info_add_source(ai, map, 0, &depth);
3319 
3320 	str = "{ [0,i,1] -> [5] : 0 <= i <= 10 }";
3321 	map = isl_map_read_from_str(ctx, str);
3322 	ai = isl_access_info_add_source(ai, map, 0, &depth);
3323 
3324 	flow = isl_access_info_compute_flow(ai);
3325 	dim = isl_space_alloc(ctx, 0, 3, 3);
3326 	mm.must = isl_map_empty(isl_space_copy(dim));
3327 	mm.may = isl_map_empty(dim);
3328 
3329 	isl_flow_foreach(flow, collect_must_may, &mm);
3330 
3331 	str = "{ [0,i,0] -> [0,i,2] : 0 <= i <= 10; "
3332 	      "  [0,i,1] -> [0,5,2] : 0 <= i <= 5 }";
3333 	assert(map_is_equal(mm.may, str));
3334 	str = "{ [i,j,k] -> [l,m,n] : 1 = 0 }";
3335 	assert(map_is_equal(mm.must, str));
3336 
3337 	isl_map_free(mm.must);
3338 	isl_map_free(mm.may);
3339 	isl_flow_free(flow);
3340 
3341 
3342 	str = "{ [0,i,1] -> [i] : 0 <= i <= 10 }";
3343 	map = isl_map_read_from_str(ctx, str);
3344 	ai = isl_access_info_alloc(map, &depth, &common_space, 2);
3345 
3346 	str = "{ [0,i,0] -> [i] : 0 <= i <= 10 }";
3347 	map = isl_map_read_from_str(ctx, str);
3348 	ai = isl_access_info_add_source(ai, map, 0, &depth);
3349 
3350 	str = "{ [0,i,2] -> [5] : 0 <= i <= 10 }";
3351 	map = isl_map_read_from_str(ctx, str);
3352 	ai = isl_access_info_add_source(ai, map, 0, &depth);
3353 
3354 	flow = isl_access_info_compute_flow(ai);
3355 	dim = isl_space_alloc(ctx, 0, 3, 3);
3356 	mm.must = isl_map_empty(isl_space_copy(dim));
3357 	mm.may = isl_map_empty(dim);
3358 
3359 	isl_flow_foreach(flow, collect_must_may, &mm);
3360 
3361 	str = "{ [0,i,0] -> [0,i,1] : 0 <= i <= 10; "
3362 	      "  [0,i,2] -> [0,5,1] : 0 <= i <= 4 }";
3363 	assert(map_is_equal(mm.may, str));
3364 	str = "{ [i,j,k] -> [l,m,n] : 1 = 0 }";
3365 	assert(map_is_equal(mm.must, str));
3366 
3367 	isl_map_free(mm.must);
3368 	isl_map_free(mm.may);
3369 	isl_flow_free(flow);
3370 
3371 
3372 	depth = 5;
3373 
3374 	str = "{ [1,i,0,0,0] -> [i,j] : 0 <= i <= 10 and 0 <= j <= 10 }";
3375 	map = isl_map_read_from_str(ctx, str);
3376 	ai = isl_access_info_alloc(map, &depth, &common_space, 1);
3377 
3378 	str = "{ [0,i,0,j,0] -> [i,j] : 0 <= i <= 10 and 0 <= j <= 10 }";
3379 	map = isl_map_read_from_str(ctx, str);
3380 	ai = isl_access_info_add_source(ai, map, 1, &depth);
3381 
3382 	flow = isl_access_info_compute_flow(ai);
3383 	dim = isl_space_alloc(ctx, 0, 5, 5);
3384 	mm.must = isl_map_empty(isl_space_copy(dim));
3385 	mm.may = isl_map_empty(dim);
3386 
3387 	isl_flow_foreach(flow, collect_must_may, &mm);
3388 
3389 	str = "{ [0,i,0,j,0] -> [1,i,0,0,0] : 0 <= i,j <= 10 }";
3390 	assert(map_is_equal(mm.must, str));
3391 	str = "{ [0,0,0,0,0] -> [0,0,0,0,0] : 1 = 0 }";
3392 	assert(map_is_equal(mm.may, str));
3393 
3394 	isl_map_free(mm.must);
3395 	isl_map_free(mm.may);
3396 	isl_flow_free(flow);
3397 
3398 	return 0;
3399 }
3400 
3401 /* Check that the dependence analysis proceeds without errors.
3402  * Earlier versions of isl would break down during the analysis
3403  * due to the use of the wrong spaces.
3404  */
test_flow(isl_ctx * ctx)3405 static int test_flow(isl_ctx *ctx)
3406 {
3407 	const char *str;
3408 	isl_union_map *access, *schedule;
3409 	isl_union_map *must_dep, *may_dep;
3410 	int r;
3411 
3412 	str = "{ S0[j] -> i[]; S1[j,i] -> i[]; S2[] -> i[]; S3[] -> i[] }";
3413 	access = isl_union_map_read_from_str(ctx, str);
3414 	str = "{ S0[j] -> [0,j,0,0] : 0 <= j < 10; "
3415 		"S1[j,i] -> [0,j,1,i] : 0 <= j < i < 10; "
3416 		"S2[] -> [1,0,0,0]; "
3417 		"S3[] -> [-1,0,0,0] }";
3418 	schedule = isl_union_map_read_from_str(ctx, str);
3419 	r = isl_union_map_compute_flow(access, isl_union_map_copy(access),
3420 					isl_union_map_copy(access), schedule,
3421 					&must_dep, &may_dep, NULL, NULL);
3422 	isl_union_map_free(may_dep);
3423 	isl_union_map_free(must_dep);
3424 
3425 	return r;
3426 }
3427 
3428 struct {
3429 	const char *map;
3430 	int sv;
3431 } sv_tests[] = {
3432 	{ "[N] -> { [i] -> [f] : 0 <= i <= N and 0 <= i - 10 f <= 9 }", 1 },
3433 	{ "[N] -> { [i] -> [f] : 0 <= i <= N and 0 <= i - 10 f <= 10 }", 0 },
3434 	{ "{ [i] -> [3*floor(i/2) + 5*floor(i/3)] }", 1 },
3435 	{ "{ S1[i] -> [i] : 0 <= i <= 9; S2[i] -> [i] : 0 <= i <= 9 }", 1 },
3436 	{ "{ [i] -> S1[i] : 0 <= i <= 9; [i] -> S2[i] : 0 <= i <= 9 }", 0 },
3437 	{ "{ A[i] -> [i]; B[i] -> [i]; B[i] -> [i + 1] }", 0 },
3438 	{ "{ A[i] -> [i]; B[i] -> [i] : i < 0; B[i] -> [i + 1] : i > 0 }", 1 },
3439 	{ "{ A[i] -> [i]; B[i] -> A[i] : i < 0; B[i] -> [i + 1] : i > 0 }", 1 },
3440 	{ "{ A[i] -> [i]; B[i] -> [j] : i - 1 <= j <= i }", 0 },
3441 };
3442 
test_sv(isl_ctx * ctx)3443 int test_sv(isl_ctx *ctx)
3444 {
3445 	isl_union_map *umap;
3446 	int i;
3447 	int sv;
3448 
3449 	for (i = 0; i < ARRAY_SIZE(sv_tests); ++i) {
3450 		umap = isl_union_map_read_from_str(ctx, sv_tests[i].map);
3451 		sv = isl_union_map_is_single_valued(umap);
3452 		isl_union_map_free(umap);
3453 		if (sv < 0)
3454 			return -1;
3455 		if (sv_tests[i].sv && !sv)
3456 			isl_die(ctx, isl_error_internal,
3457 				"map not detected as single valued", return -1);
3458 		if (!sv_tests[i].sv && sv)
3459 			isl_die(ctx, isl_error_internal,
3460 				"map detected as single valued", return -1);
3461 	}
3462 
3463 	return 0;
3464 }
3465 
3466 struct {
3467 	const char *str;
3468 	int bijective;
3469 } bijective_tests[] = {
3470 	{ "[N,M]->{[i,j] -> [i]}", 0 },
3471 	{ "[N,M]->{[i,j] -> [i] : j=i}", 1 },
3472 	{ "[N,M]->{[i,j] -> [i] : j=0}", 1 },
3473 	{ "[N,M]->{[i,j] -> [i] : j=N}", 1 },
3474 	{ "[N,M]->{[i,j] -> [j,i]}", 1 },
3475 	{ "[N,M]->{[i,j] -> [i+j]}", 0 },
3476 	{ "[N,M]->{[i,j] -> []}", 0 },
3477 	{ "[N,M]->{[i,j] -> [i,j,N]}", 1 },
3478 	{ "[N,M]->{[i,j] -> [2i]}", 0 },
3479 	{ "[N,M]->{[i,j] -> [i,i]}", 0 },
3480 	{ "[N,M]->{[i,j] -> [2i,i]}", 0 },
3481 	{ "[N,M]->{[i,j] -> [2i,j]}", 1 },
3482 	{ "[N,M]->{[i,j] -> [x,y] : 2x=i & y =j}", 1 },
3483 };
3484 
test_bijective(struct isl_ctx * ctx)3485 static int test_bijective(struct isl_ctx *ctx)
3486 {
3487 	isl_map *map;
3488 	int i;
3489 	int bijective;
3490 
3491 	for (i = 0; i < ARRAY_SIZE(bijective_tests); ++i) {
3492 		map = isl_map_read_from_str(ctx, bijective_tests[i].str);
3493 		bijective = isl_map_is_bijective(map);
3494 		isl_map_free(map);
3495 		if (bijective < 0)
3496 			return -1;
3497 		if (bijective_tests[i].bijective && !bijective)
3498 			isl_die(ctx, isl_error_internal,
3499 				"map not detected as bijective", return -1);
3500 		if (!bijective_tests[i].bijective && bijective)
3501 			isl_die(ctx, isl_error_internal,
3502 				"map detected as bijective", return -1);
3503 	}
3504 
3505 	return 0;
3506 }
3507 
3508 /* Inputs for isl_pw_qpolynomial_gist tests.
3509  * "pwqp" is the input, "set" is the context and "gist" is the expected result.
3510  */
3511 struct {
3512 	const char *pwqp;
3513 	const char *set;
3514 	const char *gist;
3515 } pwqp_gist_tests[] = {
3516 	{ "{ [i] -> i }", "{ [k] : exists a : k = 2a }", "{ [i] -> i }" },
3517 	{ "{ [i] -> i + [ (i + [i/3])/2 ] }", "{ [10] }", "{ [i] -> 16 }" },
3518 	{ "{ [i] -> ([(i)/2]) }", "{ [k] : exists a : k = 2a+1 }",
3519 	  "{ [i] -> -1/2 + 1/2 * i }" },
3520 	{ "{ [i] -> i^2 : i != 0 }", "{ [i] : i != 0 }", "{ [i] -> i^2 }" },
3521 };
3522 
3523 /* Perform some basic isl_pw_qpolynomial_gist tests.
3524  */
test_pwqp_gist(isl_ctx * ctx)3525 static isl_stat test_pwqp_gist(isl_ctx *ctx)
3526 {
3527 	int i;
3528 	const char *str;
3529 	isl_set *set;
3530 	isl_pw_qpolynomial *pwqp1, *pwqp2;
3531 	isl_bool equal;
3532 
3533 	for (i = 0; i < ARRAY_SIZE(pwqp_gist_tests); ++i) {
3534 		str = pwqp_gist_tests[i].pwqp;
3535 		pwqp1 = isl_pw_qpolynomial_read_from_str(ctx, str);
3536 		str = pwqp_gist_tests[i].set;
3537 		set = isl_set_read_from_str(ctx, str);
3538 		pwqp1 = isl_pw_qpolynomial_gist(pwqp1, set);
3539 		str = pwqp_gist_tests[i].gist;
3540 		pwqp2 = isl_pw_qpolynomial_read_from_str(ctx, str);
3541 		pwqp1 = isl_pw_qpolynomial_sub(pwqp1, pwqp2);
3542 		equal = isl_pw_qpolynomial_is_zero(pwqp1);
3543 		isl_pw_qpolynomial_free(pwqp1);
3544 
3545 		if (equal < 0)
3546 			return isl_stat_error;
3547 		if (!equal)
3548 			isl_die(ctx, isl_error_unknown,
3549 				"unexpected result", return isl_stat_error);
3550 	}
3551 
3552 	return isl_stat_ok;
3553 }
3554 
3555 /* Perform a basic isl_pw_qpolynomial_max test.
3556  */
test_pwqp_max(isl_ctx * ctx)3557 static isl_stat test_pwqp_max(isl_ctx *ctx)
3558 {
3559 	const char *str;
3560 	isl_pw_qpolynomial *pwqp;
3561 	isl_val *v;
3562 	int ok;
3563 
3564 	str = "{ [x=2:9, y] -> floor((x + 1)/4)^3 - floor((2x)/3)^2 }";
3565 	pwqp = isl_pw_qpolynomial_read_from_str(ctx, str);
3566 	v = isl_pw_qpolynomial_max(pwqp);
3567 	ok = isl_val_cmp_si(v, -1) == 0;
3568 	isl_val_free(v);
3569 
3570 	if (!v)
3571 		return isl_stat_error;
3572 	if (!ok)
3573 		isl_die(ctx, isl_error_unknown, "unexpected maximum",
3574 			return isl_stat_error);
3575 
3576 	return isl_stat_ok;
3577 }
3578 
test_pwqp(struct isl_ctx * ctx)3579 static int test_pwqp(struct isl_ctx *ctx)
3580 {
3581 	const char *str;
3582 	isl_set *set;
3583 	isl_pw_qpolynomial *pwqp1, *pwqp2;
3584 	int equal;
3585 
3586 	str = "{ [i,j,k] -> 1 + 9 * [i/5] + 7 * [j/11] + 4 * [k/13] }";
3587 	pwqp1 = isl_pw_qpolynomial_read_from_str(ctx, str);
3588 
3589 	pwqp1 = isl_pw_qpolynomial_move_dims(pwqp1, isl_dim_param, 0,
3590 						isl_dim_in, 1, 1);
3591 
3592 	str = "[j] -> { [i,k] -> 1 + 9 * [i/5] + 7 * [j/11] + 4 * [k/13] }";
3593 	pwqp2 = isl_pw_qpolynomial_read_from_str(ctx, str);
3594 
3595 	pwqp1 = isl_pw_qpolynomial_sub(pwqp1, pwqp2);
3596 
3597 	assert(isl_pw_qpolynomial_is_zero(pwqp1));
3598 
3599 	isl_pw_qpolynomial_free(pwqp1);
3600 
3601 	if (test_pwqp_gist(ctx) < 0)
3602 		return -1;
3603 
3604 	str = "{ [i] -> ([([i/2] + [i/2])/5]) }";
3605 	pwqp1 = isl_pw_qpolynomial_read_from_str(ctx, str);
3606 	str = "{ [i] -> ([(2 * [i/2])/5]) }";
3607 	pwqp2 = isl_pw_qpolynomial_read_from_str(ctx, str);
3608 
3609 	pwqp1 = isl_pw_qpolynomial_sub(pwqp1, pwqp2);
3610 
3611 	assert(isl_pw_qpolynomial_is_zero(pwqp1));
3612 
3613 	isl_pw_qpolynomial_free(pwqp1);
3614 
3615 	str = "{ [x] -> ([x/2] + [(x+1)/2]) }";
3616 	pwqp1 = isl_pw_qpolynomial_read_from_str(ctx, str);
3617 	str = "{ [x] -> x }";
3618 	pwqp2 = isl_pw_qpolynomial_read_from_str(ctx, str);
3619 
3620 	pwqp1 = isl_pw_qpolynomial_sub(pwqp1, pwqp2);
3621 
3622 	assert(isl_pw_qpolynomial_is_zero(pwqp1));
3623 
3624 	isl_pw_qpolynomial_free(pwqp1);
3625 
3626 	str = "{ [i] -> ([i/2]) : i >= 0; [i] -> ([i/3]) : i < 0 }";
3627 	pwqp1 = isl_pw_qpolynomial_read_from_str(ctx, str);
3628 	pwqp2 = isl_pw_qpolynomial_read_from_str(ctx, str);
3629 	pwqp1 = isl_pw_qpolynomial_coalesce(pwqp1);
3630 	pwqp1 = isl_pw_qpolynomial_sub(pwqp1, pwqp2);
3631 	assert(isl_pw_qpolynomial_is_zero(pwqp1));
3632 	isl_pw_qpolynomial_free(pwqp1);
3633 
3634 	str = "{ [a,b,a] -> (([(2*[a/3]+b)/5]) * ([(2*[a/3]+b)/5])) }";
3635 	pwqp2 = isl_pw_qpolynomial_read_from_str(ctx, str);
3636 	str = "{ [a,b,c] -> (([(2*[a/3]+b)/5]) * ([(2*[c/3]+b)/5])) }";
3637 	pwqp1 = isl_pw_qpolynomial_read_from_str(ctx, str);
3638 	set = isl_set_read_from_str(ctx, "{ [a,b,a] }");
3639 	pwqp1 = isl_pw_qpolynomial_intersect_domain(pwqp1, set);
3640 	equal = isl_pw_qpolynomial_plain_is_equal(pwqp1, pwqp2);
3641 	isl_pw_qpolynomial_free(pwqp1);
3642 	isl_pw_qpolynomial_free(pwqp2);
3643 	if (equal < 0)
3644 		return -1;
3645 	if (!equal)
3646 		isl_die(ctx, isl_error_unknown, "unexpected result", return -1);
3647 
3648 	str = "{ [a,b,c] -> (([(2*[a/3]+1)/5]) * ([(2*[c/3]+1)/5])) : b = 1 }";
3649 	pwqp2 = isl_pw_qpolynomial_read_from_str(ctx, str);
3650 	str = "{ [a,b,c] -> (([(2*[a/3]+b)/5]) * ([(2*[c/3]+b)/5])) }";
3651 	pwqp1 = isl_pw_qpolynomial_read_from_str(ctx, str);
3652 	pwqp1 = isl_pw_qpolynomial_fix_val(pwqp1, isl_dim_set, 1,
3653 						isl_val_one(ctx));
3654 	equal = isl_pw_qpolynomial_plain_is_equal(pwqp1, pwqp2);
3655 	isl_pw_qpolynomial_free(pwqp1);
3656 	isl_pw_qpolynomial_free(pwqp2);
3657 	if (equal < 0)
3658 		return -1;
3659 	if (!equal)
3660 		isl_die(ctx, isl_error_unknown, "unexpected result", return -1);
3661 
3662 	if (test_pwqp_max(ctx) < 0)
3663 		return -1;
3664 
3665 	return 0;
3666 }
3667 
test_split_periods(isl_ctx * ctx)3668 static int test_split_periods(isl_ctx *ctx)
3669 {
3670 	const char *str;
3671 	isl_pw_qpolynomial *pwqp;
3672 
3673 	str = "{ [U,V] -> 1/3 * U + 2/3 * V - [(U + 2V)/3] + [U/2] : "
3674 		"U + 2V + 3 >= 0 and - U -2V  >= 0 and - U + 10 >= 0 and "
3675 		"U  >= 0; [U,V] -> U^2 : U >= 100 }";
3676 	pwqp = isl_pw_qpolynomial_read_from_str(ctx, str);
3677 
3678 	pwqp = isl_pw_qpolynomial_split_periods(pwqp, 2);
3679 
3680 	isl_pw_qpolynomial_free(pwqp);
3681 
3682 	if (!pwqp)
3683 		return -1;
3684 
3685 	return 0;
3686 }
3687 
test_union(isl_ctx * ctx)3688 static int test_union(isl_ctx *ctx)
3689 {
3690 	const char *str;
3691 	isl_union_set *uset1, *uset2;
3692 	isl_union_map *umap1, *umap2;
3693 	int equal;
3694 
3695 	str = "{ [i] : 0 <= i <= 1 }";
3696 	uset1 = isl_union_set_read_from_str(ctx, str);
3697 	str = "{ [1] -> [0] }";
3698 	umap1 = isl_union_map_read_from_str(ctx, str);
3699 
3700 	umap2 = isl_union_set_lex_gt_union_set(isl_union_set_copy(uset1), uset1);
3701 	equal = isl_union_map_is_equal(umap1, umap2);
3702 
3703 	isl_union_map_free(umap1);
3704 	isl_union_map_free(umap2);
3705 
3706 	if (equal < 0)
3707 		return -1;
3708 	if (!equal)
3709 		isl_die(ctx, isl_error_unknown, "union maps not equal",
3710 			return -1);
3711 
3712 	str = "{ A[i] -> B[i]; B[i] -> C[i]; A[0] -> C[1] }";
3713 	umap1 = isl_union_map_read_from_str(ctx, str);
3714 	str = "{ A[i]; B[i] }";
3715 	uset1 = isl_union_set_read_from_str(ctx, str);
3716 
3717 	uset2 = isl_union_map_domain(umap1);
3718 
3719 	equal = isl_union_set_is_equal(uset1, uset2);
3720 
3721 	isl_union_set_free(uset1);
3722 	isl_union_set_free(uset2);
3723 
3724 	if (equal < 0)
3725 		return -1;
3726 	if (!equal)
3727 		isl_die(ctx, isl_error_unknown, "union sets not equal",
3728 			return -1);
3729 
3730 	return 0;
3731 }
3732 
3733 /* Check that computing a bound of a non-zero polynomial over an unbounded
3734  * domain does not produce a rational value.
3735  * In particular, check that the upper bound is infinity.
3736  */
test_bound_unbounded_domain(isl_ctx * ctx)3737 static int test_bound_unbounded_domain(isl_ctx *ctx)
3738 {
3739 	const char *str;
3740 	isl_pw_qpolynomial *pwqp;
3741 	isl_pw_qpolynomial_fold *pwf, *pwf2;
3742 	isl_bool equal;
3743 
3744 	str = "{ [m,n] -> -m * n }";
3745 	pwqp = isl_pw_qpolynomial_read_from_str(ctx, str);
3746 	pwf = isl_pw_qpolynomial_bound(pwqp, isl_fold_max, NULL);
3747 	str = "{ infty }";
3748 	pwqp = isl_pw_qpolynomial_read_from_str(ctx, str);
3749 	pwf2 = isl_pw_qpolynomial_bound(pwqp, isl_fold_max, NULL);
3750 	equal = isl_pw_qpolynomial_fold_plain_is_equal(pwf, pwf2);
3751 	isl_pw_qpolynomial_fold_free(pwf);
3752 	isl_pw_qpolynomial_fold_free(pwf2);
3753 
3754 	if (equal < 0)
3755 		return -1;
3756 	if (!equal)
3757 		isl_die(ctx, isl_error_unknown,
3758 			"expecting infinite polynomial bound", return -1);
3759 
3760 	return 0;
3761 }
3762 
test_bound(isl_ctx * ctx)3763 static int test_bound(isl_ctx *ctx)
3764 {
3765 	const char *str;
3766 	isl_size dim;
3767 	isl_pw_qpolynomial *pwqp;
3768 	isl_pw_qpolynomial_fold *pwf;
3769 
3770 	if (test_bound_unbounded_domain(ctx) < 0)
3771 		return -1;
3772 
3773 	str = "{ [[a, b, c, d] -> [e]] -> 0 }";
3774 	pwqp = isl_pw_qpolynomial_read_from_str(ctx, str);
3775 	pwf = isl_pw_qpolynomial_bound(pwqp, isl_fold_max, NULL);
3776 	dim = isl_pw_qpolynomial_fold_dim(pwf, isl_dim_in);
3777 	isl_pw_qpolynomial_fold_free(pwf);
3778 	if (dim < 0)
3779 		return -1;
3780 	if (dim != 4)
3781 		isl_die(ctx, isl_error_unknown, "unexpected input dimension",
3782 			return -1);
3783 
3784 	str = "{ [[x]->[x]] -> 1 : exists a : x = 2 a }";
3785 	pwqp = isl_pw_qpolynomial_read_from_str(ctx, str);
3786 	pwf = isl_pw_qpolynomial_bound(pwqp, isl_fold_max, NULL);
3787 	dim = isl_pw_qpolynomial_fold_dim(pwf, isl_dim_in);
3788 	isl_pw_qpolynomial_fold_free(pwf);
3789 	if (dim < 0)
3790 		return -1;
3791 	if (dim != 1)
3792 		isl_die(ctx, isl_error_unknown, "unexpected input dimension",
3793 			return -1);
3794 
3795 	return 0;
3796 }
3797 
3798 /* isl_set is defined to isl_map internally, so the corresponding elements
3799  * are isl_basic_map objects.
3800  */
3801 #undef EL_BASE
3802 #undef SET_BASE
3803 #define EL_BASE		basic_map
3804 #define SET_BASE	set
3805 #include "isl_test_list_templ.c"
3806 
3807 #undef EL_BASE
3808 #undef SET_BASE
3809 #define EL_BASE		basic_set
3810 #define SET_BASE	union_set
3811 #include "isl_test_list_templ.c"
3812 
3813 #undef EL_BASE
3814 #undef SET_BASE
3815 #define EL_BASE		set
3816 #define SET_BASE	union_set
3817 #include "isl_test_list_templ.c"
3818 
3819 #undef EL_BASE
3820 #undef SET_BASE
3821 #define EL_BASE		basic_map
3822 #define SET_BASE	map
3823 #include "isl_test_list_templ.c"
3824 
3825 #undef EL_BASE
3826 #undef SET_BASE
3827 #define EL_BASE		map
3828 #define SET_BASE	union_map
3829 #include "isl_test_list_templ.c"
3830 
3831 /* Check that the conversion from isl objects to lists works as expected.
3832  */
test_get_list(isl_ctx * ctx)3833 static int test_get_list(isl_ctx *ctx)
3834 {
3835 	if (test_get_list_basic_map_from_set(ctx, "{ [0]; [2]; [3] }"))
3836 		return -1;
3837 	if (test_get_list_basic_set_from_union_set(ctx, "{ A[0]; B[2]; B[3] }"))
3838 		return -1;
3839 	if (test_get_list_set_from_union_set(ctx, "{ A[0]; A[2]; B[3] }"))
3840 		return -1;
3841 	if (test_get_list_basic_map_from_map(ctx,
3842 				"{ [0] -> [0]; [2] -> [0]; [3] -> [0] }"))
3843 		return -1;
3844 	if (test_get_list_map_from_union_map(ctx,
3845 				"{ A[0] -> [0]; A[2] -> [0]; B[3] -> [0] }"))
3846 		return -1;
3847 
3848 	return 0;
3849 }
3850 
test_lift(isl_ctx * ctx)3851 static int test_lift(isl_ctx *ctx)
3852 {
3853 	const char *str;
3854 	isl_basic_map *bmap;
3855 	isl_basic_set *bset;
3856 
3857 	str = "{ [i0] : exists e0 : i0 = 4e0 }";
3858 	bset = isl_basic_set_read_from_str(ctx, str);
3859 	bset = isl_basic_set_lift(bset);
3860 	bmap = isl_basic_map_from_range(bset);
3861 	bset = isl_basic_map_domain(bmap);
3862 	isl_basic_set_free(bset);
3863 
3864 	return 0;
3865 }
3866 
3867 /* Check that isl_set_is_subset is not confused by identical
3868  * integer divisions.
3869  * The call to isl_set_normalize ensures that the equality constraints
3870  * a = b = 0 are discovered, turning e0 and e1 into identical
3871  * integer divisions.  Any further simplification would remove
3872  * the duplicate integer divisions.
3873  */
test_subset_duplicate_integer_divisions(isl_ctx * ctx)3874 static isl_stat test_subset_duplicate_integer_divisions(isl_ctx *ctx)
3875 {
3876 	const char *str;
3877 	isl_bool is_subset;
3878 	isl_set *set1, *set2;
3879 
3880 	str = "{ [a, b, c, d] : "
3881 	    "exists (e0 = floor((a + d)/4), e1 = floor((d)/4), "
3882 		    "e2 = floor((-a - d + 4 *floor((a + d)/4))/10), "
3883 		    "e3 = floor((-d + 4*floor((d)/4))/10): "
3884 		"10e2 = -a - 2c - d + 4e0 and 10e3 = -2c - d + 4e1 and "
3885 		"b >= 0 and a <= 0 and b <= a) }";
3886 	set1 = isl_set_read_from_str(ctx, str);
3887 	set2 = isl_set_read_from_str(ctx, str);
3888 	set2 = isl_set_normalize(set2);
3889 
3890 	is_subset = isl_set_is_subset(set1, set2);
3891 
3892 	isl_set_free(set1);
3893 	isl_set_free(set2);
3894 
3895 	if (is_subset < 0)
3896 		return isl_stat_error;
3897 	if (!is_subset)
3898 		isl_die(ctx, isl_error_unknown,
3899 			"set is not considered to be a subset of itself",
3900 			return isl_stat_error);
3901 
3902 	return isl_stat_ok;
3903 }
3904 
3905 struct {
3906 	const char *set1;
3907 	const char *set2;
3908 	int subset;
3909 } subset_tests[] = {
3910 	{ "{ [112, 0] }",
3911 	  "{ [i0, i1] : exists (e0 = [(i0 - i1)/16], e1: "
3912 		"16e0 <= i0 - i1 and 16e0 >= -15 + i0 - i1 and "
3913 		"16e1 <= i1 and 16e0 >= -i1 and 16e1 >= -i0 + i1) }", 1 },
3914 	{ "{ [65] }",
3915 	  "{ [i] : exists (e0 = [(255i)/256], e1 = [(127i + 65e0)/191], "
3916 		"e2 = [(3i + 61e1)/65], e3 = [(52i + 12e2)/61], "
3917 		"e4 = [(2i + e3)/3], e5 = [(4i + e3)/4], e6 = [(8i + e3)/12]: "
3918 		    "3e4 = 2i + e3 and 4e5 = 4i + e3 and 12e6 = 8i + e3 and "
3919 		    "i <= 255 and 64e3 >= -45 + 67i and i >= 0 and "
3920 		    "256e0 <= 255i and 256e0 >= -255 + 255i and "
3921 		    "191e1 <= 127i + 65e0 and 191e1 >= -190 + 127i + 65e0 and "
3922 		    "65e2 <= 3i + 61e1 and 65e2 >= -64 + 3i + 61e1 and "
3923 		    "61e3 <= 52i + 12e2 and 61e3 >= -60 + 52i + 12e2) }", 1 },
3924 	{ "{ [i] : 0 <= i <= 10 }", "{ rat: [i] : 0 <= i <= 10 }", 1 },
3925 	{ "{ rat: [i] : 0 <= i <= 10 }", "{ [i] : 0 <= i <= 10 }", 0 },
3926 	{ "{ rat: [0] }", "{ [i] : 0 <= i <= 10 }", 1 },
3927 	{ "{ rat: [(1)/2] }", "{ [i] : 0 <= i <= 10 }", 0 },
3928 	{ "{ [t, i] : (exists (e0 = [(2 + t)/4]: 4e0 <= 2 + t and "
3929 			"4e0 >= -1 + t and i >= 57 and i <= 62 and "
3930 			"4e0 <= 62 + t - i and 4e0 >= -61 + t + i and "
3931 			"t >= 0 and t <= 511 and 4e0 <= -57 + t + i and "
3932 			"4e0 >= 58 + t - i and i >= 58 + t and i >= 62 - t)) }",
3933 	  "{ [i0, i1] : (exists (e0 = [(4 + i0)/4]: 4e0 <= 62 + i0 - i1 and "
3934 			"4e0 >= 1 + i0 and i0 >= 0 and i0 <= 511 and "
3935 			"4e0 <= -57 + i0 + i1)) or "
3936 		"(exists (e0 = [(2 + i0)/4]: 4e0 <= i0 and "
3937 			"4e0 >= 58 + i0 - i1 and i0 >= 2 and i0 <= 511 and "
3938 			"4e0 >= -61 + i0 + i1)) or "
3939 		"(i1 <= 66 - i0 and i0 >= 2 and i1 >= 59 + i0) }", 1 },
3940 	{ "[a, b] -> { : a = 0 and b = -1 }", "[b, a] -> { : b >= -10 }", 1 },
3941 };
3942 
test_subset(isl_ctx * ctx)3943 static int test_subset(isl_ctx *ctx)
3944 {
3945 	int i;
3946 	isl_set *set1, *set2;
3947 	int subset;
3948 
3949 	if (test_subset_duplicate_integer_divisions(ctx) < 0)
3950 		return -1;
3951 
3952 	for (i = 0; i < ARRAY_SIZE(subset_tests); ++i) {
3953 		set1 = isl_set_read_from_str(ctx, subset_tests[i].set1);
3954 		set2 = isl_set_read_from_str(ctx, subset_tests[i].set2);
3955 		subset = isl_set_is_subset(set1, set2);
3956 		isl_set_free(set1);
3957 		isl_set_free(set2);
3958 		if (subset < 0)
3959 			return -1;
3960 		if (subset != subset_tests[i].subset)
3961 			isl_die(ctx, isl_error_unknown,
3962 				"incorrect subset result", return -1);
3963 	}
3964 
3965 	return 0;
3966 }
3967 
3968 struct {
3969 	const char *minuend;
3970 	const char *subtrahend;
3971 	const char *difference;
3972 } subtract_domain_tests[] = {
3973 	{ "{ A[i] -> B[i] }", "{ A[i] }", "{ }" },
3974 	{ "{ A[i] -> B[i] }", "{ B[i] }", "{ A[i] -> B[i] }" },
3975 	{ "{ A[i] -> B[i] }", "{ A[i] : i > 0 }", "{ A[i] -> B[i] : i <= 0 }" },
3976 };
3977 
test_subtract(isl_ctx * ctx)3978 static int test_subtract(isl_ctx *ctx)
3979 {
3980 	int i;
3981 	isl_union_map *umap1, *umap2;
3982 	isl_union_pw_multi_aff *upma1, *upma2;
3983 	isl_union_set *uset;
3984 	int equal;
3985 
3986 	for (i = 0; i < ARRAY_SIZE(subtract_domain_tests); ++i) {
3987 		umap1 = isl_union_map_read_from_str(ctx,
3988 				subtract_domain_tests[i].minuend);
3989 		uset = isl_union_set_read_from_str(ctx,
3990 				subtract_domain_tests[i].subtrahend);
3991 		umap2 = isl_union_map_read_from_str(ctx,
3992 				subtract_domain_tests[i].difference);
3993 		umap1 = isl_union_map_subtract_domain(umap1, uset);
3994 		equal = isl_union_map_is_equal(umap1, umap2);
3995 		isl_union_map_free(umap1);
3996 		isl_union_map_free(umap2);
3997 		if (equal < 0)
3998 			return -1;
3999 		if (!equal)
4000 			isl_die(ctx, isl_error_unknown,
4001 				"incorrect subtract domain result", return -1);
4002 	}
4003 
4004 	for (i = 0; i < ARRAY_SIZE(subtract_domain_tests); ++i) {
4005 		upma1 = isl_union_pw_multi_aff_read_from_str(ctx,
4006 				subtract_domain_tests[i].minuend);
4007 		uset = isl_union_set_read_from_str(ctx,
4008 				subtract_domain_tests[i].subtrahend);
4009 		upma2 = isl_union_pw_multi_aff_read_from_str(ctx,
4010 				subtract_domain_tests[i].difference);
4011 		upma1 = isl_union_pw_multi_aff_subtract_domain(upma1, uset);
4012 		equal = isl_union_pw_multi_aff_plain_is_equal(upma1, upma2);
4013 		isl_union_pw_multi_aff_free(upma1);
4014 		isl_union_pw_multi_aff_free(upma2);
4015 		if (equal < 0)
4016 			return -1;
4017 		if (!equal)
4018 			isl_die(ctx, isl_error_unknown,
4019 				"incorrect subtract domain result", return -1);
4020 	}
4021 
4022 	return 0;
4023 }
4024 
4025 /* Check that intersecting the empty basic set with another basic set
4026  * does not increase the number of constraints.  In particular,
4027  * the empty basic set should maintain its canonical representation.
4028  */
test_intersect_1(isl_ctx * ctx)4029 static int test_intersect_1(isl_ctx *ctx)
4030 {
4031 	isl_size n1, n2;
4032 	isl_basic_set *bset1, *bset2;
4033 
4034 	bset1 = isl_basic_set_read_from_str(ctx, "{ [a,b,c] : 1 = 0 }");
4035 	bset2 = isl_basic_set_read_from_str(ctx, "{ [1,2,3] }");
4036 	n1 = isl_basic_set_n_constraint(bset1);
4037 	bset1 = isl_basic_set_intersect(bset1, bset2);
4038 	n2 = isl_basic_set_n_constraint(bset1);
4039 	isl_basic_set_free(bset1);
4040 	if (n1 < 0 || n2 < 0)
4041 		return -1;
4042 	if (n1 != n2)
4043 		isl_die(ctx, isl_error_unknown,
4044 			"number of constraints of empty set changed",
4045 			return -1);
4046 
4047 	return 0;
4048 }
4049 
4050 /* Check that intersecting a set with itself does not cause
4051  * an explosion in the number of disjuncts.
4052  */
test_intersect_2(isl_ctx * ctx)4053 static isl_stat test_intersect_2(isl_ctx *ctx)
4054 {
4055 	int i;
4056 	isl_set *set;
4057 
4058 	set = isl_set_read_from_str(ctx, "{ [x,y] : x >= 0 or y >= 0 }");
4059 	for (i = 0; i < 100; ++i)
4060 		set = isl_set_intersect(set, isl_set_copy(set));
4061 	isl_set_free(set);
4062 	if (!set)
4063 		return isl_stat_error;
4064 	return isl_stat_ok;
4065 }
4066 
4067 /* Perform some intersection tests.
4068  */
test_intersect(isl_ctx * ctx)4069 static int test_intersect(isl_ctx *ctx)
4070 {
4071 	if (test_intersect_1(ctx) < 0)
4072 		return -1;
4073 	if (test_intersect_2(ctx) < 0)
4074 		return -1;
4075 
4076 	return 0;
4077 }
4078 
test_factorize(isl_ctx * ctx)4079 int test_factorize(isl_ctx *ctx)
4080 {
4081 	const char *str;
4082 	isl_basic_set *bset;
4083 	isl_factorizer *f;
4084 
4085 	str = "{ [i0, i1, i2, i3, i4, i5, i6, i7] : 3i5 <= 2 - 2i0 and "
4086 	    "i0 >= -2 and i6 >= 1 + i3 and i7 >= 0 and 3i5 >= -2i0 and "
4087 	    "2i4 <= i2 and i6 >= 1 + 2i0 + 3i1 and i4 <= -1 and "
4088 	    "i6 >= 1 + 2i0 + 3i5 and i6 <= 2 + 2i0 + 3i5 and "
4089 	    "3i5 <= 2 - 2i0 - i2 + 3i4 and i6 <= 2 + 2i0 + 3i1 and "
4090 	    "i0 <= -1 and i7 <= i2 + i3 - 3i4 - i6 and "
4091 	    "3i5 >= -2i0 - i2 + 3i4 }";
4092 	bset = isl_basic_set_read_from_str(ctx, str);
4093 	f = isl_basic_set_factorizer(bset);
4094 	isl_basic_set_free(bset);
4095 	isl_factorizer_free(f);
4096 	if (!f)
4097 		isl_die(ctx, isl_error_unknown,
4098 			"failed to construct factorizer", return -1);
4099 
4100 	str = "{ [i0, i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11, i12] : "
4101 	    "i12 <= 2 + i0 - i11 and 2i8 >= -i4 and i11 >= i1 and "
4102 	    "3i5 <= -i2 and 2i11 >= -i4 - 2i7 and i11 <= 3 + i0 + 3i9 and "
4103 	    "i11 <= -i4 - 2i7 and i12 >= -i10 and i2 >= -2 and "
4104 	    "i11 >= i1 + 3i10 and i11 >= 1 + i0 + 3i9 and "
4105 	    "i11 <= 1 - i4 - 2i8 and 6i6 <= 6 - i2 and 3i6 >= 1 - i2 and "
4106 	    "i11 <= 2 + i1 and i12 <= i4 + i11 and i12 >= i0 - i11 and "
4107 	    "3i5 >= -2 - i2 and i12 >= -1 + i4 + i11 and 3i3 <= 3 - i2 and "
4108 	    "9i6 <= 11 - i2 + 6i5 and 3i3 >= 1 - i2 and "
4109 	    "9i6 <= 5 - i2 + 6i3 and i12 <= -1 and i2 <= 0 }";
4110 	bset = isl_basic_set_read_from_str(ctx, str);
4111 	f = isl_basic_set_factorizer(bset);
4112 	isl_basic_set_free(bset);
4113 	isl_factorizer_free(f);
4114 	if (!f)
4115 		isl_die(ctx, isl_error_unknown,
4116 			"failed to construct factorizer", return -1);
4117 
4118 	return 0;
4119 }
4120 
check_injective(__isl_take isl_map * map,void * user)4121 static isl_stat check_injective(__isl_take isl_map *map, void *user)
4122 {
4123 	int *injective = user;
4124 
4125 	*injective = isl_map_is_injective(map);
4126 	isl_map_free(map);
4127 
4128 	if (*injective < 0 || !*injective)
4129 		return isl_stat_error;
4130 
4131 	return isl_stat_ok;
4132 }
4133 
test_one_schedule(isl_ctx * ctx,const char * d,const char * w,const char * r,const char * s,int tilable,int parallel)4134 int test_one_schedule(isl_ctx *ctx, const char *d, const char *w,
4135 	const char *r, const char *s, int tilable, int parallel)
4136 {
4137 	int i;
4138 	isl_union_set *D;
4139 	isl_union_map *W, *R, *S;
4140 	isl_union_map *empty;
4141 	isl_union_map *dep_raw, *dep_war, *dep_waw, *dep;
4142 	isl_union_map *validity, *proximity, *coincidence;
4143 	isl_union_map *schedule;
4144 	isl_union_map *test;
4145 	isl_union_set *delta;
4146 	isl_union_set *domain;
4147 	isl_set *delta_set;
4148 	isl_set *slice;
4149 	isl_set *origin;
4150 	isl_schedule_constraints *sc;
4151 	isl_schedule *sched;
4152 	int is_nonneg, is_parallel, is_tilable, is_injection, is_complete;
4153 	isl_size n;
4154 
4155 	D = isl_union_set_read_from_str(ctx, d);
4156 	W = isl_union_map_read_from_str(ctx, w);
4157 	R = isl_union_map_read_from_str(ctx, r);
4158 	S = isl_union_map_read_from_str(ctx, s);
4159 
4160 	W = isl_union_map_intersect_domain(W, isl_union_set_copy(D));
4161 	R = isl_union_map_intersect_domain(R, isl_union_set_copy(D));
4162 
4163 	empty = isl_union_map_empty(isl_union_map_get_space(S));
4164         isl_union_map_compute_flow(isl_union_map_copy(R),
4165 				   isl_union_map_copy(W), empty,
4166 				   isl_union_map_copy(S),
4167 				   &dep_raw, NULL, NULL, NULL);
4168         isl_union_map_compute_flow(isl_union_map_copy(W),
4169 				   isl_union_map_copy(W),
4170 				   isl_union_map_copy(R),
4171 				   isl_union_map_copy(S),
4172 				   &dep_waw, &dep_war, NULL, NULL);
4173 
4174 	dep = isl_union_map_union(dep_waw, dep_war);
4175 	dep = isl_union_map_union(dep, dep_raw);
4176 	validity = isl_union_map_copy(dep);
4177 	coincidence = isl_union_map_copy(dep);
4178 	proximity = isl_union_map_copy(dep);
4179 
4180 	sc = isl_schedule_constraints_on_domain(isl_union_set_copy(D));
4181 	sc = isl_schedule_constraints_set_validity(sc, validity);
4182 	sc = isl_schedule_constraints_set_coincidence(sc, coincidence);
4183 	sc = isl_schedule_constraints_set_proximity(sc, proximity);
4184 	sched = isl_schedule_constraints_compute_schedule(sc);
4185 	schedule = isl_schedule_get_map(sched);
4186 	isl_schedule_free(sched);
4187 	isl_union_map_free(W);
4188 	isl_union_map_free(R);
4189 	isl_union_map_free(S);
4190 
4191 	is_injection = 1;
4192 	isl_union_map_foreach_map(schedule, &check_injective, &is_injection);
4193 
4194 	domain = isl_union_map_domain(isl_union_map_copy(schedule));
4195 	is_complete = isl_union_set_is_subset(D, domain);
4196 	isl_union_set_free(D);
4197 	isl_union_set_free(domain);
4198 
4199 	test = isl_union_map_reverse(isl_union_map_copy(schedule));
4200 	test = isl_union_map_apply_range(test, dep);
4201 	test = isl_union_map_apply_range(test, schedule);
4202 
4203 	delta = isl_union_map_deltas(test);
4204 	n = isl_union_set_n_set(delta);
4205 	if (n < 0) {
4206 		isl_union_set_free(delta);
4207 		return -1;
4208 	}
4209 	if (n == 0) {
4210 		is_tilable = 1;
4211 		is_parallel = 1;
4212 		is_nonneg = 1;
4213 		isl_union_set_free(delta);
4214 	} else {
4215 		isl_size dim;
4216 
4217 		delta_set = isl_set_from_union_set(delta);
4218 
4219 		slice = isl_set_universe(isl_set_get_space(delta_set));
4220 		for (i = 0; i < tilable; ++i)
4221 			slice = isl_set_lower_bound_si(slice, isl_dim_set, i, 0);
4222 		is_tilable = isl_set_is_subset(delta_set, slice);
4223 		isl_set_free(slice);
4224 
4225 		slice = isl_set_universe(isl_set_get_space(delta_set));
4226 		for (i = 0; i < parallel; ++i)
4227 			slice = isl_set_fix_si(slice, isl_dim_set, i, 0);
4228 		is_parallel = isl_set_is_subset(delta_set, slice);
4229 		isl_set_free(slice);
4230 
4231 		origin = isl_set_universe(isl_set_get_space(delta_set));
4232 		dim = isl_set_dim(origin, isl_dim_set);
4233 		if (dim < 0)
4234 			origin = isl_set_free(origin);
4235 		for (i = 0; i < dim; ++i)
4236 			origin = isl_set_fix_si(origin, isl_dim_set, i, 0);
4237 
4238 		delta_set = isl_set_union(delta_set, isl_set_copy(origin));
4239 		delta_set = isl_set_lexmin(delta_set);
4240 
4241 		is_nonneg = isl_set_is_equal(delta_set, origin);
4242 
4243 		isl_set_free(origin);
4244 		isl_set_free(delta_set);
4245 	}
4246 
4247 	if (is_nonneg < 0 || is_parallel < 0 || is_tilable < 0 ||
4248 	    is_injection < 0 || is_complete < 0)
4249 		return -1;
4250 	if (!is_complete)
4251 		isl_die(ctx, isl_error_unknown,
4252 			"generated schedule incomplete", return -1);
4253 	if (!is_injection)
4254 		isl_die(ctx, isl_error_unknown,
4255 			"generated schedule not injective on each statement",
4256 			return -1);
4257 	if (!is_nonneg)
4258 		isl_die(ctx, isl_error_unknown,
4259 			"negative dependences in generated schedule",
4260 			return -1);
4261 	if (!is_tilable)
4262 		isl_die(ctx, isl_error_unknown,
4263 			"generated schedule not as tilable as expected",
4264 			return -1);
4265 	if (!is_parallel)
4266 		isl_die(ctx, isl_error_unknown,
4267 			"generated schedule not as parallel as expected",
4268 			return -1);
4269 
4270 	return 0;
4271 }
4272 
4273 /* Compute a schedule for the given instance set, validity constraints,
4274  * proximity constraints and context and return a corresponding union map
4275  * representation.
4276  */
compute_schedule_with_context(isl_ctx * ctx,const char * domain,const char * validity,const char * proximity,const char * context)4277 static __isl_give isl_union_map *compute_schedule_with_context(isl_ctx *ctx,
4278 	const char *domain, const char *validity, const char *proximity,
4279 	const char *context)
4280 {
4281 	isl_set *con;
4282 	isl_union_set *dom;
4283 	isl_union_map *dep;
4284 	isl_union_map *prox;
4285 	isl_schedule_constraints *sc;
4286 	isl_schedule *schedule;
4287 	isl_union_map *sched;
4288 
4289 	con = isl_set_read_from_str(ctx, context);
4290 	dom = isl_union_set_read_from_str(ctx, domain);
4291 	dep = isl_union_map_read_from_str(ctx, validity);
4292 	prox = isl_union_map_read_from_str(ctx, proximity);
4293 	sc = isl_schedule_constraints_on_domain(dom);
4294 	sc = isl_schedule_constraints_set_context(sc, con);
4295 	sc = isl_schedule_constraints_set_validity(sc, dep);
4296 	sc = isl_schedule_constraints_set_proximity(sc, prox);
4297 	schedule = isl_schedule_constraints_compute_schedule(sc);
4298 	sched = isl_schedule_get_map(schedule);
4299 	isl_schedule_free(schedule);
4300 
4301 	return sched;
4302 }
4303 
4304 /* Compute a schedule for the given instance set, validity constraints and
4305  * proximity constraints and return a corresponding union map representation.
4306  */
compute_schedule(isl_ctx * ctx,const char * domain,const char * validity,const char * proximity)4307 static __isl_give isl_union_map *compute_schedule(isl_ctx *ctx,
4308 	const char *domain, const char *validity, const char *proximity)
4309 {
4310 	return compute_schedule_with_context(ctx, domain, validity, proximity,
4311 						"{ : }");
4312 }
4313 
4314 /* Check that a schedule can be constructed on the given domain
4315  * with the given validity and proximity constraints.
4316  */
test_has_schedule(isl_ctx * ctx,const char * domain,const char * validity,const char * proximity)4317 static int test_has_schedule(isl_ctx *ctx, const char *domain,
4318 	const char *validity, const char *proximity)
4319 {
4320 	isl_union_map *sched;
4321 
4322 	sched = compute_schedule(ctx, domain, validity, proximity);
4323 	if (!sched)
4324 		return -1;
4325 
4326 	isl_union_map_free(sched);
4327 	return 0;
4328 }
4329 
test_special_schedule(isl_ctx * ctx,const char * domain,const char * validity,const char * proximity,const char * expected_sched)4330 int test_special_schedule(isl_ctx *ctx, const char *domain,
4331 	const char *validity, const char *proximity, const char *expected_sched)
4332 {
4333 	isl_union_map *sched1, *sched2;
4334 	int equal;
4335 
4336 	sched1 = compute_schedule(ctx, domain, validity, proximity);
4337 	sched2 = isl_union_map_read_from_str(ctx, expected_sched);
4338 
4339 	equal = isl_union_map_is_equal(sched1, sched2);
4340 	isl_union_map_free(sched1);
4341 	isl_union_map_free(sched2);
4342 
4343 	if (equal < 0)
4344 		return -1;
4345 	if (!equal)
4346 		isl_die(ctx, isl_error_unknown, "unexpected schedule",
4347 			return -1);
4348 
4349 	return 0;
4350 }
4351 
4352 /* Check that the schedule map is properly padded, i.e., that the range
4353  * lives in a single space.
4354  */
test_padded_schedule(isl_ctx * ctx)4355 static int test_padded_schedule(isl_ctx *ctx)
4356 {
4357 	const char *str;
4358 	isl_union_set *D;
4359 	isl_union_map *validity, *proximity;
4360 	isl_schedule_constraints *sc;
4361 	isl_schedule *sched;
4362 	isl_union_map *umap;
4363 	isl_union_set *range;
4364 	isl_set *set;
4365 
4366 	str = "[N] -> { S0[i] : 0 <= i <= N; S1[i, j] : 0 <= i, j <= N }";
4367 	D = isl_union_set_read_from_str(ctx, str);
4368 	validity = isl_union_map_empty(isl_union_set_get_space(D));
4369 	proximity = isl_union_map_copy(validity);
4370 	sc = isl_schedule_constraints_on_domain(D);
4371 	sc = isl_schedule_constraints_set_validity(sc, validity);
4372 	sc = isl_schedule_constraints_set_proximity(sc, proximity);
4373 	sched = isl_schedule_constraints_compute_schedule(sc);
4374 	umap = isl_schedule_get_map(sched);
4375 	isl_schedule_free(sched);
4376 	range = isl_union_map_range(umap);
4377 	set = isl_set_from_union_set(range);
4378 	isl_set_free(set);
4379 
4380 	if (!set)
4381 		return -1;
4382 
4383 	return 0;
4384 }
4385 
4386 /* Check that conditional validity constraints are also taken into
4387  * account across bands.
4388  * In particular, try to make sure that live ranges D[1,0]->C[2,1] and
4389  * D[2,0]->C[3,0] are not local in the outer band of the generated schedule
4390  * and then check that the adjacent order constraint C[2,1]->D[2,0]
4391  * is enforced by the rest of the schedule.
4392  */
test_special_conditional_schedule_constraints(isl_ctx * ctx)4393 static int test_special_conditional_schedule_constraints(isl_ctx *ctx)
4394 {
4395 	const char *str;
4396 	isl_union_set *domain;
4397 	isl_union_map *validity, *proximity, *condition;
4398 	isl_union_map *sink, *source, *dep;
4399 	isl_schedule_constraints *sc;
4400 	isl_schedule *schedule;
4401 	isl_union_access_info *access;
4402 	isl_union_flow *flow;
4403 	int empty;
4404 
4405 	str = "[n] -> { C[k, i] : k <= -1 + n and i >= 0 and i <= -1 + k; "
4406 	    "A[k] : k >= 1 and k <= -1 + n; "
4407 	    "B[k, i] : k <= -1 + n and i >= 0 and i <= -1 + k; "
4408 	    "D[k, i] : k <= -1 + n and i >= 0 and i <= -1 + k }";
4409 	domain = isl_union_set_read_from_str(ctx, str);
4410 	sc = isl_schedule_constraints_on_domain(domain);
4411 	str = "[n] -> { D[k, i] -> C[1 + k, k - i] : "
4412 		"k <= -2 + n and i >= 1 and i <= -1 + k; "
4413 		"D[k, i] -> C[1 + k, i] : "
4414 		"k <= -2 + n and i >= 1 and i <= -1 + k; "
4415 		"D[k, 0] -> C[1 + k, k] : k >= 1 and k <= -2 + n; "
4416 		"D[k, 0] -> C[1 + k, 0] : k >= 1 and k <= -2 + n }";
4417 	validity = isl_union_map_read_from_str(ctx, str);
4418 	sc = isl_schedule_constraints_set_validity(sc, validity);
4419 	str = "[n] -> { C[k, i] -> D[k, i] : "
4420 		"0 <= i <= -1 + k and k <= -1 + n }";
4421 	proximity = isl_union_map_read_from_str(ctx, str);
4422 	sc = isl_schedule_constraints_set_proximity(sc, proximity);
4423 	str = "[n] -> { [D[k, i] -> a[]] -> [C[1 + k, k - i] -> b[]] : "
4424 		"i <= -1 + k and i >= 1 and k <= -2 + n; "
4425 		"[B[k, i] -> c[]] -> [B[k, 1 + i] -> c[]] : "
4426 		"k <= -1 + n and i >= 0 and i <= -2 + k }";
4427 	condition = isl_union_map_read_from_str(ctx, str);
4428 	str = "[n] -> { [B[k, i] -> e[]] -> [D[k, i] -> a[]] : "
4429 		"i >= 0 and i <= -1 + k and k <= -1 + n; "
4430 		"[C[k, i] -> b[]] -> [D[k', -1 + k - i] -> a[]] : "
4431 		"i >= 0 and i <= -1 + k and k <= -1 + n and "
4432 		"k' <= -1 + n and k' >= k - i and k' >= 1 + k; "
4433 		"[C[k, i] -> b[]] -> [D[k, -1 + k - i] -> a[]] : "
4434 		"i >= 0 and i <= -1 + k and k <= -1 + n; "
4435 		"[B[k, i] -> c[]] -> [A[k'] -> d[]] : "
4436 		"k <= -1 + n and i >= 0 and i <= -1 + k and "
4437 		"k' >= 1 and k' <= -1 + n and k' >= 1 + k }";
4438 	validity = isl_union_map_read_from_str(ctx, str);
4439 	sc = isl_schedule_constraints_set_conditional_validity(sc, condition,
4440 								validity);
4441 	schedule = isl_schedule_constraints_compute_schedule(sc);
4442 	str = "{ D[2,0] -> [] }";
4443 	sink = isl_union_map_read_from_str(ctx, str);
4444 	access = isl_union_access_info_from_sink(sink);
4445 	str = "{ C[2,1] -> [] }";
4446 	source = isl_union_map_read_from_str(ctx, str);
4447 	access = isl_union_access_info_set_must_source(access, source);
4448 	access = isl_union_access_info_set_schedule(access, schedule);
4449 	flow = isl_union_access_info_compute_flow(access);
4450 	dep = isl_union_flow_get_must_dependence(flow);
4451 	isl_union_flow_free(flow);
4452 	empty = isl_union_map_is_empty(dep);
4453 	isl_union_map_free(dep);
4454 
4455 	if (empty < 0)
4456 		return -1;
4457 	if (empty)
4458 		isl_die(ctx, isl_error_unknown,
4459 			"conditional validity not respected", return -1);
4460 
4461 	return 0;
4462 }
4463 
4464 /* Check that the test for violated conditional validity constraints
4465  * is not confused by domain compression.
4466  * In particular, earlier versions of isl would apply
4467  * a schedule on the compressed domains to the original domains,
4468  * resulting in a failure to detect that the default schedule
4469  * violates the conditional validity constraints.
4470  */
test_special_conditional_schedule_constraints_2(isl_ctx * ctx)4471 static int test_special_conditional_schedule_constraints_2(isl_ctx *ctx)
4472 {
4473 	const char *str;
4474 	isl_bool empty;
4475 	isl_union_set *domain;
4476 	isl_union_map *validity, *condition;
4477 	isl_schedule_constraints *sc;
4478 	isl_schedule *schedule;
4479 	isl_union_map *umap;
4480 	isl_map *map, *ge;
4481 
4482 	str = "{ A[0, i] : 0 <= i <= 10; B[1, i] : 0 <= i <= 10 }";
4483 	domain = isl_union_set_read_from_str(ctx, str);
4484 	sc = isl_schedule_constraints_on_domain(domain);
4485 	str = "{ B[1, i] -> A[0, i + 1] }";
4486 	condition = isl_union_map_read_from_str(ctx, str);
4487 	str = "{ A[0, i] -> B[1, i - 1] }";
4488 	validity = isl_union_map_read_from_str(ctx, str);
4489 	sc = isl_schedule_constraints_set_conditional_validity(sc, condition,
4490 						isl_union_map_copy(validity));
4491 	schedule = isl_schedule_constraints_compute_schedule(sc);
4492 	umap = isl_schedule_get_map(schedule);
4493 	isl_schedule_free(schedule);
4494 	validity = isl_union_map_apply_domain(validity,
4495 						isl_union_map_copy(umap));
4496 	validity = isl_union_map_apply_range(validity, umap);
4497 	map = isl_map_from_union_map(validity);
4498 	ge = isl_map_lex_ge(isl_space_domain(isl_map_get_space(map)));
4499 	map = isl_map_intersect(map, ge);
4500 	empty = isl_map_is_empty(map);
4501 	isl_map_free(map);
4502 
4503 	if (empty < 0)
4504 		return -1;
4505 	if (!empty)
4506 		isl_die(ctx, isl_error_unknown,
4507 			"conditional validity constraints not satisfied",
4508 			return -1);
4509 
4510 	return 0;
4511 }
4512 
4513 /* Input for testing of schedule construction based on
4514  * conditional constraints.
4515  *
4516  * domain is the iteration domain
4517  * flow are the flow dependences, which determine the validity and
4518  * 	proximity constraints
4519  * condition are the conditions on the conditional validity constraints
4520  * conditional_validity are the conditional validity constraints
4521  * outer_band_n is the expected number of members in the outer band
4522  */
4523 struct {
4524 	const char *domain;
4525 	const char *flow;
4526 	const char *condition;
4527 	const char *conditional_validity;
4528 	int outer_band_n;
4529 } live_range_tests[] = {
4530 	/* Contrived example that illustrates that we need to keep
4531 	 * track of tagged condition dependences and
4532 	 * tagged conditional validity dependences
4533 	 * in isl_sched_edge separately.
4534 	 * In particular, the conditional validity constraints on A
4535 	 * cannot be satisfied,
4536 	 * but they can be ignored because there are no corresponding
4537 	 * condition constraints.  However, we do have an additional
4538 	 * conditional validity constraint that maps to the same
4539 	 * dependence relation
4540 	 * as the condition constraint on B.  If we did not make a distinction
4541 	 * between tagged condition and tagged conditional validity
4542 	 * dependences, then we
4543 	 * could end up treating this shared dependence as an condition
4544 	 * constraint on A, forcing a localization of the conditions,
4545 	 * which is impossible.
4546 	 */
4547 	{ "{ S[i] : 0 <= 1 < 100; T[i] : 0 <= 1 < 100 }",
4548 	  "{ S[i] -> S[i+1] : 0 <= i < 99 }",
4549 	  "{ [S[i] -> B[]] -> [S[i+1] -> B[]] : 0 <= i < 99 }",
4550 	  "{ [S[i] -> A[]] -> [T[i'] -> A[]] : 0 <= i', i < 100 and i != i';"
4551 	    "[T[i] -> A[]] -> [S[i'] -> A[]] : 0 <= i', i < 100 and i != i';"
4552 	    "[S[i] -> A[]] -> [S[i+1] -> A[]] : 0 <= i < 99 }",
4553 	  1
4554 	},
4555 	/* TACO 2013 Fig. 7 */
4556 	{ "[n] -> { S1[i,j] : 0 <= i,j < n; S2[i,j] : 0 <= i,j < n }",
4557 	  "[n] -> { S1[i,j] -> S2[i,j] : 0 <= i,j < n;"
4558 		   "S2[i,j] -> S2[i,j+1] : 0 <= i < n and 0 <= j < n - 1 }",
4559 	  "[n] -> { [S1[i,j] -> t[]] -> [S2[i,j] -> t[]] : 0 <= i,j < n;"
4560 		   "[S2[i,j] -> x1[]] -> [S2[i,j+1] -> x1[]] : "
4561 				"0 <= i < n and 0 <= j < n - 1 }",
4562 	  "[n] -> { [S2[i,j] -> t[]] -> [S1[i,j'] -> t[]] : "
4563 				"0 <= i < n and 0 <= j < j' < n;"
4564 		   "[S2[i,j] -> t[]] -> [S1[i',j'] -> t[]] : "
4565 				"0 <= i < i' < n and 0 <= j,j' < n;"
4566 		   "[S2[i,j] -> x1[]] -> [S2[i,j'] -> x1[]] : "
4567 				"0 <= i,j,j' < n and j < j' }",
4568 	    2
4569 	},
4570 	/* TACO 2013 Fig. 7, without tags */
4571 	{ "[n] -> { S1[i,j] : 0 <= i,j < n; S2[i,j] : 0 <= i,j < n }",
4572 	  "[n] -> { S1[i,j] -> S2[i,j] : 0 <= i,j < n;"
4573 		   "S2[i,j] -> S2[i,j+1] : 0 <= i < n and 0 <= j < n - 1 }",
4574 	  "[n] -> { S1[i,j] -> S2[i,j] : 0 <= i,j < n;"
4575 		   "S2[i,j] -> S2[i,j+1] : 0 <= i < n and 0 <= j < n - 1 }",
4576 	  "[n] -> { S2[i,j] -> S1[i,j'] : 0 <= i < n and 0 <= j < j' < n;"
4577 		   "S2[i,j] -> S1[i',j'] : 0 <= i < i' < n and 0 <= j,j' < n;"
4578 		   "S2[i,j] -> S2[i,j'] : 0 <= i,j,j' < n and j < j' }",
4579 	   1
4580 	},
4581 	/* TACO 2013 Fig. 12 */
4582 	{ "{ S1[i,0] : 0 <= i <= 1; S2[i,j] : 0 <= i <= 1 and 1 <= j <= 2;"
4583 	    "S3[i,3] : 0 <= i <= 1 }",
4584 	  "{ S1[i,0] -> S2[i,1] : 0 <= i <= 1;"
4585 	    "S2[i,1] -> S2[i,2] : 0 <= i <= 1;"
4586 	    "S2[i,2] -> S3[i,3] : 0 <= i <= 1 }",
4587 	  "{ [S1[i,0]->t[]] -> [S2[i,1]->t[]] : 0 <= i <= 1;"
4588 	    "[S2[i,1]->t[]] -> [S2[i,2]->t[]] : 0 <= i <= 1;"
4589 	    "[S2[i,2]->t[]] -> [S3[i,3]->t[]] : 0 <= i <= 1 }",
4590 	  "{ [S2[i,1]->t[]] -> [S2[i,2]->t[]] : 0 <= i <= 1;"
4591 	    "[S2[0,j]->t[]] -> [S2[1,j']->t[]] : 1 <= j,j' <= 2;"
4592 	    "[S2[0,j]->t[]] -> [S1[1,0]->t[]] : 1 <= j <= 2;"
4593 	    "[S3[0,3]->t[]] -> [S2[1,j]->t[]] : 1 <= j <= 2;"
4594 	    "[S3[0,3]->t[]] -> [S1[1,0]->t[]] }",
4595 	   1
4596 	}
4597 };
4598 
4599 /* Test schedule construction based on conditional constraints.
4600  * In particular, check the number of members in the outer band node
4601  * as an indication of whether tiling is possible or not.
4602  */
test_conditional_schedule_constraints(isl_ctx * ctx)4603 static int test_conditional_schedule_constraints(isl_ctx *ctx)
4604 {
4605 	int i;
4606 	isl_union_set *domain;
4607 	isl_union_map *condition;
4608 	isl_union_map *flow;
4609 	isl_union_map *validity;
4610 	isl_schedule_constraints *sc;
4611 	isl_schedule *schedule;
4612 	isl_schedule_node *node;
4613 	isl_size n_member;
4614 
4615 	if (test_special_conditional_schedule_constraints(ctx) < 0)
4616 		return -1;
4617 	if (test_special_conditional_schedule_constraints_2(ctx) < 0)
4618 		return -1;
4619 
4620 	for (i = 0; i < ARRAY_SIZE(live_range_tests); ++i) {
4621 		domain = isl_union_set_read_from_str(ctx,
4622 				live_range_tests[i].domain);
4623 		flow = isl_union_map_read_from_str(ctx,
4624 				live_range_tests[i].flow);
4625 		condition = isl_union_map_read_from_str(ctx,
4626 				live_range_tests[i].condition);
4627 		validity = isl_union_map_read_from_str(ctx,
4628 				live_range_tests[i].conditional_validity);
4629 		sc = isl_schedule_constraints_on_domain(domain);
4630 		sc = isl_schedule_constraints_set_validity(sc,
4631 				isl_union_map_copy(flow));
4632 		sc = isl_schedule_constraints_set_proximity(sc, flow);
4633 		sc = isl_schedule_constraints_set_conditional_validity(sc,
4634 				condition, validity);
4635 		schedule = isl_schedule_constraints_compute_schedule(sc);
4636 		node = isl_schedule_get_root(schedule);
4637 		while (node &&
4638 		    isl_schedule_node_get_type(node) != isl_schedule_node_band)
4639 			node = isl_schedule_node_first_child(node);
4640 		n_member = isl_schedule_node_band_n_member(node);
4641 		isl_schedule_node_free(node);
4642 		isl_schedule_free(schedule);
4643 
4644 		if (!schedule || n_member < 0)
4645 			return -1;
4646 		if (n_member != live_range_tests[i].outer_band_n)
4647 			isl_die(ctx, isl_error_unknown,
4648 				"unexpected number of members in outer band",
4649 				return -1);
4650 	}
4651 	return 0;
4652 }
4653 
4654 /* Check that the schedule computed for the given instance set and
4655  * dependence relation strongly satisfies the dependences.
4656  * In particular, check that no instance is scheduled before
4657  * or together with an instance on which it depends.
4658  * Earlier versions of isl would produce a schedule that
4659  * only weakly satisfies the dependences.
4660  */
test_strongly_satisfying_schedule(isl_ctx * ctx)4661 static int test_strongly_satisfying_schedule(isl_ctx *ctx)
4662 {
4663 	const char *domain, *dep;
4664 	isl_union_map *D, *schedule;
4665 	isl_map *map, *ge;
4666 	int empty;
4667 
4668 	domain = "{ B[i0, i1] : 0 <= i0 <= 1 and 0 <= i1 <= 11; "
4669 		    "A[i0] : 0 <= i0 <= 1 }";
4670 	dep = "{ B[i0, i1] -> B[i0, 1 + i1] : 0 <= i0 <= 1 and 0 <= i1 <= 10; "
4671 		"B[0, 11] -> A[1]; A[i0] -> B[i0, 0] : 0 <= i0 <= 1 }";
4672 	schedule = compute_schedule(ctx, domain, dep, dep);
4673 	D = isl_union_map_read_from_str(ctx, dep);
4674 	D = isl_union_map_apply_domain(D, isl_union_map_copy(schedule));
4675 	D = isl_union_map_apply_range(D, schedule);
4676 	map = isl_map_from_union_map(D);
4677 	ge = isl_map_lex_ge(isl_space_domain(isl_map_get_space(map)));
4678 	map = isl_map_intersect(map, ge);
4679 	empty = isl_map_is_empty(map);
4680 	isl_map_free(map);
4681 
4682 	if (empty < 0)
4683 		return -1;
4684 	if (!empty)
4685 		isl_die(ctx, isl_error_unknown,
4686 			"dependences not strongly satisfied", return -1);
4687 
4688 	return 0;
4689 }
4690 
4691 /* Compute a schedule for input where the instance set constraints
4692  * conflict with the context constraints.
4693  * Earlier versions of isl did not properly handle this situation.
4694  */
test_conflicting_context_schedule(isl_ctx * ctx)4695 static int test_conflicting_context_schedule(isl_ctx *ctx)
4696 {
4697 	isl_union_map *schedule;
4698 	const char *domain, *context;
4699 
4700 	domain = "[n] -> { A[] : n >= 0 }";
4701 	context = "[n] -> { : n < 0 }";
4702 	schedule = compute_schedule_with_context(ctx,
4703 						domain, "{}", "{}", context);
4704 	isl_union_map_free(schedule);
4705 
4706 	if (!schedule)
4707 		return -1;
4708 
4709 	return 0;
4710 }
4711 
4712 /* Check that a set of schedule constraints that only allow for
4713  * a coalescing schedule still produces a schedule even if the user
4714  * request a non-coalescing schedule.  Earlier versions of isl
4715  * would not handle this case correctly.
4716  */
test_coalescing_schedule(isl_ctx * ctx)4717 static int test_coalescing_schedule(isl_ctx *ctx)
4718 {
4719 	const char *domain, *dep;
4720 	isl_union_set *I;
4721 	isl_union_map *D;
4722 	isl_schedule_constraints *sc;
4723 	isl_schedule *schedule;
4724 	int treat_coalescing;
4725 
4726 	domain = "{ S[a, b] : 0 <= a <= 1 and 0 <= b <= 1 }";
4727 	dep = "{ S[a, b] -> S[a + b, 1 - b] }";
4728 	I = isl_union_set_read_from_str(ctx, domain);
4729 	D = isl_union_map_read_from_str(ctx, dep);
4730 	sc = isl_schedule_constraints_on_domain(I);
4731 	sc = isl_schedule_constraints_set_validity(sc, D);
4732 	treat_coalescing = isl_options_get_schedule_treat_coalescing(ctx);
4733 	isl_options_set_schedule_treat_coalescing(ctx, 1);
4734 	schedule = isl_schedule_constraints_compute_schedule(sc);
4735 	isl_options_set_schedule_treat_coalescing(ctx, treat_coalescing);
4736 	isl_schedule_free(schedule);
4737 	if (!schedule)
4738 		return -1;
4739 	return 0;
4740 }
4741 
4742 /* Check that the scheduler does not perform any needless
4743  * compound skewing.  Earlier versions of isl would compute
4744  * schedules in terms of transformed schedule coefficients and
4745  * would not accurately keep track of the sum of the original
4746  * schedule coefficients.  It could then produce the schedule
4747  * S[t,i,j,k] -> [t, 2t + i, 2t + i + j, 2t + i + j + k]
4748  * for the input below instead of the schedule below.
4749  */
test_skewing_schedule(isl_ctx * ctx)4750 static int test_skewing_schedule(isl_ctx *ctx)
4751 {
4752 	const char *D, *V, *P, *S;
4753 
4754 	D = "[n] -> { S[t,i,j,k] : 0 <= t,i,j,k < n }";
4755 	V = "[n] -> { S[t,i,j,k] -> S[t+1,a,b,c] : 0 <= t,i,j,k,a,b,c < n and "
4756 		"-2 <= a-i <= 2 and -1 <= a-i + b-j <= 1 and "
4757 		"-1 <= a-i + b-j + c-k <= 1 }";
4758 	P = "{ }";
4759 	S = "{ S[t,i,j,k] -> [t, 2t + i, t + i + j, 2t + k] }";
4760 
4761 	return test_special_schedule(ctx, D, V, P, S);
4762 }
4763 
test_schedule(isl_ctx * ctx)4764 int test_schedule(isl_ctx *ctx)
4765 {
4766 	const char *D, *W, *R, *V, *P, *S;
4767 	int max_coincidence;
4768 	int treat_coalescing;
4769 
4770 	/* Handle resulting schedule with zero bands. */
4771 	if (test_one_schedule(ctx, "{[]}", "{}", "{}", "{[] -> []}", 0, 0) < 0)
4772 		return -1;
4773 
4774 	/* Jacobi */
4775 	D = "[T,N] -> { S1[t,i] : 1 <= t <= T and 2 <= i <= N - 1 }";
4776 	W = "{ S1[t,i] -> a[t,i] }";
4777 	R = "{ S1[t,i] -> a[t-1,i]; S1[t,i] -> a[t-1,i-1]; "
4778 	    	"S1[t,i] -> a[t-1,i+1] }";
4779 	S = "{ S1[t,i] -> [t,i] }";
4780 	if (test_one_schedule(ctx, D, W, R, S, 2, 0) < 0)
4781 		return -1;
4782 
4783 	/* Fig. 5 of CC2008 */
4784 	D = "[N] -> { S_0[i, j] : i >= 0 and i <= -1 + N and j >= 2 and "
4785 				"j <= -1 + N }";
4786 	W = "[N] -> { S_0[i, j] -> a[i, j] : i >= 0 and i <= -1 + N and "
4787 				"j >= 2 and j <= -1 + N }";
4788 	R = "[N] -> { S_0[i, j] -> a[j, i] : i >= 0 and i <= -1 + N and "
4789 				"j >= 2 and j <= -1 + N; "
4790 		    "S_0[i, j] -> a[i, -1 + j] : i >= 0 and i <= -1 + N and "
4791 				"j >= 2 and j <= -1 + N }";
4792 	S = "[N] -> { S_0[i, j] -> [0, i, 0, j, 0] }";
4793 	if (test_one_schedule(ctx, D, W, R, S, 2, 0) < 0)
4794 		return -1;
4795 
4796 	D = "{ S1[i] : 0 <= i <= 10; S2[i] : 0 <= i <= 9 }";
4797 	W = "{ S1[i] -> a[i] }";
4798 	R = "{ S2[i] -> a[i+1] }";
4799 	S = "{ S1[i] -> [0,i]; S2[i] -> [1,i] }";
4800 	if (test_one_schedule(ctx, D, W, R, S, 1, 1) < 0)
4801 		return -1;
4802 
4803 	D = "{ S1[i] : 0 <= i < 10; S2[i] : 0 <= i < 10 }";
4804 	W = "{ S1[i] -> a[i] }";
4805 	R = "{ S2[i] -> a[9-i] }";
4806 	S = "{ S1[i] -> [0,i]; S2[i] -> [1,i] }";
4807 	if (test_one_schedule(ctx, D, W, R, S, 1, 1) < 0)
4808 		return -1;
4809 
4810 	D = "[N] -> { S1[i] : 0 <= i < N; S2[i] : 0 <= i < N }";
4811 	W = "{ S1[i] -> a[i] }";
4812 	R = "[N] -> { S2[i] -> a[N-1-i] }";
4813 	S = "{ S1[i] -> [0,i]; S2[i] -> [1,i] }";
4814 	if (test_one_schedule(ctx, D, W, R, S, 1, 1) < 0)
4815 		return -1;
4816 
4817 	D = "{ S1[i] : 0 < i < 10; S2[i] : 0 <= i < 10 }";
4818 	W = "{ S1[i] -> a[i]; S2[i] -> b[i] }";
4819 	R = "{ S2[i] -> a[i]; S1[i] -> b[i-1] }";
4820 	S = "{ S1[i] -> [i,0]; S2[i] -> [i,1] }";
4821 	if (test_one_schedule(ctx, D, W, R, S, 0, 0) < 0)
4822 		return -1;
4823 
4824 	D = "[N] -> { S1[i] : 1 <= i <= N; S2[i,j] : 1 <= i,j <= N }";
4825 	W = "{ S1[i] -> a[0,i]; S2[i,j] -> a[i,j] }";
4826 	R = "{ S2[i,j] -> a[i-1,j] }";
4827 	S = "{ S1[i] -> [0,i,0]; S2[i,j] -> [1,i,j] }";
4828 	if (test_one_schedule(ctx, D, W, R, S, 2, 1) < 0)
4829 		return -1;
4830 
4831 	D = "[N] -> { S1[i] : 1 <= i <= N; S2[i,j] : 1 <= i,j <= N }";
4832 	W = "{ S1[i] -> a[i,0]; S2[i,j] -> a[i,j] }";
4833 	R = "{ S2[i,j] -> a[i,j-1] }";
4834 	S = "{ S1[i] -> [0,i,0]; S2[i,j] -> [1,i,j] }";
4835 	if (test_one_schedule(ctx, D, W, R, S, 2, 1) < 0)
4836 		return -1;
4837 
4838 	D = "[N] -> { S_0[]; S_1[i] : i >= 0 and i <= -1 + N; S_2[] }";
4839 	W = "[N] -> { S_0[] -> a[0]; S_2[] -> b[0]; "
4840 		    "S_1[i] -> a[1 + i] : i >= 0 and i <= -1 + N }";
4841 	R = "[N] -> { S_2[] -> a[N]; S_1[i] -> a[i] : i >= 0 and i <= -1 + N }";
4842 	S = "[N] -> { S_1[i] -> [1, i, 0]; S_2[] -> [2, 0, 1]; "
4843 		    "S_0[] -> [0, 0, 0] }";
4844 	if (test_one_schedule(ctx, D, W, R, S, 1, 0) < 0)
4845 		return -1;
4846 	ctx->opt->schedule_parametric = 0;
4847 	if (test_one_schedule(ctx, D, W, R, S, 0, 0) < 0)
4848 		return -1;
4849 	ctx->opt->schedule_parametric = 1;
4850 
4851 	D = "[N] -> { S1[i] : 1 <= i <= N; S2[i] : 1 <= i <= N; "
4852 		    "S3[i,j] : 1 <= i,j <= N; S4[i] : 1 <= i <= N }";
4853 	W = "{ S1[i] -> a[i,0]; S2[i] -> a[0,i]; S3[i,j] -> a[i,j] }";
4854 	R = "[N] -> { S3[i,j] -> a[i-1,j]; S3[i,j] -> a[i,j-1]; "
4855 		    "S4[i] -> a[i,N] }";
4856 	S = "{ S1[i] -> [0,i,0]; S2[i] -> [1,i,0]; S3[i,j] -> [2,i,j]; "
4857 		"S4[i] -> [4,i,0] }";
4858 	max_coincidence = isl_options_get_schedule_maximize_coincidence(ctx);
4859 	isl_options_set_schedule_maximize_coincidence(ctx, 0);
4860 	if (test_one_schedule(ctx, D, W, R, S, 2, 0) < 0)
4861 		return -1;
4862 	isl_options_set_schedule_maximize_coincidence(ctx, max_coincidence);
4863 
4864 	D = "[N] -> { S_0[i, j] : i >= 1 and i <= N and j >= 1 and j <= N }";
4865 	W = "[N] -> { S_0[i, j] -> s[0] : i >= 1 and i <= N and j >= 1 and "
4866 					"j <= N }";
4867 	R = "[N] -> { S_0[i, j] -> s[0] : i >= 1 and i <= N and j >= 1 and "
4868 					"j <= N; "
4869 		    "S_0[i, j] -> a[i, j] : i >= 1 and i <= N and j >= 1 and "
4870 					"j <= N }";
4871 	S = "[N] -> { S_0[i, j] -> [0, i, 0, j, 0] }";
4872 	if (test_one_schedule(ctx, D, W, R, S, 0, 0) < 0)
4873 		return -1;
4874 
4875 	D = "[N] -> { S_0[t] : t >= 0 and t <= -1 + N; "
4876 		    " S_2[t] : t >= 0 and t <= -1 + N; "
4877 		    " S_1[t, i] : t >= 0 and t <= -1 + N and i >= 0 and "
4878 				"i <= -1 + N }";
4879 	W = "[N] -> { S_0[t] -> a[t, 0] : t >= 0 and t <= -1 + N; "
4880 		    " S_2[t] -> b[t] : t >= 0 and t <= -1 + N; "
4881 		    " S_1[t, i] -> a[t, 1 + i] : t >= 0 and t <= -1 + N and "
4882 						"i >= 0 and i <= -1 + N }";
4883 	R = "[N] -> { S_1[t, i] -> a[t, i] : t >= 0 and t <= -1 + N and "
4884 					    "i >= 0 and i <= -1 + N; "
4885 		    " S_2[t] -> a[t, N] : t >= 0 and t <= -1 + N }";
4886 	S = "[N] -> { S_2[t] -> [0, t, 2]; S_1[t, i] -> [0, t, 1, i, 0]; "
4887 		    " S_0[t] -> [0, t, 0] }";
4888 
4889 	if (test_one_schedule(ctx, D, W, R, S, 2, 1) < 0)
4890 		return -1;
4891 	ctx->opt->schedule_parametric = 0;
4892 	if (test_one_schedule(ctx, D, W, R, S, 0, 0) < 0)
4893 		return -1;
4894 	ctx->opt->schedule_parametric = 1;
4895 
4896 	D = "[N] -> { S1[i,j] : 0 <= i,j < N; S2[i,j] : 0 <= i,j < N }";
4897 	S = "{ S1[i,j] -> [0,i,j]; S2[i,j] -> [1,i,j] }";
4898 	if (test_one_schedule(ctx, D, "{}", "{}", S, 2, 2) < 0)
4899 		return -1;
4900 
4901 	D = "[M, N] -> { S_1[i] : i >= 0 and i <= -1 + M; "
4902 	    "S_0[i, j] : i >= 0 and i <= -1 + M and j >= 0 and j <= -1 + N }";
4903 	W = "[M, N] -> { S_0[i, j] -> a[j] : i >= 0 and i <= -1 + M and "
4904 					    "j >= 0 and j <= -1 + N; "
4905 			"S_1[i] -> b[0] : i >= 0 and i <= -1 + M }";
4906 	R = "[M, N] -> { S_0[i, j] -> a[0] : i >= 0 and i <= -1 + M and "
4907 					    "j >= 0 and j <= -1 + N; "
4908 			"S_1[i] -> b[0] : i >= 0 and i <= -1 + M }";
4909 	S = "[M, N] -> { S_1[i] -> [1, i, 0]; S_0[i, j] -> [0, i, 0, j, 0] }";
4910 	if (test_one_schedule(ctx, D, W, R, S, 0, 0) < 0)
4911 		return -1;
4912 
4913 	D = "{ S_0[i] : i >= 0 }";
4914 	W = "{ S_0[i] -> a[i] : i >= 0 }";
4915 	R = "{ S_0[i] -> a[0] : i >= 0 }";
4916 	S = "{ S_0[i] -> [0, i, 0] }";
4917 	if (test_one_schedule(ctx, D, W, R, S, 0, 0) < 0)
4918 		return -1;
4919 
4920 	D = "{ S_0[i] : i >= 0; S_1[i] : i >= 0 }";
4921 	W = "{ S_0[i] -> a[i] : i >= 0; S_1[i] -> b[i] : i >= 0 }";
4922 	R = "{ S_0[i] -> b[0] : i >= 0; S_1[i] -> a[i] : i >= 0 }";
4923 	S = "{ S_1[i] -> [0, i, 1]; S_0[i] -> [0, i, 0] }";
4924 	if (test_one_schedule(ctx, D, W, R, S, 0, 0) < 0)
4925 		return -1;
4926 
4927 	D = "[n] -> { S_0[j, k] : j <= -1 + n and j >= 0 and "
4928 				"k <= -1 + n and k >= 0 }";
4929 	W = "[n] -> { S_0[j, k] -> B[j] : j <= -1 + n and j >= 0 and "							"k <= -1 + n and k >= 0 }";
4930 	R = "[n] -> { S_0[j, k] -> B[j] : j <= -1 + n and j >= 0 and "
4931 					"k <= -1 + n and k >= 0; "
4932 		    "S_0[j, k] -> B[k] : j <= -1 + n and j >= 0 and "
4933 					"k <= -1 + n and k >= 0; "
4934 		    "S_0[j, k] -> A[k] : j <= -1 + n and j >= 0 and "
4935 					"k <= -1 + n and k >= 0 }";
4936 	S = "[n] -> { S_0[j, k] -> [2, j, k] }";
4937 	ctx->opt->schedule_outer_coincidence = 1;
4938 	if (test_one_schedule(ctx, D, W, R, S, 0, 0) < 0)
4939 		return -1;
4940 	ctx->opt->schedule_outer_coincidence = 0;
4941 
4942 	D = "{Stmt_for_body24[i0, i1, i2, i3]:"
4943 		"i0 >= 0 and i0 <= 1 and i1 >= 0 and i1 <= 6 and i2 >= 2 and "
4944 		"i2 <= 6 - i1 and i3 >= 0 and i3 <= -1 + i2;"
4945 	     "Stmt_for_body24[i0, i1, 1, 0]:"
4946 		"i0 >= 0 and i0 <= 1 and i1 >= 0 and i1 <= 5;"
4947 	     "Stmt_for_body7[i0, i1, i2]:"
4948 		"i0 >= 0 and i0 <= 1 and i1 >= 0 and i1 <= 7 and i2 >= 0 and "
4949 		"i2 <= 7 }";
4950 
4951 	V = "{Stmt_for_body24[0, i1, i2, i3] -> "
4952 		"Stmt_for_body24[1, i1, i2, i3]:"
4953 		"i3 >= 0 and i3 <= -1 + i2 and i1 >= 0 and i2 <= 6 - i1 and "
4954 		"i2 >= 1;"
4955 	     "Stmt_for_body24[0, i1, i2, i3] -> "
4956 		"Stmt_for_body7[1, 1 + i1 + i3, 1 + i1 + i2]:"
4957 		"i3 <= -1 + i2 and i2 <= 6 - i1 and i2 >= 1 and i1 >= 0 and "
4958 		"i3 >= 0;"
4959 	      "Stmt_for_body24[0, i1, i2, i3] ->"
4960 		"Stmt_for_body7[1, i1, 1 + i1 + i3]:"
4961 		"i3 >= 0 and i2 <= 6 - i1 and i1 >= 0 and i3 <= -1 + i2;"
4962 	      "Stmt_for_body7[0, i1, i2] -> Stmt_for_body7[1, i1, i2]:"
4963 		"(i2 >= 1 + i1 and i2 <= 6 and i1 >= 0 and i1 <= 4) or "
4964 		"(i2 >= 3 and i2 <= 7 and i1 >= 1 and i2 >= 1 + i1) or "
4965 		"(i2 >= 0 and i2 <= i1 and i2 >= -7 + i1 and i1 <= 7);"
4966 	      "Stmt_for_body7[0, i1, 1 + i1] -> Stmt_for_body7[1, i1, 1 + i1]:"
4967 		"i1 <= 6 and i1 >= 0;"
4968 	      "Stmt_for_body7[0, 0, 7] -> Stmt_for_body7[1, 0, 7];"
4969 	      "Stmt_for_body7[i0, i1, i2] -> "
4970 		"Stmt_for_body24[i0, o1, -1 + i2 - o1, -1 + i1 - o1]:"
4971 		"i0 >= 0 and i0 <= 1 and o1 >= 0 and i2 >= 1 + i1 and "
4972 		"o1 <= -2 + i2 and i2 <= 7 and o1 <= -1 + i1;"
4973 	      "Stmt_for_body7[i0, i1, i2] -> "
4974 		"Stmt_for_body24[i0, i1, o2, -1 - i1 + i2]:"
4975 		"i0 >= 0 and i0 <= 1 and i1 >= 0 and o2 >= -i1 + i2 and "
4976 		"o2 >= 1 and o2 <= 6 - i1 and i2 >= 1 + i1 }";
4977 	P = V;
4978 
4979 	treat_coalescing = isl_options_get_schedule_treat_coalescing(ctx);
4980 	isl_options_set_schedule_treat_coalescing(ctx, 0);
4981 	if (test_has_schedule(ctx, D, V, P) < 0)
4982 		return -1;
4983 	isl_options_set_schedule_treat_coalescing(ctx, treat_coalescing);
4984 
4985 	D = "{ S_0[i, j] : i >= 1 and i <= 10 and j >= 1 and j <= 8 }";
4986 	V = "{ S_0[i, j] -> S_0[i, 1 + j] : i >= 1 and i <= 10 and "
4987 					   "j >= 1 and j <= 7;"
4988 		"S_0[i, j] -> S_0[1 + i, j] : i >= 1 and i <= 9 and "
4989 					     "j >= 1 and j <= 8 }";
4990 	P = "{ }";
4991 	S = "{ S_0[i, j] -> [i + j, i] }";
4992 	ctx->opt->schedule_algorithm = ISL_SCHEDULE_ALGORITHM_FEAUTRIER;
4993 	if (test_special_schedule(ctx, D, V, P, S) < 0)
4994 		return -1;
4995 	ctx->opt->schedule_algorithm = ISL_SCHEDULE_ALGORITHM_ISL;
4996 
4997 	/* Fig. 1 from Feautrier's "Some Efficient Solutions..." pt. 2, 1992 */
4998 	D = "[N] -> { S_0[i, j] : i >= 0 and i <= -1 + N and "
4999 				 "j >= 0 and j <= -1 + i }";
5000 	V = "[N] -> { S_0[i, j] -> S_0[i, 1 + j] : j <= -2 + i and "
5001 					"i <= -1 + N and j >= 0;"
5002 		     "S_0[i, -1 + i] -> S_0[1 + i, 0] : i >= 1 and "
5003 					"i <= -2 + N }";
5004 	P = "{ }";
5005 	S = "{ S_0[i, j] -> [i, j] }";
5006 	ctx->opt->schedule_algorithm = ISL_SCHEDULE_ALGORITHM_FEAUTRIER;
5007 	if (test_special_schedule(ctx, D, V, P, S) < 0)
5008 		return -1;
5009 	ctx->opt->schedule_algorithm = ISL_SCHEDULE_ALGORITHM_ISL;
5010 
5011 	/* Test both algorithms on a case with only proximity dependences. */
5012 	D = "{ S[i,j] : 0 <= i <= 10 }";
5013 	V = "{ }";
5014 	P = "{ S[i,j] -> S[i+1,j] : 0 <= i,j <= 10 }";
5015 	S = "{ S[i, j] -> [j, i] }";
5016 	ctx->opt->schedule_algorithm = ISL_SCHEDULE_ALGORITHM_FEAUTRIER;
5017 	if (test_special_schedule(ctx, D, V, P, S) < 0)
5018 		return -1;
5019 	ctx->opt->schedule_algorithm = ISL_SCHEDULE_ALGORITHM_ISL;
5020 	if (test_special_schedule(ctx, D, V, P, S) < 0)
5021 		return -1;
5022 
5023 	D = "{ A[a]; B[] }";
5024 	V = "{}";
5025 	P = "{ A[a] -> B[] }";
5026 	if (test_has_schedule(ctx, D, V, P) < 0)
5027 		return -1;
5028 
5029 	if (test_padded_schedule(ctx) < 0)
5030 		return -1;
5031 
5032 	/* Check that check for progress is not confused by rational
5033 	 * solution.
5034 	 */
5035 	D = "[N] -> { S0[i, j] : i >= 0 and i <= N and j >= 0 and j <= N }";
5036 	V = "[N] -> { S0[i0, -1 + N] -> S0[2 + i0, 0] : i0 >= 0 and "
5037 							"i0 <= -2 + N; "
5038 			"S0[i0, i1] -> S0[i0, 1 + i1] : i0 >= 0 and "
5039 				"i0 <= N and i1 >= 0 and i1 <= -1 + N }";
5040 	P = "{}";
5041 	ctx->opt->schedule_algorithm = ISL_SCHEDULE_ALGORITHM_FEAUTRIER;
5042 	if (test_has_schedule(ctx, D, V, P) < 0)
5043 		return -1;
5044 	ctx->opt->schedule_algorithm = ISL_SCHEDULE_ALGORITHM_ISL;
5045 
5046 	/* Check that we allow schedule rows that are only non-trivial
5047 	 * on some full-dimensional domains.
5048 	 */
5049 	D = "{ S1[j] : 0 <= j <= 1; S0[]; S2[k] : 0 <= k <= 1 }";
5050 	V = "{ S0[] -> S1[j] : 0 <= j <= 1; S2[0] -> S0[];"
5051 		"S1[j] -> S2[1] : 0 <= j <= 1 }";
5052 	P = "{}";
5053 	ctx->opt->schedule_algorithm = ISL_SCHEDULE_ALGORITHM_FEAUTRIER;
5054 	if (test_has_schedule(ctx, D, V, P) < 0)
5055 		return -1;
5056 	ctx->opt->schedule_algorithm = ISL_SCHEDULE_ALGORITHM_ISL;
5057 
5058 	if (test_conditional_schedule_constraints(ctx) < 0)
5059 		return -1;
5060 
5061 	if (test_strongly_satisfying_schedule(ctx) < 0)
5062 		return -1;
5063 
5064 	if (test_conflicting_context_schedule(ctx) < 0)
5065 		return -1;
5066 
5067 	if (test_coalescing_schedule(ctx) < 0)
5068 		return -1;
5069 	if (test_skewing_schedule(ctx) < 0)
5070 		return -1;
5071 
5072 	return 0;
5073 }
5074 
5075 /* Perform scheduling tests using the whole component scheduler.
5076  */
test_schedule_whole(isl_ctx * ctx)5077 static int test_schedule_whole(isl_ctx *ctx)
5078 {
5079 	int whole;
5080 	int r;
5081 
5082 	whole = isl_options_get_schedule_whole_component(ctx);
5083 	isl_options_set_schedule_whole_component(ctx, 1);
5084 	r = test_schedule(ctx);
5085 	isl_options_set_schedule_whole_component(ctx, whole);
5086 
5087 	return r;
5088 }
5089 
5090 /* Perform scheduling tests using the incremental scheduler.
5091  */
test_schedule_incremental(isl_ctx * ctx)5092 static int test_schedule_incremental(isl_ctx *ctx)
5093 {
5094 	int whole;
5095 	int r;
5096 
5097 	whole = isl_options_get_schedule_whole_component(ctx);
5098 	isl_options_set_schedule_whole_component(ctx, 0);
5099 	r = test_schedule(ctx);
5100 	isl_options_set_schedule_whole_component(ctx, whole);
5101 
5102 	return r;
5103 }
5104 
test_plain_injective(isl_ctx * ctx,const char * str,int injective)5105 int test_plain_injective(isl_ctx *ctx, const char *str, int injective)
5106 {
5107 	isl_union_map *umap;
5108 	int test;
5109 
5110 	umap = isl_union_map_read_from_str(ctx, str);
5111 	test = isl_union_map_plain_is_injective(umap);
5112 	isl_union_map_free(umap);
5113 	if (test < 0)
5114 		return -1;
5115 	if (test == injective)
5116 		return 0;
5117 	if (injective)
5118 		isl_die(ctx, isl_error_unknown,
5119 			"map not detected as injective", return -1);
5120 	else
5121 		isl_die(ctx, isl_error_unknown,
5122 			"map detected as injective", return -1);
5123 }
5124 
test_injective(isl_ctx * ctx)5125 int test_injective(isl_ctx *ctx)
5126 {
5127 	const char *str;
5128 
5129 	if (test_plain_injective(ctx, "{S[i,j] -> A[0]; T[i,j] -> B[1]}", 0))
5130 		return -1;
5131 	if (test_plain_injective(ctx, "{S[] -> A[0]; T[] -> B[0]}", 1))
5132 		return -1;
5133 	if (test_plain_injective(ctx, "{S[] -> A[0]; T[] -> A[1]}", 1))
5134 		return -1;
5135 	if (test_plain_injective(ctx, "{S[] -> A[0]; T[] -> A[0]}", 0))
5136 		return -1;
5137 	if (test_plain_injective(ctx, "{S[i] -> A[i,0]; T[i] -> A[i,1]}", 1))
5138 		return -1;
5139 	if (test_plain_injective(ctx, "{S[i] -> A[i]; T[i] -> A[i]}", 0))
5140 		return -1;
5141 	if (test_plain_injective(ctx, "{S[] -> A[0,0]; T[] -> A[0,1]}", 1))
5142 		return -1;
5143 	if (test_plain_injective(ctx, "{S[] -> A[0,0]; T[] -> A[1,0]}", 1))
5144 		return -1;
5145 
5146 	str = "{S[] -> A[0,0]; T[] -> A[0,1]; U[] -> A[1,0]}";
5147 	if (test_plain_injective(ctx, str, 1))
5148 		return -1;
5149 	str = "{S[] -> A[0,0]; T[] -> A[0,1]; U[] -> A[0,0]}";
5150 	if (test_plain_injective(ctx, str, 0))
5151 		return -1;
5152 
5153 	return 0;
5154 }
5155 
5156 #undef BASE
5157 #define BASE	aff
5158 #include "isl_test_plain_equal_templ.c"
5159 
5160 #undef BASE
5161 #define BASE	pw_multi_aff
5162 #include "isl_test_plain_equal_templ.c"
5163 
5164 #undef BASE
5165 #define BASE	union_pw_aff
5166 #include "isl_test_plain_equal_templ.c"
5167 
5168 /* Basic tests on isl_union_pw_aff.
5169  *
5170  * In particular, check that isl_union_pw_aff_aff_on_domain
5171  * aligns the parameters of the input objects and
5172  * that isl_union_pw_aff_param_on_domain_id properly
5173  * introduces the parameter.
5174  */
test_upa(isl_ctx * ctx)5175 static int test_upa(isl_ctx *ctx)
5176 {
5177 	const char *str;
5178 	isl_id *id;
5179 	isl_aff *aff;
5180 	isl_union_set *domain;
5181 	isl_union_pw_aff *upa;
5182 	isl_stat ok;
5183 
5184 	aff = isl_aff_read_from_str(ctx, "[N] -> { [N] }");
5185 	str = "[M] -> { A[i] : 0 <= i < M; B[] }";
5186 	domain = isl_union_set_read_from_str(ctx, str);
5187 	upa = isl_union_pw_aff_aff_on_domain(domain, aff);
5188 	str = "[N, M] -> { A[i] -> [N] : 0 <= i < M; B[] -> [N] }";
5189 	ok = union_pw_aff_check_plain_equal(upa, str);
5190 	isl_union_pw_aff_free(upa);
5191 	if (ok < 0)
5192 		return -1;
5193 
5194 	id = isl_id_alloc(ctx, "N", NULL);
5195 	str = "[M] -> { A[i] : 0 <= i < M; B[] }";
5196 	domain = isl_union_set_read_from_str(ctx, str);
5197 	upa = isl_union_pw_aff_param_on_domain_id(domain, id);
5198 	str = "[N, M] -> { A[i] -> [N] : 0 <= i < M; B[] -> [N] }";
5199 	ok = union_pw_aff_check_plain_equal(upa, str);
5200 	isl_union_pw_aff_free(upa);
5201 	if (ok < 0)
5202 		return -1;
5203 
5204 	return 0;
5205 }
5206 
5207 struct {
5208 	__isl_give isl_aff *(*fn)(__isl_take isl_aff *aff1,
5209 				__isl_take isl_aff *aff2);
5210 } aff_bin_op[] = {
5211 	['+'] = { &isl_aff_add },
5212 	['-'] = { &isl_aff_sub },
5213 	['*'] = { &isl_aff_mul },
5214 	['/'] = { &isl_aff_div },
5215 };
5216 
5217 struct {
5218 	const char *arg1;
5219 	unsigned char op;
5220 	const char *arg2;
5221 	const char *res;
5222 } aff_bin_tests[] = {
5223 	{ "{ [i] -> [i] }", '+', "{ [i] -> [i] }",
5224 	  "{ [i] -> [2i] }" },
5225 	{ "{ [i] -> [i] }", '-', "{ [i] -> [i] }",
5226 	  "{ [i] -> [0] }" },
5227 	{ "{ [i] -> [i] }", '*', "{ [i] -> [2] }",
5228 	  "{ [i] -> [2i] }" },
5229 	{ "{ [i] -> [2] }", '*', "{ [i] -> [i] }",
5230 	  "{ [i] -> [2i] }" },
5231 	{ "{ [i] -> [i] }", '/', "{ [i] -> [2] }",
5232 	  "{ [i] -> [i/2] }" },
5233 	{ "{ [i] -> [2i] }", '/', "{ [i] -> [2] }",
5234 	  "{ [i] -> [i] }" },
5235 	{ "{ [i] -> [i] }", '+', "{ [i] -> [NaN] }",
5236 	  "{ [i] -> [NaN] }" },
5237 	{ "{ [i] -> [i] }", '-', "{ [i] -> [NaN] }",
5238 	  "{ [i] -> [NaN] }" },
5239 	{ "{ [i] -> [i] }", '*', "{ [i] -> [NaN] }",
5240 	  "{ [i] -> [NaN] }" },
5241 	{ "{ [i] -> [2] }", '*', "{ [i] -> [NaN] }",
5242 	  "{ [i] -> [NaN] }" },
5243 	{ "{ [i] -> [i] }", '/', "{ [i] -> [NaN] }",
5244 	  "{ [i] -> [NaN] }" },
5245 	{ "{ [i] -> [2] }", '/', "{ [i] -> [NaN] }",
5246 	  "{ [i] -> [NaN] }" },
5247 	{ "{ [i] -> [NaN] }", '+', "{ [i] -> [i] }",
5248 	  "{ [i] -> [NaN] }" },
5249 	{ "{ [i] -> [NaN] }", '-', "{ [i] -> [i] }",
5250 	  "{ [i] -> [NaN] }" },
5251 	{ "{ [i] -> [NaN] }", '*', "{ [i] -> [2] }",
5252 	  "{ [i] -> [NaN] }" },
5253 	{ "{ [i] -> [NaN] }", '*', "{ [i] -> [i] }",
5254 	  "{ [i] -> [NaN] }" },
5255 	{ "{ [i] -> [NaN] }", '/', "{ [i] -> [2] }",
5256 	  "{ [i] -> [NaN] }" },
5257 	{ "{ [i] -> [NaN] }", '/', "{ [i] -> [i] }",
5258 	  "{ [i] -> [NaN] }" },
5259 };
5260 
5261 /* Perform some basic tests of binary operations on isl_aff objects.
5262  */
test_bin_aff(isl_ctx * ctx)5263 static int test_bin_aff(isl_ctx *ctx)
5264 {
5265 	int i;
5266 	isl_aff *aff1, *aff2, *res;
5267 	__isl_give isl_aff *(*fn)(__isl_take isl_aff *aff1,
5268 				__isl_take isl_aff *aff2);
5269 	int ok;
5270 
5271 	for (i = 0; i < ARRAY_SIZE(aff_bin_tests); ++i) {
5272 		aff1 = isl_aff_read_from_str(ctx, aff_bin_tests[i].arg1);
5273 		aff2 = isl_aff_read_from_str(ctx, aff_bin_tests[i].arg2);
5274 		res = isl_aff_read_from_str(ctx, aff_bin_tests[i].res);
5275 		fn = aff_bin_op[aff_bin_tests[i].op].fn;
5276 		aff1 = fn(aff1, aff2);
5277 		if (isl_aff_is_nan(res))
5278 			ok = isl_aff_is_nan(aff1);
5279 		else
5280 			ok = isl_aff_plain_is_equal(aff1, res);
5281 		isl_aff_free(aff1);
5282 		isl_aff_free(res);
5283 		if (ok < 0)
5284 			return -1;
5285 		if (!ok)
5286 			isl_die(ctx, isl_error_unknown,
5287 				"unexpected result", return -1);
5288 	}
5289 
5290 	return 0;
5291 }
5292 
5293 struct {
5294 	__isl_give isl_pw_aff *(*fn)(__isl_take isl_pw_aff *pa1,
5295 				     __isl_take isl_pw_aff *pa2);
5296 } pw_aff_bin_op[] = {
5297 	['m'] = { &isl_pw_aff_min },
5298 	['M'] = { &isl_pw_aff_max },
5299 };
5300 
5301 /* Inputs for binary isl_pw_aff operation tests.
5302  * "arg1" and "arg2" are the two arguments, "op" identifies the operation
5303  * defined by pw_aff_bin_op, and "res" is the expected result.
5304  */
5305 struct {
5306 	const char *arg1;
5307 	unsigned char op;
5308 	const char *arg2;
5309 	const char *res;
5310 } pw_aff_bin_tests[] = {
5311 	{ "{ [i] -> [i] }", 'm', "{ [i] -> [i] }",
5312 	  "{ [i] -> [i] }" },
5313 	{ "{ [i] -> [i] }", 'M', "{ [i] -> [i] }",
5314 	  "{ [i] -> [i] }" },
5315 	{ "{ [i] -> [i] }", 'm', "{ [i] -> [0] }",
5316 	  "{ [i] -> [i] : i <= 0; [i] -> [0] : i > 0 }" },
5317 	{ "{ [i] -> [i] }", 'M', "{ [i] -> [0] }",
5318 	  "{ [i] -> [i] : i >= 0; [i] -> [0] : i < 0 }" },
5319 	{ "{ [i] -> [i] }", 'm', "{ [i] -> [NaN] }",
5320 	  "{ [i] -> [NaN] }" },
5321 	{ "{ [i] -> [NaN] }", 'm', "{ [i] -> [i] }",
5322 	  "{ [i] -> [NaN] }" },
5323 };
5324 
5325 /* Perform some basic tests of binary operations on isl_pw_aff objects.
5326  */
test_bin_pw_aff(isl_ctx * ctx)5327 static int test_bin_pw_aff(isl_ctx *ctx)
5328 {
5329 	int i;
5330 	isl_bool ok;
5331 	isl_pw_aff *pa1, *pa2, *res;
5332 
5333 	for (i = 0; i < ARRAY_SIZE(pw_aff_bin_tests); ++i) {
5334 		pa1 = isl_pw_aff_read_from_str(ctx, pw_aff_bin_tests[i].arg1);
5335 		pa2 = isl_pw_aff_read_from_str(ctx, pw_aff_bin_tests[i].arg2);
5336 		res = isl_pw_aff_read_from_str(ctx, pw_aff_bin_tests[i].res);
5337 		pa1 = pw_aff_bin_op[pw_aff_bin_tests[i].op].fn(pa1, pa2);
5338 		if (isl_pw_aff_involves_nan(res))
5339 			ok = isl_pw_aff_involves_nan(pa1);
5340 		else
5341 			ok = isl_pw_aff_plain_is_equal(pa1, res);
5342 		isl_pw_aff_free(pa1);
5343 		isl_pw_aff_free(res);
5344 		if (ok < 0)
5345 			return -1;
5346 		if (!ok)
5347 			isl_die(ctx, isl_error_unknown,
5348 				"unexpected result", return -1);
5349 	}
5350 
5351 	return 0;
5352 }
5353 
5354 struct {
5355 	__isl_give isl_union_pw_multi_aff *(*fn)(
5356 		__isl_take isl_union_pw_multi_aff *upma1,
5357 		__isl_take isl_union_pw_multi_aff *upma2);
5358 	const char *arg1;
5359 	const char *arg2;
5360 	const char *res;
5361 } upma_bin_tests[] = {
5362 	{ &isl_union_pw_multi_aff_add, "{ A[] -> [0]; B[0] -> [1] }",
5363 	  "{ B[x] -> [2] : x >= 0 }", "{ B[0] -> [3] }" },
5364 	{ &isl_union_pw_multi_aff_union_add, "{ A[] -> [0]; B[0] -> [1] }",
5365 	  "{ B[x] -> [2] : x >= 0 }",
5366 	  "{ A[] -> [0]; B[0] -> [3]; B[x] -> [2] : x >= 1 }" },
5367 	{ &isl_union_pw_multi_aff_pullback_union_pw_multi_aff,
5368 	  "{ A[] -> B[0]; C[x] -> B[1] : x < 10; C[y] -> B[2] : y >= 10 }",
5369 	  "{ D[i] -> A[] : i < 0; D[i] -> C[i + 5] : i >= 0 }",
5370 	  "{ D[i] -> B[0] : i < 0; D[i] -> B[1] : 0 <= i < 5; "
5371 	    "D[i] -> B[2] : i >= 5 }" },
5372 	{ &isl_union_pw_multi_aff_union_add, "{ B[x] -> A[1] : x <= 0 }",
5373 	  "{ B[x] -> C[2] : x > 0 }",
5374 	  "{ B[x] -> A[1] : x <= 0; B[x] -> C[2] : x > 0 }" },
5375 	{ &isl_union_pw_multi_aff_union_add, "{ B[x] -> A[1] : x <= 0 }",
5376 	  "{ B[x] -> A[2] : x >= 0 }",
5377 	  "{ B[x] -> A[1] : x < 0; B[x] -> A[2] : x > 0; B[0] -> A[3] }" },
5378 };
5379 
5380 /* Perform some basic tests of binary operations on
5381  * isl_union_pw_multi_aff objects.
5382  */
test_bin_upma(isl_ctx * ctx)5383 static int test_bin_upma(isl_ctx *ctx)
5384 {
5385 	int i;
5386 	isl_union_pw_multi_aff *upma1, *upma2, *res;
5387 	int ok;
5388 
5389 	for (i = 0; i < ARRAY_SIZE(upma_bin_tests); ++i) {
5390 		upma1 = isl_union_pw_multi_aff_read_from_str(ctx,
5391 							upma_bin_tests[i].arg1);
5392 		upma2 = isl_union_pw_multi_aff_read_from_str(ctx,
5393 							upma_bin_tests[i].arg2);
5394 		res = isl_union_pw_multi_aff_read_from_str(ctx,
5395 							upma_bin_tests[i].res);
5396 		upma1 = upma_bin_tests[i].fn(upma1, upma2);
5397 		ok = isl_union_pw_multi_aff_plain_is_equal(upma1, res);
5398 		isl_union_pw_multi_aff_free(upma1);
5399 		isl_union_pw_multi_aff_free(res);
5400 		if (ok < 0)
5401 			return -1;
5402 		if (!ok)
5403 			isl_die(ctx, isl_error_unknown,
5404 				"unexpected result", return -1);
5405 	}
5406 
5407 	return 0;
5408 }
5409 
5410 struct {
5411 	__isl_give isl_union_pw_multi_aff *(*fn)(
5412 		__isl_take isl_union_pw_multi_aff *upma1,
5413 		__isl_take isl_union_pw_multi_aff *upma2);
5414 	const char *arg1;
5415 	const char *arg2;
5416 } upma_bin_fail_tests[] = {
5417 	{ &isl_union_pw_multi_aff_union_add, "{ B[x] -> A[1] : x <= 0 }",
5418 	  "{ B[x] -> C[2] : x >= 0 }" },
5419 };
5420 
5421 /* Perform some basic tests of binary operations on
5422  * isl_union_pw_multi_aff objects that are expected to fail.
5423  */
test_bin_upma_fail(isl_ctx * ctx)5424 static int test_bin_upma_fail(isl_ctx *ctx)
5425 {
5426 	int i, n;
5427 	isl_union_pw_multi_aff *upma1, *upma2;
5428 	int on_error;
5429 
5430 	on_error = isl_options_get_on_error(ctx);
5431 	isl_options_set_on_error(ctx, ISL_ON_ERROR_CONTINUE);
5432 	n = ARRAY_SIZE(upma_bin_fail_tests);
5433 	for (i = 0; i < n; ++i) {
5434 		upma1 = isl_union_pw_multi_aff_read_from_str(ctx,
5435 						upma_bin_fail_tests[i].arg1);
5436 		upma2 = isl_union_pw_multi_aff_read_from_str(ctx,
5437 						upma_bin_fail_tests[i].arg2);
5438 		upma1 = upma_bin_fail_tests[i].fn(upma1, upma2);
5439 		isl_union_pw_multi_aff_free(upma1);
5440 		if (upma1)
5441 			break;
5442 	}
5443 	isl_options_set_on_error(ctx, on_error);
5444 	if (i < n)
5445 		isl_die(ctx, isl_error_unknown,
5446 			"operation not expected to succeed", return -1);
5447 
5448 	return 0;
5449 }
5450 
5451 /* Inputs for basic tests of binary operations on
5452  * pairs of isl_union_pw_multi_aff and isl_union_set objects.
5453  * "fn" is the function that is being tested.
5454  * "arg1" and "arg2" are string descriptions of the inputs.
5455  * "res" is a string description of the expected result.
5456  */
5457 struct {
5458 	__isl_give isl_union_pw_multi_aff *(*fn)(
5459 		__isl_take isl_union_pw_multi_aff *upma,
5460 		__isl_take isl_union_set *uset);
5461 	const char *arg1;
5462 	const char *arg2;
5463 	const char *res;
5464 } upma_uset_tests[] = {
5465 	{ &isl_union_pw_multi_aff_intersect_domain_wrapped_range,
5466 	  "{ A[i] -> B[i] }", "{ B[0] }",
5467 	  "{ }" },
5468 	{ &isl_union_pw_multi_aff_intersect_domain_wrapped_domain,
5469 	  "{ [A[i] -> B[i]] -> C[i + 1] }", "{ A[1]; B[0] }",
5470 	  "{ [A[1] -> B[1]] -> C[2] }" },
5471 	{ &isl_union_pw_multi_aff_intersect_domain_wrapped_range,
5472 	  "{ [A[i] -> B[i]] -> C[i + 1] }", "{ A[1]; B[0] }",
5473 	  "{ [A[0] -> B[0]] -> C[1] }" },
5474 	{ &isl_union_pw_multi_aff_intersect_domain_wrapped_range,
5475 	  "{ [A[i] -> B[i]] -> C[i + 1] }", "[N] -> { B[N] }",
5476 	  "[N] -> { [A[N] -> B[N]] -> C[N + 1] }" },
5477 	{ &isl_union_pw_multi_aff_intersect_domain_wrapped_range,
5478 	  "[M] -> { [A[M] -> B[M]] -> C[M + 1] }", "[N] -> { B[N] }",
5479 	  "[N, M] -> { [A[N] -> B[N]] -> C[N + 1] : N = M }" },
5480 	{ &isl_union_pw_multi_aff_intersect_domain_wrapped_range,
5481 	  "{ [A[] -> B[]] -> C[]; N[A[] -> B[]] -> D[]; [B[] -> A[]] -> E[] }",
5482 	  "{ B[] }",
5483 	  "{ [A[] -> B[]] -> C[]; N[A[] -> B[]] -> D[] }" },
5484 };
5485 
5486 /* Perform some basic tests of binary operations on
5487  * pairs of isl_union_pw_multi_aff and isl_union_set objects.
5488  */
test_upma_uset(isl_ctx * ctx)5489 static isl_stat test_upma_uset(isl_ctx *ctx)
5490 {
5491 	int i;
5492 	isl_bool ok;
5493 	isl_union_pw_multi_aff *upma, *res;
5494 	isl_union_set *uset;
5495 
5496 	for (i = 0; i < ARRAY_SIZE(upma_uset_tests); ++i) {
5497 		upma = isl_union_pw_multi_aff_read_from_str(ctx,
5498 						    upma_uset_tests[i].arg1);
5499 		uset = isl_union_set_read_from_str(ctx,
5500 						    upma_uset_tests[i].arg2);
5501 		res = isl_union_pw_multi_aff_read_from_str(ctx,
5502 						    upma_uset_tests[i].res);
5503 		upma = upma_uset_tests[i].fn(upma, uset);
5504 		ok = isl_union_pw_multi_aff_plain_is_equal(upma, res);
5505 		isl_union_pw_multi_aff_free(upma);
5506 		isl_union_pw_multi_aff_free(res);
5507 		if (ok < 0)
5508 			return isl_stat_error;
5509 		if (!ok)
5510 			isl_die(ctx, isl_error_unknown,
5511 				"unexpected result", return isl_stat_error);
5512 	}
5513 
5514 	return isl_stat_ok;
5515 }
5516 
5517 /* Inputs for basic tests of unary operations on isl_multi_pw_aff objects.
5518  * "fn" is the function that is tested.
5519  * "arg" is a string description of the input.
5520  * "res" is a string description of the expected result.
5521  */
5522 struct {
5523 	__isl_give isl_multi_pw_aff *(*fn)(__isl_take isl_multi_pw_aff *mpa);
5524 	const char *arg;
5525 	const char *res;
5526 } mpa_un_tests[] = {
5527 	{ &isl_multi_pw_aff_range_factor_domain,
5528 	  "{ A[x] -> [B[(1 : x >= 5)] -> C[(2 : x <= 10)]] }",
5529 	  "{ A[x] -> B[(1 : x >= 5)] }" },
5530 	{ &isl_multi_pw_aff_range_factor_range,
5531 	  "{ A[x] -> [B[(1 : x >= 5)] -> C[(2 : x <= 10)]] }",
5532 	  "{ A[y] -> C[(2 : y <= 10)] }" },
5533 	{ &isl_multi_pw_aff_range_factor_domain,
5534 	  "{ A[x] -> [B[(1 : x >= 5)] -> C[]] }",
5535 	  "{ A[x] -> B[(1 : x >= 5)] }" },
5536 	{ &isl_multi_pw_aff_range_factor_range,
5537 	  "{ A[x] -> [B[(1 : x >= 5)] -> C[]] }",
5538 	  "{ A[y] -> C[] }" },
5539 	{ &isl_multi_pw_aff_range_factor_domain,
5540 	  "{ A[x] -> [B[] -> C[(2 : x <= 10)]] }",
5541 	  "{ A[x] -> B[] }" },
5542 	{ &isl_multi_pw_aff_range_factor_range,
5543 	  "{ A[x] -> [B[] -> C[(2 : x <= 10)]] }",
5544 	  "{ A[y] -> C[(2 : y <= 10)] }" },
5545 	{ &isl_multi_pw_aff_range_factor_domain,
5546 	  "{ A[x] -> [B[] -> C[]] }",
5547 	  "{ A[x] -> B[] }" },
5548 	{ &isl_multi_pw_aff_range_factor_range,
5549 	  "{ A[x] -> [B[] -> C[]] }",
5550 	  "{ A[y] -> C[] }" },
5551 	{ &isl_multi_pw_aff_factor_range,
5552 	  "{ [B[] -> C[]] }",
5553 	  "{ C[] }" },
5554 	{ &isl_multi_pw_aff_range_factor_domain,
5555 	  "{ A[x] -> [B[] -> C[]] : x >= 0 }",
5556 	  "{ A[x] -> B[] : x >= 0 }" },
5557 	{ &isl_multi_pw_aff_range_factor_range,
5558 	  "{ A[x] -> [B[] -> C[]] : x >= 0 }",
5559 	  "{ A[y] -> C[] : y >= 0 }" },
5560 	{ &isl_multi_pw_aff_factor_range,
5561 	  "[N] -> { [B[] -> C[]] : N >= 0 }",
5562 	  "[N] -> { C[] : N >= 0 }" },
5563 };
5564 
5565 /* Perform some basic tests of unary operations on isl_multi_pw_aff objects.
5566  */
test_un_mpa(isl_ctx * ctx)5567 static int test_un_mpa(isl_ctx *ctx)
5568 {
5569 	int i;
5570 	isl_bool ok;
5571 	isl_multi_pw_aff *mpa, *res;
5572 
5573 	for (i = 0; i < ARRAY_SIZE(mpa_un_tests); ++i) {
5574 		mpa = isl_multi_pw_aff_read_from_str(ctx, mpa_un_tests[i].arg);
5575 		res = isl_multi_pw_aff_read_from_str(ctx, mpa_un_tests[i].res);
5576 		mpa = mpa_un_tests[i].fn(mpa);
5577 		ok = isl_multi_pw_aff_plain_is_equal(mpa, res);
5578 		isl_multi_pw_aff_free(mpa);
5579 		isl_multi_pw_aff_free(res);
5580 		if (ok < 0)
5581 			return -1;
5582 		if (!ok)
5583 			isl_die(ctx, isl_error_unknown,
5584 				"unexpected result", return -1);
5585 	}
5586 
5587 	return 0;
5588 }
5589 
5590 /* Inputs for basic tests of binary operations on isl_multi_pw_aff objects.
5591  * "fn" is the function that is tested.
5592  * "arg1" and "arg2" are string descriptions of the inputs.
5593  * "res" is a string description of the expected result.
5594  */
5595 struct {
5596 	__isl_give isl_multi_pw_aff *(*fn)(
5597 		__isl_take isl_multi_pw_aff *mpa1,
5598 		__isl_take isl_multi_pw_aff *mpa2);
5599 	const char *arg1;
5600 	const char *arg2;
5601 	const char *res;
5602 } mpa_bin_tests[] = {
5603 	{ &isl_multi_pw_aff_add, "{ A[] -> [1] }", "{ A[] -> [2] }",
5604 	  "{ A[] -> [3] }" },
5605 	{ &isl_multi_pw_aff_add, "{ A[x] -> [(1 : x >= 5)] }",
5606 	  "{ A[x] -> [(x : x <= 10)] }",
5607 	  "{ A[x] -> [(1 + x : 5 <= x <= 10)] }" },
5608 	{ &isl_multi_pw_aff_add, "{ A[x] -> [] : x >= 5 }",
5609 	  "{ A[x] -> [] : x <= 10 }",
5610 	  "{ A[x] -> [] : 5 <= x <= 10 }" },
5611 	{ &isl_multi_pw_aff_add, "{ A[x] -> [] : x >= 5 }",
5612 	  "[N] -> { A[x] -> [] : x <= N }",
5613 	  "[N] -> { A[x] -> [] : 5 <= x <= N }" },
5614 	{ &isl_multi_pw_aff_add,
5615 	  "[N] -> { A[x] -> [] : x <= N }",
5616 	  "{ A[x] -> [] : x >= 5 }",
5617 	  "[N] -> { A[x] -> [] : 5 <= x <= N }" },
5618 	{ &isl_multi_pw_aff_range_product, "{ A[x] -> B[(1 : x >= 5)] }",
5619 	  "{ A[y] -> C[(2 : y <= 10)] }",
5620 	  "{ A[x] -> [B[(1 : x >= 5)] -> C[(2 : x <= 10)]] }" },
5621 	{ &isl_multi_pw_aff_range_product, "{ A[x] -> B[1] : x >= 5 }",
5622 	  "{ A[y] -> C[2] : y <= 10 }",
5623 	  "{ A[x] -> [B[(1 : x >= 5)] -> C[(2 : x <= 10)]] }" },
5624 	{ &isl_multi_pw_aff_range_product, "{ A[x] -> B[1] : x >= 5 }",
5625 	  "[N] -> { A[y] -> C[2] : y <= N }",
5626 	  "[N] -> { A[x] -> [B[(1 : x >= 5)] -> C[(2 : x <= N)]] }" },
5627 	{ &isl_multi_pw_aff_range_product, "[N] -> { A[x] -> B[1] : x >= N }",
5628 	  "{ A[y] -> C[2] : y <= 10 }",
5629 	  "[N] -> { A[x] -> [B[(1 : x >= N)] -> C[(2 : x <= 10)]] }" },
5630 	{ &isl_multi_pw_aff_range_product, "{ A[] -> B[1] }", "{ A[] -> C[2] }",
5631 	  "{ A[] -> [B[1] -> C[2]] }" },
5632 	{ &isl_multi_pw_aff_range_product, "{ A[] -> B[] }", "{ A[] -> C[] }",
5633 	  "{ A[] -> [B[] -> C[]] }" },
5634 	{ &isl_multi_pw_aff_range_product, "{ A[x] -> B[(1 : x >= 5)] }",
5635 	  "{ A[y] -> C[] : y <= 10 }",
5636 	  "{ A[x] -> [B[(1 : x >= 5)] -> C[]] : x <= 10 }" },
5637 	{ &isl_multi_pw_aff_range_product, "{ A[y] -> C[] : y <= 10 }",
5638 	  "{ A[x] -> B[(1 : x >= 5)] }",
5639 	  "{ A[x] -> [C[] -> B[(1 : x >= 5)]] : x <= 10 }" },
5640 	{ &isl_multi_pw_aff_product, "{ A[x] -> B[(1 : x >= 5)] }",
5641 	  "{ A[y] -> C[(2 : y <= 10)] }",
5642 	  "{ [A[x] -> A[y]] -> [B[(1 : x >= 5)] -> C[(2 : y <= 10)]] }" },
5643 	{ &isl_multi_pw_aff_product, "{ A[x] -> B[(1 : x >= 5)] }",
5644 	  "{ A[y] -> C[] : y <= 10 }",
5645 	  "{ [A[x] -> A[y]] -> [B[(1 : x >= 5)] -> C[]] : y <= 10 }" },
5646 	{ &isl_multi_pw_aff_product, "{ A[y] -> C[] : y <= 10 }",
5647 	  "{ A[x] -> B[(1 : x >= 5)] }",
5648 	  "{ [A[y] -> A[x]] -> [C[] -> B[(1 : x >= 5)]] : y <= 10 }" },
5649 	{ &isl_multi_pw_aff_product, "{ A[x] -> B[(1 : x >= 5)] }",
5650 	  "[N] -> { A[y] -> C[] : y <= N }",
5651 	  "[N] -> { [A[x] -> A[y]] -> [B[(1 : x >= 5)] -> C[]] : y <= N }" },
5652 	{ &isl_multi_pw_aff_product, "[N] -> { A[y] -> C[] : y <= N }",
5653 	  "{ A[x] -> B[(1 : x >= 5)] }",
5654 	  "[N] -> { [A[y] -> A[x]] -> [C[] -> B[(1 : x >= 5)]] : y <= N }" },
5655 	{ &isl_multi_pw_aff_product, "{ A[x] -> B[] : x >= 5 }",
5656 	  "{ A[y] -> C[] : y <= 10 }",
5657 	  "{ [A[x] -> A[y]] -> [B[] -> C[]] : x >= 5 and y <= 10 }" },
5658 	{ &isl_multi_pw_aff_product, "{ A[] -> B[1] }", "{ A[] -> C[2] }",
5659 	  "{ [A[] -> A[]] -> [B[1] -> C[2]] }" },
5660 	{ &isl_multi_pw_aff_product, "{ A[] -> B[] }", "{ A[] -> C[] }",
5661 	  "{ [A[] -> A[]] -> [B[] -> C[]] }" },
5662 	{ &isl_multi_pw_aff_pullback_multi_pw_aff,
5663 	  "{ B[i,j] -> C[i + 2j] }", "{ A[a,b] -> B[b,a] }",
5664 	  "{ A[a,b] -> C[b + 2a] }" },
5665 	{ &isl_multi_pw_aff_pullback_multi_pw_aff,
5666 	  "{ B[i,j] -> C[i + 2j] }",
5667 	  "{ A[a,b] -> B[(b : b > a),(a : b > a)] }",
5668 	  "{ A[a,b] -> C[(b + 2a : b > a)] }" },
5669 	{ &isl_multi_pw_aff_pullback_multi_pw_aff,
5670 	  "{ B[i,j] -> C[(i + 2j : j > 4)] }",
5671 	  "{ A[a,b] -> B[(b : b > a),(a : b > a)] }",
5672 	  "{ A[a,b] -> C[(b + 2a : b > a > 4)] }" },
5673 	{ &isl_multi_pw_aff_pullback_multi_pw_aff,
5674 	  "{ B[i,j] -> C[] }",
5675 	  "{ A[a,b] -> B[(b : b > a),(a : b > a)] }",
5676 	  "{ A[a,b] -> C[] }" },
5677 	{ &isl_multi_pw_aff_pullback_multi_pw_aff,
5678 	  "{ B[i,j] -> C[] : i > j }",
5679 	  "{ A[a,b] -> B[b,a] }",
5680 	  "{ A[a,b] -> C[] : b > a }" },
5681 	{ &isl_multi_pw_aff_pullback_multi_pw_aff,
5682 	  "{ B[i,j] -> C[] : j > 5 }",
5683 	  "{ A[a,b] -> B[(b : b > a),(a : b > a)] }",
5684 	  "{ A[a,b] -> C[] : b > a > 5 }" },
5685 	{ &isl_multi_pw_aff_pullback_multi_pw_aff,
5686 	  "[N] -> { B[i,j] -> C[] : j > N }",
5687 	  "{ A[a,b] -> B[(b : b > a),(a : b > a)] }",
5688 	  "[N] -> { A[a,b] -> C[] : b > a > N }" },
5689 	{ &isl_multi_pw_aff_pullback_multi_pw_aff,
5690 	  "[M,N] -> { B[] -> C[] : N > 5 }",
5691 	  "[M,N] -> { A[] -> B[] : M > N }",
5692 	  "[M,N] -> { A[] -> C[] : M > N > 5 }" },
5693 };
5694 
5695 /* Perform some basic tests of binary operations on isl_multi_pw_aff objects.
5696  */
test_bin_mpa(isl_ctx * ctx)5697 static int test_bin_mpa(isl_ctx *ctx)
5698 {
5699 	int i;
5700 	isl_bool ok;
5701 	isl_multi_pw_aff *mpa1, *mpa2, *res;
5702 
5703 	for (i = 0; i < ARRAY_SIZE(mpa_bin_tests); ++i) {
5704 		mpa1 = isl_multi_pw_aff_read_from_str(ctx,
5705 							mpa_bin_tests[i].arg1);
5706 		mpa2 = isl_multi_pw_aff_read_from_str(ctx,
5707 							mpa_bin_tests[i].arg2);
5708 		res = isl_multi_pw_aff_read_from_str(ctx,
5709 							mpa_bin_tests[i].res);
5710 		mpa1 = mpa_bin_tests[i].fn(mpa1, mpa2);
5711 		ok = isl_multi_pw_aff_plain_is_equal(mpa1, res);
5712 		isl_multi_pw_aff_free(mpa1);
5713 		isl_multi_pw_aff_free(res);
5714 		if (ok < 0)
5715 			return -1;
5716 		if (!ok)
5717 			isl_die(ctx, isl_error_unknown,
5718 				"unexpected result", return -1);
5719 	}
5720 
5721 	return 0;
5722 }
5723 
5724 /* Inputs for basic tests of unary operations on
5725  * isl_multi_union_pw_aff objects.
5726  * "fn" is the function that is tested.
5727  * "arg" is a string description of the input.
5728  * "res" is a string description of the expected result.
5729  */
5730 struct {
5731 	__isl_give isl_multi_union_pw_aff *(*fn)(
5732 		__isl_take isl_multi_union_pw_aff *mupa);
5733 	const char *arg;
5734 	const char *res;
5735 } mupa_un_tests[] = {
5736 	{ &isl_multi_union_pw_aff_factor_range,
5737 	  "[B[{ A[] -> [1] }] -> C[{ A[] -> [2] }]]",
5738 	  "C[{ A[] -> [2] }]" },
5739 	{ &isl_multi_union_pw_aff_factor_range,
5740 	  "[B[] -> C[{ A[] -> [2] }]]",
5741 	  "C[{ A[] -> [2] }]" },
5742 	{ &isl_multi_union_pw_aff_factor_range,
5743 	  "[B[{ A[] -> [1] }] -> C[]]",
5744 	  "C[]" },
5745 	{ &isl_multi_union_pw_aff_factor_range,
5746 	  "[B[] -> C[]]",
5747 	  "C[]" },
5748 	{ &isl_multi_union_pw_aff_factor_range,
5749 	  "([B[] -> C[]] : { A[x] : x >= 0 })",
5750 	  "(C[] : { A[x] : x >= 0 })" },
5751 	{ &isl_multi_union_pw_aff_factor_range,
5752 	  "[N] -> ([B[] -> C[]] : { A[x] : x <= N })",
5753 	  "[N] -> (C[] : { A[x] : x <= N })" },
5754 	{ &isl_multi_union_pw_aff_factor_range,
5755 	  "[N] -> ([B[] -> C[]] : { : N >= 0 })",
5756 	  "[N] -> (C[] : { : N >= 0 })" },
5757 };
5758 
5759 /* Perform some basic tests of unary operations on
5760  * isl_multi_union_pw_aff objects.
5761  */
test_un_mupa(isl_ctx * ctx)5762 static int test_un_mupa(isl_ctx *ctx)
5763 {
5764 	int i;
5765 	isl_bool ok;
5766 	isl_multi_union_pw_aff *mupa, *res;
5767 
5768 	for (i = 0; i < ARRAY_SIZE(mupa_un_tests); ++i) {
5769 		mupa = isl_multi_union_pw_aff_read_from_str(ctx,
5770 							mupa_un_tests[i].arg);
5771 		res = isl_multi_union_pw_aff_read_from_str(ctx,
5772 							mupa_un_tests[i].res);
5773 		mupa = mupa_un_tests[i].fn(mupa);
5774 		ok = isl_multi_union_pw_aff_plain_is_equal(mupa, res);
5775 		isl_multi_union_pw_aff_free(mupa);
5776 		isl_multi_union_pw_aff_free(res);
5777 		if (ok < 0)
5778 			return -1;
5779 		if (!ok)
5780 			isl_die(ctx, isl_error_unknown,
5781 				"unexpected result", return -1);
5782 	}
5783 
5784 	return 0;
5785 }
5786 
5787 /* Inputs for basic tests of binary operations on
5788  * isl_multi_union_pw_aff objects.
5789  * "fn" is the function that is tested.
5790  * "arg1" and "arg2" are string descriptions of the inputs.
5791  * "res" is a string description of the expected result.
5792  */
5793 struct {
5794 	__isl_give isl_multi_union_pw_aff *(*fn)(
5795 		__isl_take isl_multi_union_pw_aff *mupa1,
5796 		__isl_take isl_multi_union_pw_aff *mupa2);
5797 	const char *arg1;
5798 	const char *arg2;
5799 	const char *res;
5800 } mupa_bin_tests[] = {
5801 	{ &isl_multi_union_pw_aff_add, "[{ A[] -> [1] }]", "[{ A[] -> [2] }]",
5802 	  "[{ A[] -> [3] }]" },
5803 	{ &isl_multi_union_pw_aff_sub, "[{ A[] -> [1] }]", "[{ A[] -> [2] }]",
5804 	  "[{ A[] -> [-1] }]" },
5805 	{ &isl_multi_union_pw_aff_add,
5806 	  "[{ A[] -> [1]; B[] -> [4] }]",
5807 	  "[{ A[] -> [2]; C[] -> [5] }]",
5808 	  "[{ A[] -> [3] }]" },
5809 	{ &isl_multi_union_pw_aff_union_add,
5810 	  "[{ A[] -> [1]; B[] -> [4] }]",
5811 	  "[{ A[] -> [2]; C[] -> [5] }]",
5812 	  "[{ A[] -> [3]; B[] -> [4]; C[] -> [5] }]" },
5813 	{ &isl_multi_union_pw_aff_add, "[{ A[x] -> [(1)] : x >= 5 }]",
5814 	  "[{ A[x] -> [(x)] : x <= 10 }]",
5815 	  "[{ A[x] -> [(1 + x)] : 5 <= x <= 10 }]" },
5816 	{ &isl_multi_union_pw_aff_add, "([] : { A[x] : x >= 5 })",
5817 	  "([] : { A[x] : x <= 10 })",
5818 	  "([] : { A[x] : 5 <= x <= 10 })" },
5819 	{ &isl_multi_union_pw_aff_add, "([] : { A[x] : x >= 5 })",
5820 	  "[N] -> ([] : { A[x] : x <= N })",
5821 	  "[N] -> ([] : { A[x] : 5 <= x <= N })" },
5822 	{ &isl_multi_union_pw_aff_add, "[N] -> ([] : { A[x] : x >= N })",
5823 	  "([] : { A[x] : x <= 10 })",
5824 	  "[N] -> ([] : { A[x] : N <= x <= 10 })" },
5825 	{ &isl_multi_union_pw_aff_union_add, "[{ A[x] -> [(1)] : x >= 5 }]",
5826 	  "[{ A[x] -> [(x)] : x <= 10 }]",
5827 	  "[{ A[x] -> [(1 + x)] : 5 <= x <= 10; "
5828 	     "A[x] -> [(1)] : x > 10; A[x] -> [(x)] : x < 5 }]" },
5829 	{ &isl_multi_union_pw_aff_union_add, "([] : { A[x] : x >= 5 })",
5830 	  "([] : { A[x] : x <= 10 })",
5831 	  "([] : { A[x] })" },
5832 	{ &isl_multi_union_pw_aff_union_add, "([] : { A[x] : x >= 0 })",
5833 	  "[N] -> ([] : { A[x] : x >= N })",
5834 	  "[N] -> ([] : { A[x] : x >= 0 or x >= N })" },
5835 	{ &isl_multi_union_pw_aff_union_add,
5836 	  "[N] -> ([] : { A[] : N >= 0})",
5837 	  "[N] -> ([] : { A[] : N <= 0})",
5838 	  "[N] -> ([] : { A[] })" },
5839 	{ &isl_multi_union_pw_aff_union_add,
5840 	  "[N] -> ([] : { A[] })",
5841 	  "[N] -> ([] : { : })",
5842 	  "[N] -> ([] : { : })" },
5843 	{ &isl_multi_union_pw_aff_union_add,
5844 	  "[N] -> ([] : { : })",
5845 	  "[N] -> ([] : { A[] })",
5846 	  "[N] -> ([] : { : })" },
5847 	{ &isl_multi_union_pw_aff_union_add,
5848 	  "[N] -> ([] : { : N >= 0})",
5849 	  "[N] -> ([] : { : N <= 0})",
5850 	  "[N] -> ([] : { : })" },
5851 	{ &isl_multi_union_pw_aff_range_product,
5852 	  "B[{ A[] -> [1] }]",
5853 	  "C[{ A[] -> [2] }]",
5854 	  "[B[{ A[] -> [1] }] -> C[{ A[] -> [2] }]]" },
5855 	{ &isl_multi_union_pw_aff_range_product,
5856 	  "(B[] : { A[x] : x >= 5 })",
5857 	  "(C[] : { A[x] : x <= 10 })",
5858 	  "([B[] -> C[]] : { A[x] : 5 <= x <= 10 })" },
5859 	{ &isl_multi_union_pw_aff_range_product,
5860 	  "B[{ A[x] -> [x + 1] : x >= 5 }]",
5861 	  "(C[] : { A[x] : x <= 10 })",
5862 	  "[B[{ A[x] -> [x + 1] : 5 <= x <= 10 }] -> C[]]" },
5863 	{ &isl_multi_union_pw_aff_range_product,
5864 	  "(C[] : { A[x] : x <= 10 })",
5865 	  "B[{ A[x] -> [x + 1] : x >= 5 }]",
5866 	  "[C[] -> B[{ A[x] -> [x + 1] : 5 <= x <= 10 }]]" },
5867 	{ &isl_multi_union_pw_aff_range_product,
5868 	  "B[{ A[x] -> [x + 1] : x >= 5 }]",
5869 	  "[N] -> (C[] : { A[x] : x <= N })",
5870 	  "[N] -> [B[{ A[x] -> [x + 1] : 5 <= x <= N }] -> C[]]" },
5871 	{ &isl_multi_union_pw_aff_range_product,
5872 	  "[N] -> (C[] : { A[x] : x <= N })",
5873 	  "B[{ A[x] -> [x + 1] : x >= 5 }]",
5874 	  "[N] -> [C[] -> B[{ A[x] -> [x + 1] : 5 <= x <= N }]]" },
5875 	{ &isl_multi_union_pw_aff_range_product,
5876 	  "B[{ A[] -> [1]; D[] -> [3] }]",
5877 	  "C[{ A[] -> [2] }]",
5878 	  "[B[{ A[] -> [1]; D[] -> [3] }] -> C[{ A[] -> [2] }]]" },
5879 	{ &isl_multi_union_pw_aff_range_product,
5880 	  "B[] }]",
5881 	  "(C[] : { A[x] })",
5882 	  "([B[] -> C[]] : { A[x] })" },
5883 	{ &isl_multi_union_pw_aff_range_product,
5884 	  "(B[] : { A[x] })",
5885 	  "C[] }]",
5886 	  "([B[] -> C[]] : { A[x] })" },
5887 };
5888 
5889 /* Perform some basic tests of binary operations on
5890  * isl_multi_union_pw_aff objects.
5891  */
test_bin_mupa(isl_ctx * ctx)5892 static int test_bin_mupa(isl_ctx *ctx)
5893 {
5894 	int i;
5895 	isl_bool ok;
5896 	isl_multi_union_pw_aff *mupa1, *mupa2, *res;
5897 
5898 	for (i = 0; i < ARRAY_SIZE(mupa_bin_tests); ++i) {
5899 		mupa1 = isl_multi_union_pw_aff_read_from_str(ctx,
5900 							mupa_bin_tests[i].arg1);
5901 		mupa2 = isl_multi_union_pw_aff_read_from_str(ctx,
5902 							mupa_bin_tests[i].arg2);
5903 		res = isl_multi_union_pw_aff_read_from_str(ctx,
5904 							mupa_bin_tests[i].res);
5905 		mupa1 = mupa_bin_tests[i].fn(mupa1, mupa2);
5906 		ok = isl_multi_union_pw_aff_plain_is_equal(mupa1, res);
5907 		isl_multi_union_pw_aff_free(mupa1);
5908 		isl_multi_union_pw_aff_free(res);
5909 		if (ok < 0)
5910 			return -1;
5911 		if (!ok)
5912 			isl_die(ctx, isl_error_unknown,
5913 				"unexpected result", return -1);
5914 	}
5915 
5916 	return 0;
5917 }
5918 
5919 /* Inputs for basic tests of binary operations on
5920  * pairs of isl_multi_union_pw_aff and isl_set objects.
5921  * "fn" is the function that is tested.
5922  * "arg1" and "arg2" are string descriptions of the inputs.
5923  * "res" is a string description of the expected result.
5924  */
5925 struct {
5926 	__isl_give isl_multi_union_pw_aff *(*fn)(
5927 		__isl_take isl_multi_union_pw_aff *mupa,
5928 		__isl_take isl_set *set);
5929 	const char *arg1;
5930 	const char *arg2;
5931 	const char *res;
5932 } mupa_set_tests[] = {
5933 	{ &isl_multi_union_pw_aff_intersect_range,
5934 	  "C[{ B[i,j] -> [i + 2j] }]", "{ C[1] }",
5935 	  "C[{ B[i,j] -> [i + 2j] : i + 2j = 1 }]" },
5936 	{ &isl_multi_union_pw_aff_intersect_range,
5937 	  "C[{ B[i,j] -> [i + 2j] }]", "[N] -> { C[N] }",
5938 	  "[N] -> C[{ B[i,j] -> [i + 2j] : i + 2j = N }]" },
5939 	{ &isl_multi_union_pw_aff_intersect_range,
5940 	  "[N] -> C[{ B[i,j] -> [i + 2j + N] }]", "{ C[1] }",
5941 	  "[N] -> C[{ B[i,j] -> [i + 2j + N] : i + 2j + N = 1 }]" },
5942 	{ &isl_multi_union_pw_aff_intersect_range,
5943 	  "C[{ B[i,j] -> [i + 2j] }]", "[N] -> { C[x] : N >= 0 }",
5944 	  "[N] -> C[{ B[i,j] -> [i + 2j] : N >= 0 }]" },
5945 	{ &isl_multi_union_pw_aff_intersect_range,
5946 	  "C[]", "{ C[] }", "C[]" },
5947 	{ &isl_multi_union_pw_aff_intersect_range,
5948 	  "[N] -> (C[] : { : N >= 0 })",
5949 	  "{ C[] }",
5950 	  "[N] -> (C[] : { : N >= 0 })" },
5951 	{ &isl_multi_union_pw_aff_intersect_range,
5952 	  "(C[] : { A[a,b] })",
5953 	  "{ C[] }",
5954 	  "(C[] : { A[a,b] })" },
5955 	{ &isl_multi_union_pw_aff_intersect_range,
5956 	  "[N] -> (C[] : { A[a,b] : a,b <= N })",
5957 	  "{ C[] }",
5958 	  "[N] -> (C[] : { A[a,b] : a,b <= N })" },
5959 	{ &isl_multi_union_pw_aff_intersect_range,
5960 	  "C[]",
5961 	  "[N] -> { C[] : N >= 0 }",
5962 	  "[N] -> (C[] : { : N >= 0 })" },
5963 	{ &isl_multi_union_pw_aff_intersect_range,
5964 	  "(C[] : { A[a,b] })",
5965 	  "[N] -> { C[] : N >= 0 }",
5966 	  "[N] -> (C[] : { A[a,b] : N >= 0 })" },
5967 	{ &isl_multi_union_pw_aff_intersect_range,
5968 	  "[N] -> (C[] : { : N >= 0 })",
5969 	  "[N] -> { C[] : N < 1024 }",
5970 	  "[N] -> (C[] : { : 0 <= N < 1024 })" },
5971 	{ &isl_multi_union_pw_aff_intersect_params,
5972 	  "C[{ B[i,j] -> [i + 2j] }]", "[N] -> { : N >= 0 }",
5973 	  "[N] -> C[{ B[i,j] -> [i + 2j] : N >= 0}]" },
5974 	{ &isl_multi_union_pw_aff_intersect_params,
5975 	  "[N] -> C[{ B[i,j] -> [i + 2j] : N <= 256 }]", "[N] -> { : N >= 0 }",
5976 	  "[N] -> C[{ B[i,j] -> [i + 2j] : 0 <= N <= 256 }]" },
5977 	{ &isl_multi_union_pw_aff_intersect_params,
5978 	  "[N] -> C[{ B[i,j] -> [i + 2j] : N <= 256 }]", "{ : }",
5979 	  "[N] -> C[{ B[i,j] -> [i + 2j] : N <= 256 }]" },
5980 	{ &isl_multi_union_pw_aff_intersect_params,
5981 	  "C[]", "[N] -> { : N >= 0 }",
5982 	  "[N] -> (C[] : { : N >= 0 })" },
5983 	{ &isl_multi_union_pw_aff_intersect_params,
5984 	  "(C[] : { A[a,b] })", "[N] -> { : N >= 0 }",
5985 	  "[N] -> (C[] : { A[a,b] : N >= 0 })" },
5986 	{ &isl_multi_union_pw_aff_intersect_params,
5987 	  "[N] -> (C[] : { A[a,N] })", "{ : }",
5988 	  "[N] -> (C[] : { A[a,N] })" },
5989 	{ &isl_multi_union_pw_aff_intersect_params,
5990 	  "[N] -> (C[] : { A[a,b] : N <= 256 })", "[N] -> { : N >= 0 }",
5991 	  "[N] -> (C[] : { A[a,b] : 0 <= N <= 256 })" },
5992 };
5993 
5994 /* Perform some basic tests of binary operations on
5995  * pairs of isl_multi_union_pw_aff and isl_set objects.
5996  */
test_mupa_set(isl_ctx * ctx)5997 static int test_mupa_set(isl_ctx *ctx)
5998 {
5999 	int i;
6000 	isl_bool ok;
6001 	isl_multi_union_pw_aff *mupa, *res;
6002 	isl_set *set;
6003 
6004 	for (i = 0; i < ARRAY_SIZE(mupa_set_tests); ++i) {
6005 		mupa = isl_multi_union_pw_aff_read_from_str(ctx,
6006 						    mupa_set_tests[i].arg1);
6007 		set = isl_set_read_from_str(ctx, mupa_set_tests[i].arg2);
6008 		res = isl_multi_union_pw_aff_read_from_str(ctx,
6009 						    mupa_set_tests[i].res);
6010 		mupa = mupa_set_tests[i].fn(mupa, set);
6011 		ok = isl_multi_union_pw_aff_plain_is_equal(mupa, res);
6012 		isl_multi_union_pw_aff_free(mupa);
6013 		isl_multi_union_pw_aff_free(res);
6014 		if (ok < 0)
6015 			return -1;
6016 		if (!ok)
6017 			isl_die(ctx, isl_error_unknown,
6018 				"unexpected result", return -1);
6019 	}
6020 
6021 	return 0;
6022 }
6023 
6024 /* Inputs for basic tests of binary operations on
6025  * pairs of isl_multi_union_pw_aff and isl_union_set objects.
6026  * "fn" is the function that is tested.
6027  * "arg1" and "arg2" are string descriptions of the inputs.
6028  * "res" is a string description of the expected result.
6029  */
6030 struct {
6031 	__isl_give isl_multi_union_pw_aff *(*fn)(
6032 		__isl_take isl_multi_union_pw_aff *mupa,
6033 		__isl_take isl_union_set *uset);
6034 	const char *arg1;
6035 	const char *arg2;
6036 	const char *res;
6037 } mupa_uset_tests[] = {
6038 	{ &isl_multi_union_pw_aff_intersect_domain,
6039 	  "C[{ B[i,j] -> [i + 2j] }]", "{ B[i,i] }",
6040 	  "C[{ B[i,i] -> [3i] }]" },
6041 	{ &isl_multi_union_pw_aff_intersect_domain,
6042 	  "(C[] : { B[i,j] })", "{ B[i,i] }",
6043 	  "(C[] : { B[i,i] })" },
6044 	{ &isl_multi_union_pw_aff_intersect_domain,
6045 	  "(C[] : { B[i,j] })", "[N] -> { B[N,N] }",
6046 	  "[N] -> (C[] : { B[N,N] })" },
6047 	{ &isl_multi_union_pw_aff_intersect_domain,
6048 	  "C[]", "{ B[i,i] }",
6049 	  "(C[] : { B[i,i] })" },
6050 	{ &isl_multi_union_pw_aff_intersect_domain,
6051 	  "[N] -> (C[] : { : N >= 0 })", "{ B[i,i] }",
6052 	  "[N] -> (C[] : { B[i,i] : N >= 0 })" },
6053 };
6054 
6055 /* Perform some basic tests of binary operations on
6056  * pairs of isl_multi_union_pw_aff and isl_union_set objects.
6057  */
test_mupa_uset(isl_ctx * ctx)6058 static int test_mupa_uset(isl_ctx *ctx)
6059 {
6060 	int i;
6061 	isl_bool ok;
6062 	isl_multi_union_pw_aff *mupa, *res;
6063 	isl_union_set *uset;
6064 
6065 	for (i = 0; i < ARRAY_SIZE(mupa_uset_tests); ++i) {
6066 		mupa = isl_multi_union_pw_aff_read_from_str(ctx,
6067 						    mupa_uset_tests[i].arg1);
6068 		uset = isl_union_set_read_from_str(ctx,
6069 						    mupa_uset_tests[i].arg2);
6070 		res = isl_multi_union_pw_aff_read_from_str(ctx,
6071 						    mupa_uset_tests[i].res);
6072 		mupa = mupa_uset_tests[i].fn(mupa, uset);
6073 		ok = isl_multi_union_pw_aff_plain_is_equal(mupa, res);
6074 		isl_multi_union_pw_aff_free(mupa);
6075 		isl_multi_union_pw_aff_free(res);
6076 		if (ok < 0)
6077 			return -1;
6078 		if (!ok)
6079 			isl_die(ctx, isl_error_unknown,
6080 				"unexpected result", return -1);
6081 	}
6082 
6083 	return 0;
6084 }
6085 
6086 /* Inputs for basic tests of binary operations on
6087  * pairs of isl_multi_union_pw_aff and isl_multi_aff objects.
6088  * "fn" is the function that is tested.
6089  * "arg1" and "arg2" are string descriptions of the inputs.
6090  * "res" is a string description of the expected result.
6091  */
6092 struct {
6093 	__isl_give isl_multi_union_pw_aff *(*fn)(
6094 		__isl_take isl_multi_union_pw_aff *mupa,
6095 		__isl_take isl_multi_aff *ma);
6096 	const char *arg1;
6097 	const char *arg2;
6098 	const char *res;
6099 } mupa_ma_tests[] = {
6100 	{ &isl_multi_union_pw_aff_apply_multi_aff,
6101 	  "C[{ A[i,j] -> [i]; B[i,j] -> [j] }, "
6102 	    "{ A[i,j] -> [j]; B[i,j] -> [i] }]",
6103 	  "{ C[a,b] -> D[b,a] }",
6104 	  "D[{ A[i,j] -> [j]; B[i,j] -> [i] }, "
6105 	    "{ A[i,j] -> [i]; B[i,j] -> [j] }]" },
6106 	{ &isl_multi_union_pw_aff_apply_multi_aff,
6107 	  "C[{ A[i,j] -> [i] : i >= 0; B[i,j] -> [j] }, "
6108 	    "{ A[i,j] -> [j]; B[i,j] -> [i] }]",
6109 	  "{ C[a,b] -> D[b,a] }",
6110 	  "D[{ A[i,j] -> [j] : i >= 0; B[i,j] -> [i] }, "
6111 	    "{ A[i,j] -> [i] : i >= 0; B[i,j] -> [j] }]" },
6112 	{ &isl_multi_union_pw_aff_apply_multi_aff,
6113 	  "C[{ A[i,j] -> [i]; B[i,j] -> [j] }]",
6114 	  "[N] -> { C[a] -> D[a + N] }",
6115 	  "[N] -> D[{ A[i,j] -> [i + N]; B[i,j] -> [j + N] }] " },
6116 	{ &isl_multi_union_pw_aff_apply_multi_aff,
6117 	  "C[]",
6118 	  "{ C[] -> D[] }",
6119 	  "D[]" },
6120 	{ &isl_multi_union_pw_aff_apply_multi_aff,
6121 	  "[N] -> (C[] : { : N >= 0 })",
6122 	  "{ C[] -> D[] }",
6123 	  "[N] -> (D[] : { : N >= 0 })" },
6124 	{ &isl_multi_union_pw_aff_apply_multi_aff,
6125 	  "C[]",
6126 	  "[N] -> { C[] -> D[N] }",
6127 	  "[N] -> D[{ [N] }]" },
6128 	{ &isl_multi_union_pw_aff_apply_multi_aff,
6129 	  "(C[] : { A[i,j] : i >= j })",
6130 	  "{ C[] -> D[] }",
6131 	  "(D[] : { A[i,j] : i >= j })" },
6132 	{ &isl_multi_union_pw_aff_apply_multi_aff,
6133 	  "[N] -> (C[] : { A[i,j] : N >= 0 })",
6134 	  "{ C[] -> D[] }",
6135 	  "[N] -> (D[] : { A[i,j] : N >= 0 })" },
6136 	{ &isl_multi_union_pw_aff_apply_multi_aff,
6137 	  "(C[] : { A[i,j] : i >= j })",
6138 	  "[N] -> { C[] -> D[N] }",
6139 	  "[N] -> (D[{ A[i,j] -> [N] : i >= j }])" },
6140 };
6141 
6142 /* Perform some basic tests of binary operations on
6143  * pairs of isl_multi_union_pw_aff and isl_multi_aff objects.
6144  */
test_mupa_ma(isl_ctx * ctx)6145 static int test_mupa_ma(isl_ctx *ctx)
6146 {
6147 	int i;
6148 	isl_bool ok;
6149 	isl_multi_union_pw_aff *mupa, *res;
6150 	isl_multi_aff *ma;
6151 
6152 	for (i = 0; i < ARRAY_SIZE(mupa_ma_tests); ++i) {
6153 		mupa = isl_multi_union_pw_aff_read_from_str(ctx,
6154 						    mupa_ma_tests[i].arg1);
6155 		ma = isl_multi_aff_read_from_str(ctx, mupa_ma_tests[i].arg2);
6156 		res = isl_multi_union_pw_aff_read_from_str(ctx,
6157 						    mupa_ma_tests[i].res);
6158 		mupa = mupa_ma_tests[i].fn(mupa, ma);
6159 		ok = isl_multi_union_pw_aff_plain_is_equal(mupa, res);
6160 		isl_multi_union_pw_aff_free(mupa);
6161 		isl_multi_union_pw_aff_free(res);
6162 		if (ok < 0)
6163 			return -1;
6164 		if (!ok)
6165 			isl_die(ctx, isl_error_unknown,
6166 				"unexpected result", return -1);
6167 	}
6168 
6169 	return 0;
6170 }
6171 
6172 /* Inputs for basic tests of binary operations on
6173  * pairs of isl_multi_union_pw_aff and isl_pw_aff objects.
6174  * "fn" is the function that is tested.
6175  * "arg1" and "arg2" are string descriptions of the inputs.
6176  * "res" is a string description of the expected result.
6177  */
6178 struct {
6179 	__isl_give isl_union_pw_aff *(*fn)(
6180 		__isl_take isl_multi_union_pw_aff *mupa,
6181 		__isl_take isl_pw_aff *pa);
6182 	const char *arg1;
6183 	const char *arg2;
6184 	const char *res;
6185 } mupa_pa_tests[] = {
6186 	{ &isl_multi_union_pw_aff_apply_pw_aff,
6187 	  "C[{ A[i,j] -> [i]; B[i,j] -> [j] }]",
6188 	  "[N] -> { C[a] -> [a + N] }",
6189 	  "[N] -> { A[i,j] -> [i + N]; B[i,j] -> [j + N] }" },
6190 	{ &isl_multi_union_pw_aff_apply_pw_aff,
6191 	  "C[{ A[i,j] -> [i]; B[i,j] -> [j] }]",
6192 	  "{ C[a] -> [a] : a >= 0; C[a] -> [-a] : a < 0 }",
6193 	  "{ A[i,j] -> [i] : i >= 0; A[i,j] -> [-i] : i < 0; "
6194 	    "B[i,j] -> [j] : j >= 0; B[i,j] -> [-j] : j < 0 }" },
6195 	{ &isl_multi_union_pw_aff_apply_pw_aff,
6196 	  "C[]",
6197 	  "[N] -> { C[] -> [N] }",
6198 	  "[N] -> { [N] }" },
6199 	{ &isl_multi_union_pw_aff_apply_pw_aff,
6200 	  "C[]",
6201 	  "[N] -> { C[] -> [N] : N >= 0; C[] -> [-N] : N < 0 }",
6202 	  "[N] -> { [N] : N >= 0; [-N] : N < 0 }" },
6203 	{ &isl_multi_union_pw_aff_apply_pw_aff,
6204 	  "[N] -> (C[] : { : N >= 0 })",
6205 	  "[N] -> { C[] -> [N] }",
6206 	  "[N] -> { [N] : N >= 0 }" },
6207 	{ &isl_multi_union_pw_aff_apply_pw_aff,
6208 	  "[N] -> (C[] : { : N >= 0 })",
6209 	  "[N] -> { C[] -> [N] : N >= 0; C[] -> [-N] : N < 0 }",
6210 	  "[N] -> { [N] : N >= 0 }" },
6211 	{ &isl_multi_union_pw_aff_apply_pw_aff,
6212 	  "[N] -> (C[] : { : N >= 0 })",
6213 	  "{ C[] -> [0] }",
6214 	  "[N] -> { [0] : N >= 0 }" },
6215 	{ &isl_multi_union_pw_aff_apply_pw_aff,
6216 	  "(C[] : { A[i,j] : i >= j })",
6217 	  "[N] -> { C[] -> [N] }",
6218 	  "[N] -> { A[i,j] -> [N] : i >= j }" },
6219 	{ &isl_multi_union_pw_aff_apply_pw_aff,
6220 	  "(C[] : { A[i,j] : i >= j })",
6221 	  "[N] -> { C[] -> [N] : N >= 0 }",
6222 	  "[N] -> { A[i,j] -> [N] : i >= j and N >= 0 }" },
6223 };
6224 
6225 /* Perform some basic tests of binary operations on
6226  * pairs of isl_multi_union_pw_aff and isl_pw_aff objects.
6227  */
test_mupa_pa(isl_ctx * ctx)6228 static int test_mupa_pa(isl_ctx *ctx)
6229 {
6230 	int i;
6231 	isl_bool ok;
6232 	isl_multi_union_pw_aff *mupa;
6233 	isl_union_pw_aff *upa, *res;
6234 	isl_pw_aff *pa;
6235 
6236 	for (i = 0; i < ARRAY_SIZE(mupa_pa_tests); ++i) {
6237 		mupa = isl_multi_union_pw_aff_read_from_str(ctx,
6238 						    mupa_pa_tests[i].arg1);
6239 		pa = isl_pw_aff_read_from_str(ctx, mupa_pa_tests[i].arg2);
6240 		res = isl_union_pw_aff_read_from_str(ctx,
6241 						    mupa_pa_tests[i].res);
6242 		upa = mupa_pa_tests[i].fn(mupa, pa);
6243 		ok = isl_union_pw_aff_plain_is_equal(upa, res);
6244 		isl_union_pw_aff_free(upa);
6245 		isl_union_pw_aff_free(res);
6246 		if (ok < 0)
6247 			return -1;
6248 		if (!ok)
6249 			isl_die(ctx, isl_error_unknown,
6250 				"unexpected result", return -1);
6251 	}
6252 
6253 	return 0;
6254 }
6255 
6256 /* Inputs for basic tests of binary operations on
6257  * pairs of isl_multi_union_pw_aff and isl_pw_multi_aff objects.
6258  * "fn" is the function that is tested.
6259  * "arg1" and "arg2" are string descriptions of the inputs.
6260  * "res" is a string description of the expected result.
6261  */
6262 struct {
6263 	__isl_give isl_multi_union_pw_aff *(*fn)(
6264 		__isl_take isl_multi_union_pw_aff *mupa,
6265 		__isl_take isl_pw_multi_aff *pma);
6266 	const char *arg1;
6267 	const char *arg2;
6268 	const char *res;
6269 } mupa_pma_tests[] = {
6270 	{ &isl_multi_union_pw_aff_apply_pw_multi_aff,
6271 	  "C[{ A[i,j] -> [i]; B[i,j] -> [j] }, "
6272 	    "{ A[i,j] -> [j]; B[i,j] -> [i] }]",
6273 	  "{ C[a,b] -> D[b,a] }",
6274 	  "D[{ A[i,j] -> [j]; B[i,j] -> [i] }, "
6275 	    "{ A[i,j] -> [i]; B[i,j] -> [j] }]" },
6276 	{ &isl_multi_union_pw_aff_apply_pw_multi_aff,
6277 	  "C[{ A[i,j] -> [i] : i >= 0; B[i,j] -> [j] }, "
6278 	    "{ A[i,j] -> [j]; B[i,j] -> [i] }]",
6279 	  "{ C[a,b] -> D[b,a] }",
6280 	  "D[{ A[i,j] -> [j] : i >= 0; B[i,j] -> [i] }, "
6281 	    "{ A[i,j] -> [i] : i >= 0; B[i,j] -> [j] }]" },
6282 	{ &isl_multi_union_pw_aff_apply_pw_multi_aff,
6283 	  "C[{ A[i,j] -> [i]; B[i,j] -> [j] }]",
6284 	  "[N] -> { C[a] -> D[a + N] }",
6285 	  "[N] -> D[{ A[i,j] -> [i + N]; B[i,j] -> [j + N] }]" },
6286 	{ &isl_multi_union_pw_aff_apply_pw_multi_aff,
6287 	  "C[{ A[i,j] -> [i]; B[i,j] -> [j] }]",
6288 	  "{ C[a] -> D[a] : a >= 0; C[a] -> D[-a] : a < 0 }",
6289 	  "D[{ A[i,j] -> [i] : i >= 0; A[i,j] -> [-i] : i < 0; "
6290 	      "B[i,j] -> [j] : j >= 0; B[i,j] -> [-j] : j < 0 }]" },
6291 	{ &isl_multi_union_pw_aff_apply_pw_multi_aff,
6292 	  "C[{ A[i,j] -> [i]; B[i,j] -> [j] }, "
6293 	    "{ A[i,j] -> [j]; B[i,j] -> [i] }]",
6294 	  "{ C[a,b] -> D[a,b] : a >= b; C[a,b] -> D[b,a] : a < b }",
6295 	  "D[{ A[i,j] -> [i] : i >= j; A[i,j] -> [j] : i < j; "
6296 	      "B[i,j] -> [j] : i <= j; B[i,j] -> [i] : i > j }, "
6297 	    "{ A[i,j] -> [j] : i >= j; A[i,j] -> [i] : i < j; "
6298 	      "B[i,j] -> [i] : i <= j; B[i,j] -> [j] : i > j }]" },
6299 	{ &isl_multi_union_pw_aff_apply_pw_multi_aff,
6300 	  "C[]",
6301 	  "{ C[] -> D[] }",
6302 	  "D[]" },
6303 	{ &isl_multi_union_pw_aff_apply_pw_multi_aff,
6304 	  "[N] -> (C[] : { : N >= 0 })",
6305 	  "{ C[] -> D[] }",
6306 	  "[N] -> (D[] : { : N >= 0 })" },
6307 	{ &isl_multi_union_pw_aff_apply_pw_multi_aff,
6308 	  "C[]",
6309 	  "[N] -> { C[] -> D[N] }",
6310 	  "[N] -> D[{ [N] }]" },
6311 	{ &isl_multi_union_pw_aff_apply_pw_multi_aff,
6312 	  "(C[] : { A[i,j] : i >= j })",
6313 	  "{ C[] -> D[] }",
6314 	  "(D[] : { A[i,j] : i >= j })" },
6315 	{ &isl_multi_union_pw_aff_apply_pw_multi_aff,
6316 	  "[N] -> (C[] : { A[i,j] : N >= 0 })",
6317 	  "{ C[] -> D[] }",
6318 	  "[N] -> (D[] : { A[i,j] : N >= 0 })" },
6319 	{ &isl_multi_union_pw_aff_apply_pw_multi_aff,
6320 	  "(C[] : { A[i,j] : i >= j })",
6321 	  "[N] -> { C[] -> D[N] }",
6322 	  "[N] -> (D[{ A[i,j] -> [N] : i >= j }])" },
6323 	{ &isl_multi_union_pw_aff_apply_pw_multi_aff,
6324 	  "C[]",
6325 	  "[N] -> { C[] -> D[N] : N >= 0; C[] -> D[-N] : N < 0 }",
6326 	  "[N] -> D[{ [N] : N >= 0; [-N] : N < 0 }]" },
6327 	{ &isl_multi_union_pw_aff_apply_pw_multi_aff,
6328 	  "[N] -> (C[] : { : N >= 0 })",
6329 	  "[N] -> { C[] -> D[N] }",
6330 	  "[N] -> D[{ [N] : N >= 0 }]" },
6331 	{ &isl_multi_union_pw_aff_apply_pw_multi_aff,
6332 	  "[N] -> (C[] : { : N >= 0 })",
6333 	  "[N] -> { C[] -> D[N] : N >= 0; C[] -> D[-N] : N < 0 }",
6334 	  "[N] -> D[{ [N] : N >= 0 }]" },
6335 	{ &isl_multi_union_pw_aff_apply_pw_multi_aff,
6336 	  "[N] -> (C[] : { : N >= 0 })",
6337 	  "{ C[] -> D[0] }",
6338 	  "[N] -> D[{ [0] : N >= 0 }]" },
6339 	{ &isl_multi_union_pw_aff_apply_pw_multi_aff,
6340 	  "(C[] : { A[i,j] : i >= j })",
6341 	  "[N] -> { C[] -> D[N] : N >= 0 }",
6342 	  "[N] -> D[{ A[i,j] -> [N] : i >= j and N >= 0 }]" },
6343 };
6344 
6345 /* Perform some basic tests of binary operations on
6346  * pairs of isl_multi_union_pw_aff and isl_pw_multi_aff objects.
6347  */
test_mupa_pma(isl_ctx * ctx)6348 static int test_mupa_pma(isl_ctx *ctx)
6349 {
6350 	int i;
6351 	isl_bool ok;
6352 	isl_multi_union_pw_aff *mupa, *res;
6353 	isl_pw_multi_aff *pma;
6354 
6355 	for (i = 0; i < ARRAY_SIZE(mupa_pma_tests); ++i) {
6356 		mupa = isl_multi_union_pw_aff_read_from_str(ctx,
6357 						    mupa_pma_tests[i].arg1);
6358 		pma = isl_pw_multi_aff_read_from_str(ctx,
6359 						    mupa_pma_tests[i].arg2);
6360 		res = isl_multi_union_pw_aff_read_from_str(ctx,
6361 						    mupa_pma_tests[i].res);
6362 		mupa = mupa_pma_tests[i].fn(mupa, pma);
6363 		ok = isl_multi_union_pw_aff_plain_is_equal(mupa, res);
6364 		isl_multi_union_pw_aff_free(mupa);
6365 		isl_multi_union_pw_aff_free(res);
6366 		if (ok < 0)
6367 			return -1;
6368 		if (!ok)
6369 			isl_die(ctx, isl_error_unknown,
6370 				"unexpected result", return -1);
6371 	}
6372 
6373 	return 0;
6374 }
6375 
6376 /* Inputs for basic tests of binary operations on
6377  * pairs of isl_multi_union_pw_aff and isl_union_pw_multi_aff objects.
6378  * "fn" is the function that is tested.
6379  * "arg1" and "arg2" are string descriptions of the inputs.
6380  * "res" is a string description of the expected result.
6381  */
6382 struct {
6383 	__isl_give isl_multi_union_pw_aff *(*fn)(
6384 		__isl_take isl_multi_union_pw_aff *mupa,
6385 		__isl_take isl_union_pw_multi_aff *upma);
6386 	const char *arg1;
6387 	const char *arg2;
6388 	const char *res;
6389 } mupa_upma_tests[] = {
6390 	{ &isl_multi_union_pw_aff_pullback_union_pw_multi_aff,
6391 	  "C[{ B[i,j] -> [i + 2j] }]", "{ A[a,b] -> B[b,a] }",
6392 	  "C[{ A[a,b] -> [b + 2a] }]" },
6393 	{ &isl_multi_union_pw_aff_pullback_union_pw_multi_aff,
6394 	  "C[{ B[i,j] -> [i + 2j] }]",
6395 	  "{ A[a,b] -> B[b,a] : b > a }",
6396 	  "C[{ A[a,b] -> [b + 2a] : b > a }]" },
6397 	{ &isl_multi_union_pw_aff_pullback_union_pw_multi_aff,
6398 	  "C[{ B[i,j] -> [i + 2j] : j > 4 }]",
6399 	  "{ A[a,b] -> B[b,a] : b > a }",
6400 	  "C[{ A[a,b] -> [b + 2a] : b > a > 4 }]" },
6401 	{ &isl_multi_union_pw_aff_pullback_union_pw_multi_aff,
6402 	  "C[{ B[i,j] -> [i + 2j] }]",
6403 	  "{ A[a,b] -> B[b,a] : a > b; A[a,b] -> B[a,b] : a <= b }",
6404 	  "C[{ A[a,b] -> [b + 2a] : a > b; A[a,b] -> [a + 2b] : a <= b }]" },
6405 	{ &isl_multi_union_pw_aff_pullback_union_pw_multi_aff,
6406 	  "(C[] : { B[a,b] })",
6407 	  "{ A[a,b] -> B[b,a] }",
6408 	  "(C[] : { A[a,b] })" },
6409 	{ &isl_multi_union_pw_aff_pullback_union_pw_multi_aff,
6410 	  "(C[] : { B[a,b] })",
6411 	  "{ B[a,b] -> A[b,a] }",
6412 	  "(C[] : { })" },
6413 	{ &isl_multi_union_pw_aff_pullback_union_pw_multi_aff,
6414 	  "(C[] : { B[a,b] })",
6415 	  "{ A[a,b] -> B[b,a] : a > b }",
6416 	  "(C[] : { A[a,b] : a > b })" },
6417 	{ &isl_multi_union_pw_aff_pullback_union_pw_multi_aff,
6418 	  "(C[] : { B[a,b] : a > b })",
6419 	  "{ A[a,b] -> B[b,a] }",
6420 	  "(C[] : { A[a,b] : b > a })" },
6421 	{ &isl_multi_union_pw_aff_pullback_union_pw_multi_aff,
6422 	  "[N] -> (C[] : { B[a,b] : a > N })",
6423 	  "{ A[a,b] -> B[b,a] : a > b }",
6424 	  "[N] -> (C[] : { A[a,b] : a > b > N })" },
6425 	{ &isl_multi_union_pw_aff_pullback_union_pw_multi_aff,
6426 	  "(C[] : { B[a,b] : a > b })",
6427 	  "[N] -> { A[a,b] -> B[b,a] : a > N }",
6428 	  "[N] -> (C[] : { A[a,b] : b > a > N })" },
6429 	{ &isl_multi_union_pw_aff_pullback_union_pw_multi_aff,
6430 	  "C[]",
6431 	  "{ A[a,b] -> B[b,a] }",
6432 	  "C[]" },
6433 	{ &isl_multi_union_pw_aff_pullback_union_pw_multi_aff,
6434 	  "[N] -> (C[] : { : N >= 0 })",
6435 	  "{ A[a,b] -> B[b,a] }",
6436 	  "[N] -> (C[] : { : N >= 0 })" },
6437 	{ &isl_multi_union_pw_aff_pullback_union_pw_multi_aff,
6438 	  "C[]",
6439 	  "[N] -> { A[a,b] -> B[b,a] : N >= 0 }",
6440 	  "[N] -> (C[] : { : N >= 0 })" },
6441 };
6442 
6443 /* Perform some basic tests of binary operations on
6444  * pairs of isl_multi_union_pw_aff and isl_union_pw_multi_aff objects.
6445  */
test_mupa_upma(isl_ctx * ctx)6446 static int test_mupa_upma(isl_ctx *ctx)
6447 {
6448 	int i;
6449 	isl_bool ok;
6450 	isl_multi_union_pw_aff *mupa, *res;
6451 	isl_union_pw_multi_aff *upma;
6452 
6453 	for (i = 0; i < ARRAY_SIZE(mupa_upma_tests); ++i) {
6454 		mupa = isl_multi_union_pw_aff_read_from_str(ctx,
6455 						    mupa_upma_tests[i].arg1);
6456 		upma = isl_union_pw_multi_aff_read_from_str(ctx,
6457 						    mupa_upma_tests[i].arg2);
6458 		res = isl_multi_union_pw_aff_read_from_str(ctx,
6459 						    mupa_upma_tests[i].res);
6460 		mupa = mupa_upma_tests[i].fn(mupa, upma);
6461 		ok = isl_multi_union_pw_aff_plain_is_equal(mupa, res);
6462 		isl_multi_union_pw_aff_free(mupa);
6463 		isl_multi_union_pw_aff_free(res);
6464 		if (ok < 0)
6465 			return -1;
6466 		if (!ok)
6467 			isl_die(ctx, isl_error_unknown,
6468 				"unexpected result", return -1);
6469 	}
6470 
6471 	return 0;
6472 }
6473 
6474 /* Check that the input tuple of an isl_aff can be set properly.
6475  */
test_aff_set_tuple_id(isl_ctx * ctx)6476 static isl_stat test_aff_set_tuple_id(isl_ctx *ctx)
6477 {
6478 	isl_id *id;
6479 	isl_aff *aff;
6480 	isl_stat equal;
6481 
6482 	aff = isl_aff_read_from_str(ctx, "{ [x] -> [x + 1] }");
6483 	id = isl_id_alloc(ctx, "A", NULL);
6484 	aff = isl_aff_set_tuple_id(aff, isl_dim_in, id);
6485 	equal = aff_check_plain_equal(aff, "{ A[x] -> [x + 1] }");
6486 	isl_aff_free(aff);
6487 	if (equal < 0)
6488 		return isl_stat_error;
6489 
6490 	return isl_stat_ok;
6491 }
6492 
6493 /* Check that affine expressions get normalized on addition/subtraction.
6494  * In particular, check that (final) unused integer divisions get removed
6495  * such that an expression derived from expressions with integer divisions
6496  * is found to be obviously equal to one that is created directly.
6497  */
test_aff_normalize(isl_ctx * ctx)6498 static isl_stat test_aff_normalize(isl_ctx *ctx)
6499 {
6500 	isl_aff *aff, *aff2;
6501 	isl_stat ok;
6502 
6503 	aff = isl_aff_read_from_str(ctx, "{ [x] -> [x//2] }");
6504 	aff2 = isl_aff_read_from_str(ctx, "{ [x] -> [1 + x//2] }");
6505 	aff = isl_aff_sub(aff2, aff);
6506 	ok = aff_check_plain_equal(aff, "{ [x] -> [1] }");
6507 	isl_aff_free(aff);
6508 
6509 	return ok;
6510 }
6511 
test_aff(isl_ctx * ctx)6512 int test_aff(isl_ctx *ctx)
6513 {
6514 	const char *str;
6515 	isl_set *set;
6516 	isl_space *space;
6517 	isl_local_space *ls;
6518 	isl_aff *aff;
6519 	int zero;
6520 	isl_stat equal;
6521 
6522 	if (test_upa(ctx) < 0)
6523 		return -1;
6524 	if (test_bin_aff(ctx) < 0)
6525 		return -1;
6526 	if (test_bin_pw_aff(ctx) < 0)
6527 		return -1;
6528 	if (test_bin_upma(ctx) < 0)
6529 		return -1;
6530 	if (test_bin_upma_fail(ctx) < 0)
6531 		return -1;
6532 	if (test_upma_uset(ctx) < 0)
6533 		return -1;
6534 	if (test_un_mpa(ctx) < 0)
6535 		return -1;
6536 	if (test_bin_mpa(ctx) < 0)
6537 		return -1;
6538 	if (test_un_mupa(ctx) < 0)
6539 		return -1;
6540 	if (test_bin_mupa(ctx) < 0)
6541 		return -1;
6542 	if (test_mupa_set(ctx) < 0)
6543 		return -1;
6544 	if (test_mupa_uset(ctx) < 0)
6545 		return -1;
6546 	if (test_mupa_ma(ctx) < 0)
6547 		return -1;
6548 	if (test_mupa_pa(ctx) < 0)
6549 		return -1;
6550 	if (test_mupa_pma(ctx) < 0)
6551 		return -1;
6552 	if (test_mupa_upma(ctx) < 0)
6553 		return -1;
6554 
6555 	space = isl_space_set_alloc(ctx, 0, 1);
6556 	ls = isl_local_space_from_space(space);
6557 	aff = isl_aff_zero_on_domain(ls);
6558 
6559 	aff = isl_aff_add_coefficient_si(aff, isl_dim_in, 0, 1);
6560 	aff = isl_aff_scale_down_ui(aff, 3);
6561 	aff = isl_aff_floor(aff);
6562 	aff = isl_aff_add_coefficient_si(aff, isl_dim_in, 0, 1);
6563 	aff = isl_aff_scale_down_ui(aff, 2);
6564 	aff = isl_aff_floor(aff);
6565 	aff = isl_aff_add_coefficient_si(aff, isl_dim_in, 0, 1);
6566 
6567 	str = "{ [10] }";
6568 	set = isl_set_read_from_str(ctx, str);
6569 	aff = isl_aff_gist(aff, set);
6570 
6571 	aff = isl_aff_add_constant_si(aff, -16);
6572 	zero = isl_aff_plain_is_zero(aff);
6573 	isl_aff_free(aff);
6574 
6575 	if (zero < 0)
6576 		return -1;
6577 	if (!zero)
6578 		isl_die(ctx, isl_error_unknown, "unexpected result", return -1);
6579 
6580 	aff = isl_aff_read_from_str(ctx, "{ [-1] }");
6581 	aff = isl_aff_scale_down_ui(aff, 64);
6582 	aff = isl_aff_floor(aff);
6583 	equal = aff_check_plain_equal(aff, "{ [-1] }");
6584 	isl_aff_free(aff);
6585 	if (equal < 0)
6586 		return -1;
6587 
6588 	if (test_aff_set_tuple_id(ctx) < 0)
6589 		return -1;
6590 	if (test_aff_normalize(ctx) < 0)
6591 		return -1;
6592 
6593 	return 0;
6594 }
6595 
6596 /* Inputs for isl_set_bind tests.
6597  * "set" is the input set.
6598  * "tuple" is the binding tuple.
6599  * "res" is the expected result.
6600  */
6601 static
6602 struct {
6603 	const char *set;
6604 	const char *tuple;
6605 	const char *res;
6606 } bind_set_tests[] = {
6607 	{ "{ A[M, N] : M mod 2 = 0 and N mod 8 = 3 }",
6608 	  "{ A[M, N] }",
6609 	  "[M, N] -> { : M mod 2 = 0 and N mod 8 = 3 }" },
6610 	{ "{ B[N, M] : M mod 2 = 0 and N mod 8 = 3 }",
6611 	  "{ B[N, M] }",
6612 	  "[M, N] -> { : M mod 2 = 0 and N mod 8 = 3 }" },
6613 	{ "[M] -> { C[N] : M mod 2 = 0 and N mod 8 = 3 }",
6614 	  "{ C[N] }",
6615 	  "[M, N] -> { : M mod 2 = 0 and N mod 8 = 3 }" },
6616 	{ "[M] -> { D[x, N] : x mod 2 = 0 and N mod 8 = 3 and M >= 0 }",
6617 	  "{ D[M, N] }",
6618 	  "[M, N] -> { : M mod 2 = 0 and N mod 8 = 3 and M >= 0 }" },
6619 };
6620 
6621 /* Perform basic isl_set_bind tests.
6622  */
test_bind_set(isl_ctx * ctx)6623 static isl_stat test_bind_set(isl_ctx *ctx)
6624 {
6625 	int i;
6626 
6627 	for (i = 0; i < ARRAY_SIZE(bind_set_tests); ++i) {
6628 		const char *str;
6629 		isl_set *set;
6630 		isl_multi_id *tuple;
6631 		isl_stat r;
6632 
6633 		set = isl_set_read_from_str(ctx, bind_set_tests[i].set);
6634 		str = bind_set_tests[i].tuple;
6635 		tuple = isl_multi_id_read_from_str(ctx, str);
6636 		set = isl_set_bind(set, tuple);
6637 		r = set_check_equal(set, bind_set_tests[i].res);
6638 		isl_set_free(set);
6639 		if (r < 0)
6640 			return isl_stat_error;
6641 	}
6642 
6643 	return isl_stat_ok;
6644 }
6645 
6646 /* Inputs for isl_map_bind_domain tests.
6647  * "map" is the input map.
6648  * "tuple" is the binding tuple.
6649  * "res" is the expected result.
6650  */
6651 struct {
6652 	const char *map;
6653 	const char *tuple;
6654 	const char *res;
6655 } bind_map_domain_tests[] = {
6656 	{ "{ A[M, N] -> [M + floor(N/2)] }",
6657 	  "{ A[M, N] }",
6658 	  "[M, N] -> { [M + floor(N/2)] }" },
6659 	{ "{ B[N, M] -> [M + floor(N/2)] }",
6660 	  "{ B[N, M] }",
6661 	  "[N, M] -> { [M + floor(N/2)] }" },
6662 	{ "[M] -> { C[N] -> [M + floor(N/2)] }",
6663 	  "{ C[N] }",
6664 	  "[M, N] -> { [M + floor(N/2)] }" },
6665 	{ "[M] -> { C[x, N] -> [x + floor(N/2)] }",
6666 	  "{ C[M, N] }",
6667 	  "[M, N] -> { [M + floor(N/2)] }" },
6668 	{ "[M] -> { C[x, N] -> [M + floor(N/2)] }",
6669 	  "{ C[M, N] }",
6670 	  "[M, N] -> { [M + floor(N/2)] }" },
6671 	{ "[A, M] -> { C[N, x] -> [x + floor(N/2)] }",
6672 	  "{ C[N, M] }",
6673 	  "[A, N, M] -> { [M + floor(N/2)] }" },
6674 };
6675 
6676 /* Perform basic isl_map_bind_domain tests.
6677  */
test_bind_map_domain(isl_ctx * ctx)6678 static isl_stat test_bind_map_domain(isl_ctx *ctx)
6679 {
6680 	int i;
6681 
6682 	for (i = 0; i < ARRAY_SIZE(bind_map_domain_tests); ++i) {
6683 		const char *str;
6684 		isl_map *map;
6685 		isl_set *set;
6686 		isl_multi_id *tuple;
6687 		isl_stat r;
6688 
6689 		str = bind_map_domain_tests[i].map;
6690 		map = isl_map_read_from_str(ctx, str);
6691 		str = bind_map_domain_tests[i].tuple;
6692 		tuple = isl_multi_id_read_from_str(ctx, str);
6693 		set = isl_map_bind_domain(map, tuple);
6694 		str = bind_map_domain_tests[i].res;
6695 		r = set_check_equal(set, str);
6696 		isl_set_free(set);
6697 		if (r < 0)
6698 			return isl_stat_error;
6699 	}
6700 
6701 	return isl_stat_ok;
6702 }
6703 
6704 /* Inputs for isl_union_map_bind_range tests.
6705  * "map" is the input union map.
6706  * "tuple" is the binding tuple.
6707  * "res" is the expected result.
6708  */
6709 struct {
6710 	const char *map;
6711 	const char *tuple;
6712 	const char *res;
6713 } bind_umap_range_tests[] = {
6714 	{ "{ B[N, M] -> A[M, N] : M mod 2 = 0 and N mod 8 = 3 }",
6715 	  "{ A[M, N] }",
6716 	  "[M, N] -> { B[N, M] : M mod 2 = 0 and N mod 8 = 3 }" },
6717 	{ "{ B[N, M] -> A[M, N] : M mod 2 = 0 and N mod 8 = 3 }",
6718 	  "{ B[M, N] }",
6719 	  "{ }" },
6720 	{ "{ A[] -> B[]; C[] -> D[]; E[] -> B[] }",
6721 	  "{ B[] }",
6722 	  "{ A[]; E[] }" },
6723 };
6724 
6725 /* Perform basic isl_union_map_bind_range tests.
6726  */
test_bind_umap_range(isl_ctx * ctx)6727 static isl_stat test_bind_umap_range(isl_ctx *ctx)
6728 {
6729 	int i;
6730 
6731 	for (i = 0; i < ARRAY_SIZE(bind_umap_range_tests); ++i) {
6732 		const char *str;
6733 		isl_union_map *umap;
6734 		isl_union_set *uset;
6735 		isl_multi_id *tuple;
6736 		isl_stat r;
6737 
6738 		str = bind_umap_range_tests[i].map;
6739 		umap = isl_union_map_read_from_str(ctx, str);
6740 		str = bind_umap_range_tests[i].tuple;
6741 		tuple = isl_multi_id_read_from_str(ctx, str);
6742 		uset = isl_union_map_bind_range(umap, tuple);
6743 		str = bind_umap_range_tests[i].res;
6744 		r = uset_check_equal(uset, str);
6745 		isl_union_set_free(uset);
6746 		if (r < 0)
6747 			return isl_stat_error;
6748 	}
6749 
6750 	return isl_stat_ok;
6751 }
6752 
6753 /* Inputs for isl_pw_multi_aff_bind_domain tests.
6754  * "pma" is the input expression.
6755  * "tuple" is the binding tuple.
6756  * "res" is the expected result.
6757  */
6758 struct {
6759 	const char *pma;
6760 	const char *tuple;
6761 	const char *res;
6762 } bind_pma_domain_tests[] = {
6763 	{ "{ A[M, N] -> [M + floor(N/2)] }",
6764 	  "{ A[M, N] }",
6765 	  "[M, N] -> { [M + floor(N/2)] }" },
6766 	{ "{ B[N, M] -> [M + floor(N/2)] }",
6767 	  "{ B[N, M] }",
6768 	  "[N, M] -> { [M + floor(N/2)] }" },
6769 	{ "[M] -> { C[N] -> [M + floor(N/2)] }",
6770 	  "{ C[N] }",
6771 	  "[M, N] -> { [M + floor(N/2)] }" },
6772 	{ "[M] -> { C[x, N] -> [x + floor(N/2)] }",
6773 	  "{ C[M, N] }",
6774 	  "[M, N] -> { [M + floor(N/2)] }" },
6775 	{ "[M] -> { C[x, N] -> [M + floor(N/2)] }",
6776 	  "{ C[M, N] }",
6777 	  "[M, N] -> { [M + floor(N/2)] }" },
6778 	{ "[A, M] -> { C[N, x] -> [x + floor(N/2)] }",
6779 	  "{ C[N, M] }",
6780 	  "[A, N, M] -> { [M + floor(N/2)] }" },
6781 };
6782 
6783 /* Perform basic isl_pw_multi_aff_bind_domain tests.
6784  */
test_bind_pma_domain(isl_ctx * ctx)6785 static isl_stat test_bind_pma_domain(isl_ctx *ctx)
6786 {
6787 	int i;
6788 
6789 	for (i = 0; i < ARRAY_SIZE(bind_pma_domain_tests); ++i) {
6790 		const char *str;
6791 		isl_pw_multi_aff *pma;
6792 		isl_multi_id *tuple;
6793 		isl_stat r;
6794 
6795 		str = bind_pma_domain_tests[i].pma;
6796 		pma = isl_pw_multi_aff_read_from_str(ctx, str);
6797 		str = bind_pma_domain_tests[i].tuple;
6798 		tuple = isl_multi_id_read_from_str(ctx, str);
6799 		pma = isl_pw_multi_aff_bind_domain(pma, tuple);
6800 		str = bind_pma_domain_tests[i].res;
6801 		r = pw_multi_aff_check_plain_equal(pma, str);
6802 		isl_pw_multi_aff_free(pma);
6803 		if (r < 0)
6804 			return isl_stat_error;
6805 	}
6806 
6807 	return isl_stat_ok;
6808 }
6809 
6810 /* Inputs for isl_pw_multi_aff_bind_domain_wrapped_domain tests.
6811  * "pma" is the input expression.
6812  * "tuple" is the binding tuple.
6813  * "res" is the expected result.
6814  */
6815 struct {
6816 	const char *pma;
6817 	const char *tuple;
6818 	const char *res;
6819 } bind_pma_domain_wrapped_tests[] = {
6820 	{ "{ [A[M, N] -> B[]] -> [M + floor(N/2)] }",
6821 	  "{ A[M, N] }",
6822 	  "[M, N] -> { B[] -> [M + floor(N/2)] }" },
6823 	{ "{ [B[N, M] -> D[]] -> [M + floor(N/2)] }",
6824 	  "{ B[N, M] }",
6825 	  "[N, M] -> { D[] -> [M + floor(N/2)] }" },
6826 	{ "[M] -> { [C[N] -> B[x]] -> [x + M + floor(N/2)] }",
6827 	  "{ C[N] }",
6828 	  "[M, N] -> { B[x] -> [x + M + floor(N/2)] }" },
6829 	{ "[M] -> { [C[x, N] -> B[]] -> [x + floor(N/2)] }",
6830 	  "{ C[M, N] }",
6831 	  "[M, N] -> { B[] -> [M + floor(N/2)] }" },
6832 	{ "[M] -> { [C[x, N] -> B[]] -> [M + floor(N/2)] }",
6833 	  "{ C[M, N] }",
6834 	  "[M, N] -> { B[] -> [M + floor(N/2)] }" },
6835 	{ "[A, M] -> { [C[N, x] -> B[]] -> [x + floor(N/2)] }",
6836 	  "{ C[N, M] }",
6837 	  "[A, N, M] -> { B[] -> [M + floor(N/2)] }" },
6838 };
6839 
6840 /* Perform basic isl_pw_multi_aff_bind_domain_wrapped_domain tests.
6841  */
test_bind_pma_domain_wrapped(isl_ctx * ctx)6842 static isl_stat test_bind_pma_domain_wrapped(isl_ctx *ctx)
6843 {
6844 	int i;
6845 
6846 	for (i = 0; i < ARRAY_SIZE(bind_pma_domain_wrapped_tests); ++i) {
6847 		const char *str;
6848 		isl_pw_multi_aff *pma;
6849 		isl_multi_id *tuple;
6850 		isl_stat r;
6851 
6852 		str = bind_pma_domain_wrapped_tests[i].pma;
6853 		pma = isl_pw_multi_aff_read_from_str(ctx, str);
6854 		str = bind_pma_domain_wrapped_tests[i].tuple;
6855 		tuple = isl_multi_id_read_from_str(ctx, str);
6856 		pma = isl_pw_multi_aff_bind_domain_wrapped_domain(pma, tuple);
6857 		str = bind_pma_domain_wrapped_tests[i].res;
6858 		r = pw_multi_aff_check_plain_equal(pma, str);
6859 		isl_pw_multi_aff_free(pma);
6860 		if (r < 0)
6861 			return isl_stat_error;
6862 	}
6863 
6864 	return isl_stat_ok;
6865 }
6866 
6867 /* Inputs for isl_aff_bind_id tests.
6868  * "aff" is the input expression.
6869  * "id" is the binding id.
6870  * "res" is the expected result.
6871  */
6872 static
6873 struct {
6874 	const char *aff;
6875 	const char *id;
6876 	const char *res;
6877 } bind_aff_tests[] = {
6878 	{ "{ [4] }", "M", "[M = 4] -> { : }" },
6879 	{ "{ B[x] -> [floor(x/2)] }", "M", "[M] -> { B[x] : M = floor(x/2) }" },
6880 	{ "[M] -> { [4] }", "M", "[M = 4] -> { : }" },
6881 	{ "[M] -> { [floor(M/2)] }", "M", "[M] -> { : floor(M/2) = M }" },
6882 	{ "{ [NaN] }", "M", "{ : false }" },
6883 	{ "{ A[x] -> [NaN] }", "M", "{ A[x] : false }" },
6884 };
6885 
6886 /* Perform basic isl_aff_bind_id tests.
6887  */
test_bind_aff(isl_ctx * ctx)6888 static isl_stat test_bind_aff(isl_ctx *ctx)
6889 {
6890 	int i;
6891 
6892 	for (i = 0; i < ARRAY_SIZE(bind_aff_tests); ++i) {
6893 		isl_aff *aff;
6894 		isl_set *res;
6895 		isl_id *id;
6896 		isl_stat r;
6897 
6898 		aff = isl_aff_read_from_str(ctx, bind_aff_tests[i].aff);
6899 		id = isl_id_read_from_str(ctx, bind_aff_tests[i].id);
6900 		res = isl_set_from_basic_set(isl_aff_bind_id(aff, id));
6901 		r = set_check_equal(res, bind_aff_tests[i].res);
6902 		isl_set_free(res);
6903 		if (r < 0)
6904 			return isl_stat_error;
6905 	}
6906 
6907 	return isl_stat_ok;
6908 }
6909 
6910 /* Inputs for isl_pw_aff_bind_id tests.
6911  * "pa" is the input expression.
6912  * "id" is the binding id.
6913  * "res" is the expected result.
6914  */
6915 static
6916 struct {
6917 	const char *pa;
6918 	const char *id;
6919 	const char *res;
6920 } bind_pa_tests[] = {
6921 	{ "{ [4] }", "M", "[M = 4] -> { : }" },
6922 	{ "{ B[x] -> [floor(x/2)] }", "M", "[M] -> { B[x] : M = floor(x/2) }" },
6923 	{ "[M] -> { [4] }", "M", "[M = 4] -> { : }" },
6924 	{ "[M] -> { [floor(M/2)] }", "M", "[M] -> { : floor(M/2) = M }" },
6925 	{ "[M] -> { [M] : M >= 0; [-M] : M < 0 }", "M", "[M] -> { : M >= 0 }" },
6926 	{ "{ [NaN] }", "M", "{ : false }" },
6927 	{ "{ A[x] -> [NaN] }", "M", "{ A[x] : false }" },
6928 };
6929 
6930 /* Perform basic isl_pw_aff_bind_id tests.
6931  */
test_bind_pa(isl_ctx * ctx)6932 static isl_stat test_bind_pa(isl_ctx *ctx)
6933 {
6934 	int i;
6935 
6936 	for (i = 0; i < ARRAY_SIZE(bind_pa_tests); ++i) {
6937 		isl_pw_aff *pa;
6938 		isl_set *res;
6939 		isl_id *id;
6940 		isl_stat r;
6941 
6942 		pa = isl_pw_aff_read_from_str(ctx, bind_pa_tests[i].pa);
6943 		id = isl_id_read_from_str(ctx, bind_pa_tests[i].id);
6944 		res = isl_pw_aff_bind_id(pa, id);
6945 		r = set_check_equal(res, bind_pa_tests[i].res);
6946 		isl_set_free(res);
6947 		if (r < 0)
6948 			return isl_stat_error;
6949 	}
6950 
6951 	return isl_stat_ok;
6952 }
6953 
6954 /* Inputs for isl_multi_union_pw_aff_bind tests.
6955  * "mupa" is the input expression.
6956  * "tuple" is the binding tuple.
6957  * "res" is the expected result.
6958  */
6959 static
6960 struct {
6961 	const char *mupa;
6962 	const char *tuple;
6963 	const char *res;
6964 } bind_mupa_tests[] = {
6965 	{ "A[{ [4] }, { [5] }]",
6966 	  "{ A[M, N] }",
6967 	  "[M = 4, N = 5] -> { : }" },
6968 	{ "A[{ B[x] -> [floor(x/2)] }, { B[y] -> [y + 5] }]",
6969 	  "{ A[M, N] }",
6970 	  "[M, N] -> { B[x] : M = floor(x/2) and N = x + 5 }" },
6971 	{ "[M] -> A[{ [4] }, { [M + 1] }]",
6972 	  "{ A[M, N] }",
6973 	  "[M = 4, N = 5] -> { : }" },
6974 };
6975 
6976 /* Perform basic isl_multi_union_pw_aff_bind tests.
6977  */
test_bind_mupa(isl_ctx * ctx)6978 static isl_stat test_bind_mupa(isl_ctx *ctx)
6979 {
6980 	int i;
6981 
6982 	for (i = 0; i < ARRAY_SIZE(bind_mupa_tests); ++i) {
6983 		const char *str;
6984 		isl_multi_union_pw_aff *mupa;
6985 		isl_union_set *res;
6986 		isl_multi_id *tuple;
6987 		isl_stat r;
6988 
6989 		str = bind_mupa_tests[i].mupa;
6990 		mupa = isl_multi_union_pw_aff_read_from_str(ctx, str);
6991 		str = bind_mupa_tests[i].tuple;
6992 		tuple = isl_multi_id_read_from_str(ctx, str);
6993 		res = isl_multi_union_pw_aff_bind(mupa, tuple);
6994 		r = uset_check_equal(res, bind_mupa_tests[i].res);
6995 		isl_union_set_free(res);
6996 		if (r < 0)
6997 			return isl_stat_error;
6998 	}
6999 
7000 	return isl_stat_ok;
7001 }
7002 
7003 /* Perform tests that reinterpret dimensions as parameters.
7004  */
test_bind(isl_ctx * ctx)7005 static int test_bind(isl_ctx *ctx)
7006 {
7007 	if (test_bind_set(ctx) < 0)
7008 		return -1;
7009 	if (test_bind_map_domain(ctx) < 0)
7010 		return -1;
7011 	if (test_bind_umap_range(ctx) < 0)
7012 		return -1;
7013 	if (test_bind_pma_domain(ctx) < 0)
7014 		return -1;
7015 	if (test_bind_pma_domain_wrapped(ctx) < 0)
7016 		return -1;
7017 	if (test_bind_aff(ctx) < 0)
7018 		return -1;
7019 	if (test_bind_pa(ctx) < 0)
7020 		return -1;
7021 	if (test_bind_mupa(ctx) < 0)
7022 		return -1;
7023 
7024 	return 0;
7025 }
7026 
7027 /* Inputs for isl_set_unbind_params tests.
7028  * "set" is the input parameter domain.
7029  * "tuple" is the tuple of the constructed set.
7030  * "res" is the expected result.
7031  */
7032 struct {
7033 	const char *set;
7034 	const char *tuple;
7035 	const char *res;
7036 } unbind_set_tests[] = {
7037 	{ "[M, N] -> { : M mod 2 = 0 and N mod 8 = 3 }",
7038 	  "{ A[M, N] }",
7039 	  "{ A[M, N] : M mod 2 = 0 and N mod 8 = 3 }" },
7040 	{ "[M, N] -> { : M mod 2 = 0 and N mod 8 = 3 }",
7041 	  "{ B[N, M] }",
7042 	  "{ B[N, M] : M mod 2 = 0 and N mod 8 = 3 }" },
7043 	{ "[M, N] -> { : M mod 2 = 0 and N mod 8 = 3 }",
7044 	  "{ C[N] }",
7045 	  "[M] -> { C[N] : M mod 2 = 0 and N mod 8 = 3 }" },
7046 	{ "[M, N] -> { : M mod 2 = 0 and N mod 8 = 3 }",
7047 	  "{ D[T, N] }",
7048 	  "[M] -> { D[x, N] : M mod 2 = 0 and N mod 8 = 3 }" },
7049 };
7050 
7051 /* Perform basic isl_set_unbind_params tests.
7052  */
test_unbind_set(isl_ctx * ctx)7053 static isl_stat test_unbind_set(isl_ctx *ctx)
7054 {
7055 	int i;
7056 
7057 	for (i = 0; i < ARRAY_SIZE(unbind_set_tests); ++i) {
7058 		const char *str;
7059 		isl_set *set;
7060 		isl_multi_id *tuple;
7061 		isl_stat r;
7062 
7063 		set = isl_set_read_from_str(ctx, unbind_set_tests[i].set);
7064 		str = unbind_set_tests[i].tuple;
7065 		tuple = isl_multi_id_read_from_str(ctx, str);
7066 		set = isl_set_unbind_params(set, tuple);
7067 		r = set_check_equal(set, unbind_set_tests[i].res);
7068 		isl_set_free(set);
7069 		if (r < 0)
7070 			return isl_stat_error;
7071 	}
7072 
7073 	return isl_stat_ok;
7074 }
7075 
7076 /* Inputs for isl_aff_unbind_params_insert_domain tests.
7077  * "aff" is the input affine expression defined over a parameter domain.
7078  * "tuple" is the tuple of the domain that gets introduced.
7079  * "res" is the expected result.
7080  */
7081 struct {
7082 	const char *aff;
7083 	const char *tuple;
7084 	const char *res;
7085 } unbind_aff_tests[] = {
7086 	{ "[M, N] -> { [M + floor(N/2)] }",
7087 	  "{ A[M, N] }",
7088 	  "{ A[M, N] -> [M + floor(N/2)] }" },
7089 	{ "[M, N] -> { [M + floor(N/2)] }",
7090 	  "{ B[N, M] }",
7091 	  "{ B[N, M] -> [M + floor(N/2)] }" },
7092 	{ "[M, N] -> { [M + floor(N/2)] }",
7093 	  "{ C[N] }",
7094 	  "[M] -> { C[N] -> [M + floor(N/2)] }" },
7095 	{ "[M, N] -> { [M + floor(N/2)] }",
7096 	  "{ D[A, B, C, N, Z] }",
7097 	  "[M] -> { D[A, B, C, N, Z] -> [M + floor(N/2)] }" },
7098 };
7099 
7100 /* Perform basic isl_aff_unbind_params_insert_domain tests.
7101  */
test_unbind_aff(isl_ctx * ctx)7102 static isl_stat test_unbind_aff(isl_ctx *ctx)
7103 {
7104 	int i;
7105 
7106 	for (i = 0; i < ARRAY_SIZE(unbind_aff_tests); ++i) {
7107 		const char *str;
7108 		isl_aff *aff;
7109 		isl_multi_id *tuple;
7110 		isl_stat r;
7111 
7112 		aff = isl_aff_read_from_str(ctx, unbind_aff_tests[i].aff);
7113 		str = unbind_aff_tests[i].tuple;
7114 		tuple = isl_multi_id_read_from_str(ctx, str);
7115 		aff = isl_aff_unbind_params_insert_domain(aff, tuple);
7116 		r = aff_check_plain_equal(aff, unbind_aff_tests[i].res);
7117 		isl_aff_free(aff);
7118 		if (r < 0)
7119 			return isl_stat_error;
7120 	}
7121 
7122 	return isl_stat_ok;
7123 }
7124 
7125 /* Perform tests that reinterpret parameters.
7126  */
test_unbind(isl_ctx * ctx)7127 static int test_unbind(isl_ctx *ctx)
7128 {
7129 	if (test_unbind_set(ctx) < 0)
7130 		return -1;
7131 	if (test_unbind_aff(ctx) < 0)
7132 		return -1;
7133 
7134 	return 0;
7135 }
7136 
7137 /* Check that "pa" consists of a single expression.
7138  */
check_single_piece(isl_ctx * ctx,__isl_take isl_pw_aff * pa)7139 static int check_single_piece(isl_ctx *ctx, __isl_take isl_pw_aff *pa)
7140 {
7141 	isl_size n;
7142 
7143 	n = isl_pw_aff_n_piece(pa);
7144 	isl_pw_aff_free(pa);
7145 
7146 	if (n < 0)
7147 		return -1;
7148 	if (n != 1)
7149 		isl_die(ctx, isl_error_unknown, "expecting single expression",
7150 			return -1);
7151 
7152 	return 0;
7153 }
7154 
7155 /* Check that the computation below results in a single expression.
7156  * One or two expressions may result depending on which constraint
7157  * ends up being considered as redundant with respect to the other
7158  * constraints after the projection that is performed internally
7159  * by isl_set_dim_min.
7160  */
test_dim_max_1(isl_ctx * ctx)7161 static int test_dim_max_1(isl_ctx *ctx)
7162 {
7163 	const char *str;
7164 	isl_set *set;
7165 	isl_pw_aff *pa;
7166 
7167 	str = "[n] -> { [a, b] : n >= 0 and 4a >= -4 + n and b >= 0 and "
7168 				"-4a <= b <= 3 and b < n - 4a }";
7169 	set = isl_set_read_from_str(ctx, str);
7170 	pa = isl_set_dim_min(set, 0);
7171 	return check_single_piece(ctx, pa);
7172 }
7173 
7174 /* Check that the computation below results in a single expression.
7175  * The PIP problem corresponding to these constraints has a row
7176  * that causes a split of the solution domain.  The solver should
7177  * first pick rows that split off empty parts such that the actual
7178  * solution domain does not get split.
7179  * Note that the description contains some redundant constraints.
7180  * If these constraints get removed first, then the row mentioned
7181  * above does not appear in the PIP problem.
7182  */
test_dim_max_2(isl_ctx * ctx)7183 static int test_dim_max_2(isl_ctx *ctx)
7184 {
7185 	const char *str;
7186 	isl_set *set;
7187 	isl_pw_aff *pa;
7188 
7189 	str = "[P, N] -> { [a] : a < N and a >= 0 and N > P and a <= P and "
7190 				"N > 0 and P >= 0 }";
7191 	set = isl_set_read_from_str(ctx, str);
7192 	pa = isl_set_dim_max(set, 0);
7193 	return check_single_piece(ctx, pa);
7194 }
7195 
test_dim_max(isl_ctx * ctx)7196 int test_dim_max(isl_ctx *ctx)
7197 {
7198 	int equal;
7199 	const char *str;
7200 	isl_set *set1, *set2;
7201 	isl_set *set;
7202 	isl_map *map;
7203 	isl_pw_aff *pwaff;
7204 
7205 	if (test_dim_max_1(ctx) < 0)
7206 		return -1;
7207 	if (test_dim_max_2(ctx) < 0)
7208 		return -1;
7209 
7210 	str = "[N] -> { [i] : 0 <= i <= min(N,10) }";
7211 	set = isl_set_read_from_str(ctx, str);
7212 	pwaff = isl_set_dim_max(set, 0);
7213 	set1 = isl_set_from_pw_aff(pwaff);
7214 	str = "[N] -> { [10] : N >= 10; [N] : N <= 9 and N >= 0 }";
7215 	set2 = isl_set_read_from_str(ctx, str);
7216 	equal = isl_set_is_equal(set1, set2);
7217 	isl_set_free(set1);
7218 	isl_set_free(set2);
7219 	if (equal < 0)
7220 		return -1;
7221 	if (!equal)
7222 		isl_die(ctx, isl_error_unknown, "unexpected result", return -1);
7223 
7224 	str = "[N] -> { [i] : 0 <= i <= max(2N,N+6) }";
7225 	set = isl_set_read_from_str(ctx, str);
7226 	pwaff = isl_set_dim_max(set, 0);
7227 	set1 = isl_set_from_pw_aff(pwaff);
7228 	str = "[N] -> { [6 + N] : -6 <= N <= 5; [2N] : N >= 6 }";
7229 	set2 = isl_set_read_from_str(ctx, str);
7230 	equal = isl_set_is_equal(set1, set2);
7231 	isl_set_free(set1);
7232 	isl_set_free(set2);
7233 	if (equal < 0)
7234 		return -1;
7235 	if (!equal)
7236 		isl_die(ctx, isl_error_unknown, "unexpected result", return -1);
7237 
7238 	str = "[N] -> { [i] : 0 <= i <= 2N or 0 <= i <= N+6 }";
7239 	set = isl_set_read_from_str(ctx, str);
7240 	pwaff = isl_set_dim_max(set, 0);
7241 	set1 = isl_set_from_pw_aff(pwaff);
7242 	str = "[N] -> { [6 + N] : -6 <= N <= 5; [2N] : N >= 6 }";
7243 	set2 = isl_set_read_from_str(ctx, str);
7244 	equal = isl_set_is_equal(set1, set2);
7245 	isl_set_free(set1);
7246 	isl_set_free(set2);
7247 	if (equal < 0)
7248 		return -1;
7249 	if (!equal)
7250 		isl_die(ctx, isl_error_unknown, "unexpected result", return -1);
7251 
7252 	str = "[N,M] -> { [i,j] -> [([i/16]), i%16, ([j/16]), j%16] : "
7253 			"0 <= i < N and 0 <= j < M }";
7254 	map = isl_map_read_from_str(ctx, str);
7255 	set = isl_map_range(map);
7256 
7257 	pwaff = isl_set_dim_max(isl_set_copy(set), 0);
7258 	set1 = isl_set_from_pw_aff(pwaff);
7259 	str = "[N,M] -> { [([(N-1)/16])] : M,N > 0 }";
7260 	set2 = isl_set_read_from_str(ctx, str);
7261 	equal = isl_set_is_equal(set1, set2);
7262 	isl_set_free(set1);
7263 	isl_set_free(set2);
7264 
7265 	pwaff = isl_set_dim_max(isl_set_copy(set), 3);
7266 	set1 = isl_set_from_pw_aff(pwaff);
7267 	str = "[N,M] -> { [t] : t = min(M-1,15) and M,N > 0 }";
7268 	set2 = isl_set_read_from_str(ctx, str);
7269 	if (equal >= 0 && equal)
7270 		equal = isl_set_is_equal(set1, set2);
7271 	isl_set_free(set1);
7272 	isl_set_free(set2);
7273 
7274 	isl_set_free(set);
7275 
7276 	if (equal < 0)
7277 		return -1;
7278 	if (!equal)
7279 		isl_die(ctx, isl_error_unknown, "unexpected result", return -1);
7280 
7281 	/* Check that solutions are properly merged. */
7282 	str = "[n] -> { [a, b, c] : c >= -4a - 2b and "
7283 				"c <= -1 + n - 4a - 2b and c >= -2b and "
7284 				"4a >= -4 + n and c >= 0 }";
7285 	set = isl_set_read_from_str(ctx, str);
7286 	pwaff = isl_set_dim_min(set, 2);
7287 	set1 = isl_set_from_pw_aff(pwaff);
7288 	str = "[n] -> { [(0)] : n >= 1 }";
7289 	set2 = isl_set_read_from_str(ctx, str);
7290 	equal = isl_set_is_equal(set1, set2);
7291 	isl_set_free(set1);
7292 	isl_set_free(set2);
7293 
7294 	if (equal < 0)
7295 		return -1;
7296 	if (!equal)
7297 		isl_die(ctx, isl_error_unknown, "unexpected result", return -1);
7298 
7299 	/* Check that empty solution lie in the right space. */
7300 	str = "[n] -> { [t,a] : 1 = 0 }";
7301 	set = isl_set_read_from_str(ctx, str);
7302 	pwaff = isl_set_dim_max(set, 0);
7303 	set1 = isl_set_from_pw_aff(pwaff);
7304 	str = "[n] -> { [t] : 1 = 0 }";
7305 	set2 = isl_set_read_from_str(ctx, str);
7306 	equal = isl_set_is_equal(set1, set2);
7307 	isl_set_free(set1);
7308 	isl_set_free(set2);
7309 
7310 	if (equal < 0)
7311 		return -1;
7312 	if (!equal)
7313 		isl_die(ctx, isl_error_unknown, "unexpected result", return -1);
7314 
7315 	return 0;
7316 }
7317 
7318 /* Basic test for isl_pw_multi_aff_product.
7319  *
7320  * Check that multiple pieces are properly handled.
7321  */
test_product_pma(isl_ctx * ctx)7322 static int test_product_pma(isl_ctx *ctx)
7323 {
7324 	isl_stat equal;
7325 	const char *str;
7326 	isl_pw_multi_aff *pma1, *pma2;
7327 
7328 	str = "{ A[i] -> B[1] : i < 0; A[i] -> B[2] : i >= 0 }";
7329 	pma1 = isl_pw_multi_aff_read_from_str(ctx, str);
7330 	str = "{ C[] -> D[] }";
7331 	pma2 = isl_pw_multi_aff_read_from_str(ctx, str);
7332 	pma1 = isl_pw_multi_aff_product(pma1, pma2);
7333 	str = "{ [A[i] -> C[]] -> [B[(1)] -> D[]] : i < 0;"
7334 		"[A[i] -> C[]] -> [B[(2)] -> D[]] : i >= 0 }";
7335 	equal = pw_multi_aff_check_plain_equal(pma1, str);
7336 	isl_pw_multi_aff_free(pma1);
7337 	if (equal < 0)
7338 		return -1;
7339 
7340 	return 0;
7341 }
7342 
test_product(isl_ctx * ctx)7343 int test_product(isl_ctx *ctx)
7344 {
7345 	const char *str;
7346 	isl_set *set;
7347 	isl_union_set *uset1, *uset2;
7348 	int ok;
7349 
7350 	str = "{ A[i] }";
7351 	set = isl_set_read_from_str(ctx, str);
7352 	set = isl_set_product(set, isl_set_copy(set));
7353 	ok = isl_set_is_wrapping(set);
7354 	isl_set_free(set);
7355 	if (ok < 0)
7356 		return -1;
7357 	if (!ok)
7358 		isl_die(ctx, isl_error_unknown, "unexpected result", return -1);
7359 
7360 	str = "{ [] }";
7361 	uset1 = isl_union_set_read_from_str(ctx, str);
7362 	uset1 = isl_union_set_product(uset1, isl_union_set_copy(uset1));
7363 	str = "{ [[] -> []] }";
7364 	uset2 = isl_union_set_read_from_str(ctx, str);
7365 	ok = isl_union_set_is_equal(uset1, uset2);
7366 	isl_union_set_free(uset1);
7367 	isl_union_set_free(uset2);
7368 	if (ok < 0)
7369 		return -1;
7370 	if (!ok)
7371 		isl_die(ctx, isl_error_unknown, "unexpected result", return -1);
7372 
7373 	if (test_product_pma(ctx) < 0)
7374 		return -1;
7375 
7376 	return 0;
7377 }
7378 
7379 /* Check that two sets are not considered disjoint just because
7380  * they have a different set of (named) parameters.
7381  */
test_disjoint(isl_ctx * ctx)7382 static int test_disjoint(isl_ctx *ctx)
7383 {
7384 	const char *str;
7385 	isl_set *set, *set2;
7386 	int disjoint;
7387 
7388 	str = "[n] -> { [[]->[]] }";
7389 	set = isl_set_read_from_str(ctx, str);
7390 	str = "{ [[]->[]] }";
7391 	set2 = isl_set_read_from_str(ctx, str);
7392 	disjoint = isl_set_is_disjoint(set, set2);
7393 	isl_set_free(set);
7394 	isl_set_free(set2);
7395 	if (disjoint < 0)
7396 		return -1;
7397 	if (disjoint)
7398 		isl_die(ctx, isl_error_unknown, "unexpected result", return -1);
7399 
7400 	return 0;
7401 }
7402 
7403 /* Inputs for isl_pw_multi_aff_is_equal tests.
7404  * "f1" and "f2" are the two function that need to be compared.
7405  * "equal" is the expected result.
7406  */
7407 struct {
7408 	int equal;
7409 	const char *f1;
7410 	const char *f2;
7411 } pma_equal_tests[] = {
7412 	{ 1, "[N] -> { [floor(N/2)] : 0 <= N <= 1 }",
7413 	     "[N] -> { [0] : 0 <= N <= 1 }" },
7414 	{ 1, "[N] -> { [floor(N/2)] : 0 <= N <= 2 }",
7415 	     "[N] -> { [0] : 0 <= N <= 1; [1] : N = 2 }" },
7416 	{ 0, "[N] -> { [floor(N/2)] : 0 <= N <= 2 }",
7417 	     "[N] -> { [0] : 0 <= N <= 1 }" },
7418 	{ 0, "{ [NaN] }", "{ [NaN] }" },
7419 };
7420 
test_equal(isl_ctx * ctx)7421 int test_equal(isl_ctx *ctx)
7422 {
7423 	int i;
7424 	const char *str;
7425 	isl_set *set, *set2;
7426 	int equal;
7427 
7428 	str = "{ S_6[i] }";
7429 	set = isl_set_read_from_str(ctx, str);
7430 	str = "{ S_7[i] }";
7431 	set2 = isl_set_read_from_str(ctx, str);
7432 	equal = isl_set_is_equal(set, set2);
7433 	isl_set_free(set);
7434 	isl_set_free(set2);
7435 	if (equal < 0)
7436 		return -1;
7437 	if (equal)
7438 		isl_die(ctx, isl_error_unknown, "unexpected result", return -1);
7439 
7440 	for (i = 0; i < ARRAY_SIZE(pma_equal_tests); ++i) {
7441 		int expected = pma_equal_tests[i].equal;
7442 		isl_pw_multi_aff *f1, *f2;
7443 
7444 		f1 = isl_pw_multi_aff_read_from_str(ctx, pma_equal_tests[i].f1);
7445 		f2 = isl_pw_multi_aff_read_from_str(ctx, pma_equal_tests[i].f2);
7446 		equal = isl_pw_multi_aff_is_equal(f1, f2);
7447 		isl_pw_multi_aff_free(f1);
7448 		isl_pw_multi_aff_free(f2);
7449 		if (equal < 0)
7450 			return -1;
7451 		if (equal != expected)
7452 			isl_die(ctx, isl_error_unknown,
7453 				"unexpected equality result", return -1);
7454 	}
7455 
7456 	return 0;
7457 }
7458 
test_plain_fixed(isl_ctx * ctx,__isl_take isl_map * map,enum isl_dim_type type,unsigned pos,int fixed)7459 static int test_plain_fixed(isl_ctx *ctx, __isl_take isl_map *map,
7460 	enum isl_dim_type type, unsigned pos, int fixed)
7461 {
7462 	isl_bool test;
7463 
7464 	test = isl_map_plain_is_fixed(map, type, pos, NULL);
7465 	isl_map_free(map);
7466 	if (test < 0)
7467 		return -1;
7468 	if (test == fixed)
7469 		return 0;
7470 	if (fixed)
7471 		isl_die(ctx, isl_error_unknown,
7472 			"map not detected as fixed", return -1);
7473 	else
7474 		isl_die(ctx, isl_error_unknown,
7475 			"map detected as fixed", return -1);
7476 }
7477 
test_fixed(isl_ctx * ctx)7478 int test_fixed(isl_ctx *ctx)
7479 {
7480 	const char *str;
7481 	isl_map *map;
7482 
7483 	str = "{ [i] -> [i] }";
7484 	map = isl_map_read_from_str(ctx, str);
7485 	if (test_plain_fixed(ctx, map, isl_dim_out, 0, 0))
7486 		return -1;
7487 	str = "{ [i] -> [1] }";
7488 	map = isl_map_read_from_str(ctx, str);
7489 	if (test_plain_fixed(ctx, map, isl_dim_out, 0, 1))
7490 		return -1;
7491 	str = "{ S_1[p1] -> [o0] : o0 = -2 and p1 >= 1 and p1 <= 7 }";
7492 	map = isl_map_read_from_str(ctx, str);
7493 	if (test_plain_fixed(ctx, map, isl_dim_out, 0, 1))
7494 		return -1;
7495 	map = isl_map_read_from_str(ctx, str);
7496 	map = isl_map_neg(map);
7497 	if (test_plain_fixed(ctx, map, isl_dim_out, 0, 1))
7498 		return -1;
7499 
7500 	return 0;
7501 }
7502 
7503 struct isl_vertices_test_data {
7504 	const char *set;
7505 	int n;
7506 	const char *vertex[6];
7507 } vertices_tests[] = {
7508 	{ "{ A[t, i] : t = 12 and i >= 4 and i <= 12 }",
7509 	  2, { "{ A[12, 4] }", "{ A[12, 12] }" } },
7510 	{ "{ A[t, i] : t = 14 and i = 1 }",
7511 	  1, { "{ A[14, 1] }" } },
7512 	{ "[n, m] -> { [a, b, c] : b <= a and a <= n and b > 0 and c >= b and "
7513 				"c <= m and m <= n and m > 0 }",
7514 	  6, {
7515 		"[n, m] -> { [n, m, m] : 0 < m <= n }",
7516 		"[n, m] -> { [n, 1, m] : 0 < m <= n }",
7517 		"[n, m] -> { [n, 1, 1] : 0 < m <= n }",
7518 		"[n, m] -> { [m, m, m] : 0 < m <= n }",
7519 		"[n, m] -> { [1, 1, m] : 0 < m <= n }",
7520 		"[n, m] -> { [1, 1, 1] : 0 < m <= n }"
7521 	    } },
7522 };
7523 
7524 /* Check that "vertex" corresponds to one of the vertices in data->vertex.
7525  */
find_vertex(__isl_take isl_vertex * vertex,void * user)7526 static isl_stat find_vertex(__isl_take isl_vertex *vertex, void *user)
7527 {
7528 	struct isl_vertices_test_data *data = user;
7529 	isl_ctx *ctx;
7530 	isl_multi_aff *ma;
7531 	isl_basic_set *bset;
7532 	isl_pw_multi_aff *pma;
7533 	int i;
7534 	isl_bool equal;
7535 
7536 	ctx = isl_vertex_get_ctx(vertex);
7537 	bset = isl_vertex_get_domain(vertex);
7538 	ma = isl_vertex_get_expr(vertex);
7539 	pma = isl_pw_multi_aff_alloc(isl_set_from_basic_set(bset), ma);
7540 
7541 	for (i = 0; i < data->n; ++i) {
7542 		isl_pw_multi_aff *pma_i;
7543 
7544 		pma_i = isl_pw_multi_aff_read_from_str(ctx, data->vertex[i]);
7545 		equal = isl_pw_multi_aff_plain_is_equal(pma, pma_i);
7546 		isl_pw_multi_aff_free(pma_i);
7547 
7548 		if (equal < 0 || equal)
7549 			break;
7550 	}
7551 
7552 	isl_pw_multi_aff_free(pma);
7553 	isl_vertex_free(vertex);
7554 
7555 	if (equal < 0)
7556 		return isl_stat_error;
7557 
7558 	return equal ? isl_stat_ok : isl_stat_error;
7559 }
7560 
test_vertices(isl_ctx * ctx)7561 int test_vertices(isl_ctx *ctx)
7562 {
7563 	int i;
7564 
7565 	for (i = 0; i < ARRAY_SIZE(vertices_tests); ++i) {
7566 		isl_basic_set *bset;
7567 		isl_vertices *vertices;
7568 		int ok = 1;
7569 		isl_size n;
7570 
7571 		bset = isl_basic_set_read_from_str(ctx, vertices_tests[i].set);
7572 		vertices = isl_basic_set_compute_vertices(bset);
7573 		n = isl_vertices_get_n_vertices(vertices);
7574 		if (vertices_tests[i].n != n)
7575 			ok = 0;
7576 		if (isl_vertices_foreach_vertex(vertices, &find_vertex,
7577 						&vertices_tests[i]) < 0)
7578 			ok = 0;
7579 		isl_vertices_free(vertices);
7580 		isl_basic_set_free(bset);
7581 
7582 		if (n < 0)
7583 			return -1;
7584 		if (!ok)
7585 			isl_die(ctx, isl_error_unknown, "unexpected vertices",
7586 				return -1);
7587 	}
7588 
7589 	return 0;
7590 }
7591 
7592 /* Inputs for basic tests of unary operations on isl_union_map.
7593  * "fn" is the function that is being tested.
7594  * "arg" is a string description of the input.
7595  * "res" is a string description of the expected result.
7596  */
7597 static struct {
7598 	__isl_give isl_union_map *(*fn)(__isl_take isl_union_map *umap);
7599 	const char *arg;
7600 	const char *res;
7601 } umap_un_tests[] = {
7602 	{ &isl_union_map_range_reverse,
7603 	  "{ A[] -> [B[] -> C[]]; A[] -> B[]; A[0] -> N[B[1] -> B[2]] }",
7604 	  "{ A[] -> [C[] -> B[]]; A[0] -> N[B[2] -> B[1]] }" },
7605 	{ &isl_union_map_range_reverse,
7606 	  "{ A[] -> N[B[] -> C[]] }",
7607 	  "{ A[] -> [C[] -> B[]] }" },
7608 	{ &isl_union_map_range_reverse,
7609 	  "{ A[] -> N[B[x] -> B[y]] }",
7610 	  "{ A[] -> N[B[*] -> B[*]] }" },
7611 };
7612 
7613 /* Perform basic tests of unary operations on isl_union_map.
7614  */
test_un_union_map(isl_ctx * ctx)7615 static isl_stat test_un_union_map(isl_ctx *ctx)
7616 {
7617 	int i;
7618 
7619 	for (i = 0; i < ARRAY_SIZE(umap_un_tests); ++i) {
7620 		const char *str;
7621 		isl_union_map *umap, *res;
7622 		isl_bool equal;
7623 
7624 		str = umap_un_tests[i].arg;
7625 		umap = isl_union_map_read_from_str(ctx, str);
7626 		str = umap_un_tests[i].res;
7627 		res = isl_union_map_read_from_str(ctx, str);
7628 		umap = umap_un_tests[i].fn(umap);
7629 		equal = isl_union_map_is_equal(umap, res);
7630 		isl_union_map_free(umap);
7631 		isl_union_map_free(res);
7632 		if (equal < 0)
7633 			return isl_stat_error;
7634 		if (!equal)
7635 			isl_die(ctx, isl_error_unknown,
7636 				"unexpected result", return isl_stat_error);
7637 	}
7638 
7639 	return isl_stat_ok;
7640 }
7641 
7642 /* Inputs for basic tests of binary operations on isl_union_map.
7643  * "fn" is the function that is being tested.
7644  * "arg1" and "arg2" are string descriptions of the inputs.
7645  * "res" is a string description of the expected result.
7646  */
7647 static struct {
7648 	__isl_give isl_union_map *(*fn)(__isl_take isl_union_map *umap1,
7649 				__isl_take isl_union_map *umap2);
7650 	const char *arg1;
7651 	const char *arg2;
7652 	const char *res;
7653 } umap_bin_tests[] = {
7654 	{ &isl_union_map_intersect,
7655 	  "[n] -> { A[i] -> [] : 0 <= i <= n; B[] -> [] }",
7656 	  "[m] -> { A[i] -> [] : 0 <= i <= m; C[] -> [] }",
7657 	  "[m, n] -> { A[i] -> [] : 0 <= i <= n and i <= m }" },
7658 	{ &isl_union_map_intersect_domain_factor_range,
7659 	  "{ [A[i] -> B[i + 1]] -> C[i + 2] }",
7660 	  "[N] -> { B[i] -> C[N] }",
7661 	  "[N] -> { [A[N - 2] -> B[N - 1]] -> C[N] }" },
7662 	{ &isl_union_map_intersect_domain_factor_range,
7663 	  "{ T[A[i] -> B[i + 1]] -> C[i + 2] }",
7664 	  "[N] -> { B[i] -> C[N] }",
7665 	  "[N] -> { T[A[N - 2] -> B[N - 1]] -> C[N] }" },
7666 	{ &isl_union_map_intersect_domain_factor_range,
7667 	  "{ [A[i] -> B[i + 1]] -> C[i + 2] }",
7668 	  "[N] -> { A[i] -> C[N] }",
7669 	  "{ }" },
7670 	{ &isl_union_map_intersect_range_factor_domain,
7671 	  "{ A[i] -> [B[i + 1] -> C[i + 2]] }",
7672 	  "[N] -> { A[i] -> B[N] }",
7673 	  "[N] -> { A[N - 1] -> [B[N] -> C[N + 1]] }" },
7674 	{ &isl_union_map_intersect_range_factor_domain,
7675 	  "{ A[i] -> T[B[i + 1] -> C[i + 2]] }",
7676 	  "[N] -> { A[i] -> B[N] }",
7677 	  "[N] -> { A[N - 1] -> T[B[N] -> C[N + 1]] }" },
7678 	{ &isl_union_map_intersect_range_factor_domain,
7679 	  "{ A[i] -> [B[i + 1] -> C[i + 2]] }",
7680 	  "[N] -> { A[i] -> C[N] }",
7681 	  "{ }" },
7682 	{ &isl_union_map_intersect_range_factor_range,
7683 	  "{ A[i] -> [B[i + 1] -> C[i + 2]] }",
7684 	  "[N] -> { A[i] -> C[N] }",
7685 	  "[N] -> { A[N - 2] -> [B[N - 1] -> C[N]] }" },
7686 	{ &isl_union_map_intersect_range_factor_range,
7687 	  "{ A[i] -> T[B[i + 1] -> C[i + 2]] }",
7688 	  "[N] -> { A[i] -> C[N] }",
7689 	  "[N] -> { A[N - 2] -> T[B[N - 1] -> C[N]] }" },
7690 	{ &isl_union_map_intersect_range_factor_range,
7691 	  "{ A[i] -> [B[i + 1] -> C[i + 2]] }",
7692 	  "[N] -> { A[i] -> B[N] }",
7693 	  "{ }" },
7694 };
7695 
7696 /* Perform basic tests of binary operations on isl_union_map.
7697  */
test_bin_union_map(isl_ctx * ctx)7698 static isl_stat test_bin_union_map(isl_ctx *ctx)
7699 {
7700 	int i;
7701 
7702 	for (i = 0; i < ARRAY_SIZE(umap_bin_tests); ++i) {
7703 		const char *str;
7704 		isl_union_map *umap1, *umap2, *res;
7705 		isl_bool equal;
7706 
7707 		str = umap_bin_tests[i].arg1;
7708 		umap1 = isl_union_map_read_from_str(ctx, str);
7709 		str = umap_bin_tests[i].arg2;
7710 		umap2 = isl_union_map_read_from_str(ctx, str);
7711 		str = umap_bin_tests[i].res;
7712 		res = isl_union_map_read_from_str(ctx, str);
7713 		umap1 = umap_bin_tests[i].fn(umap1, umap2);
7714 		equal = isl_union_map_is_equal(umap1, res);
7715 		isl_union_map_free(umap1);
7716 		isl_union_map_free(res);
7717 		if (equal < 0)
7718 			return isl_stat_error;
7719 		if (!equal)
7720 			isl_die(ctx, isl_error_unknown,
7721 				"unexpected result", return isl_stat_error);
7722 	}
7723 
7724 	return isl_stat_ok;
7725 }
7726 
7727 /* Perform basic tests of operations on isl_union_map.
7728  */
test_union_map(isl_ctx * ctx)7729 static int test_union_map(isl_ctx *ctx)
7730 {
7731 	if (test_un_union_map(ctx) < 0)
7732 		return -1;
7733 	if (test_bin_union_map(ctx) < 0)
7734 		return -1;
7735 	return 0;
7736 }
7737 
test_union_pw(isl_ctx * ctx)7738 int test_union_pw(isl_ctx *ctx)
7739 {
7740 	int equal;
7741 	const char *str;
7742 	isl_union_set *uset;
7743 	isl_union_pw_qpolynomial *upwqp1, *upwqp2;
7744 
7745 	str = "{ [x] -> x^2 }";
7746 	upwqp1 = isl_union_pw_qpolynomial_read_from_str(ctx, str);
7747 	upwqp2 = isl_union_pw_qpolynomial_copy(upwqp1);
7748 	uset = isl_union_pw_qpolynomial_domain(upwqp1);
7749 	upwqp1 = isl_union_pw_qpolynomial_copy(upwqp2);
7750 	upwqp1 = isl_union_pw_qpolynomial_intersect_domain(upwqp1, uset);
7751 	equal = isl_union_pw_qpolynomial_plain_is_equal(upwqp1, upwqp2);
7752 	isl_union_pw_qpolynomial_free(upwqp1);
7753 	isl_union_pw_qpolynomial_free(upwqp2);
7754 	if (equal < 0)
7755 		return -1;
7756 	if (!equal)
7757 		isl_die(ctx, isl_error_unknown, "unexpected result", return -1);
7758 
7759 	return 0;
7760 }
7761 
7762 /* Inputs for basic tests of functions that select
7763  * subparts of the domain of an isl_multi_union_pw_aff.
7764  * "fn" is the function that is tested.
7765  * "arg" is a string description of the input.
7766  * "res" is a string description of the expected result.
7767  */
7768 struct {
7769 	__isl_give isl_union_set *(*fn)(
7770 		__isl_take isl_multi_union_pw_aff *mupa);
7771 	const char *arg;
7772 	const char *res;
7773 } un_locus_tests[] = {
7774 	{ &isl_multi_union_pw_aff_zero_union_set,
7775 	  "F[{ A[i,j] -> [i]; B[i,j] -> [i] }]",
7776 	  "{ A[0,j]; B[0,j] }" },
7777 	{ &isl_multi_union_pw_aff_zero_union_set,
7778 	  "F[{ A[i,j] -> [i-j]; B[i,j] -> [i-j] : i >= 0 }]",
7779 	  "{ A[i,i]; B[i,i] : i >= 0 }" },
7780 	{ &isl_multi_union_pw_aff_zero_union_set,
7781 	  "(F[] : { A[i,j]; B[i,i] : i >= 0 })",
7782 	  "{ A[i,j]; B[i,i] : i >= 0 }" },
7783 };
7784 
7785 /* Perform some basic tests of functions that select
7786  * subparts of the domain of an isl_multi_union_pw_aff.
7787  */
test_un_locus(isl_ctx * ctx)7788 static int test_un_locus(isl_ctx *ctx)
7789 {
7790 	int i;
7791 	isl_bool ok;
7792 	isl_union_set *uset, *res;
7793 	isl_multi_union_pw_aff *mupa;
7794 
7795 	for (i = 0; i < ARRAY_SIZE(un_locus_tests); ++i) {
7796 		mupa = isl_multi_union_pw_aff_read_from_str(ctx,
7797 						    un_locus_tests[i].arg);
7798 		res = isl_union_set_read_from_str(ctx, un_locus_tests[i].res);
7799 		uset = un_locus_tests[i].fn(mupa);
7800 		ok = isl_union_set_is_equal(uset, res);
7801 		isl_union_set_free(uset);
7802 		isl_union_set_free(res);
7803 		if (ok < 0)
7804 			return -1;
7805 		if (!ok)
7806 			isl_die(ctx, isl_error_unknown,
7807 				"unexpected result", return -1);
7808 	}
7809 
7810 	return 0;
7811 }
7812 
7813 /* Inputs for basic tests of functions that select
7814  * subparts of an isl_union_map based on a relation
7815  * specified by an isl_multi_union_pw_aff.
7816  * "fn" is the function that is tested.
7817  * "arg1" and "arg2" are string descriptions of the inputs.
7818  * "res" is a string description of the expected result.
7819  */
7820 struct {
7821 	__isl_give isl_union_map *(*fn)(
7822 		__isl_take isl_union_map *umap,
7823 		__isl_take isl_multi_union_pw_aff *mupa);
7824 	const char *arg1;
7825 	const char *arg2;
7826 	const char *res;
7827 } bin_locus_tests[] = {
7828 	{ &isl_union_map_eq_at_multi_union_pw_aff,
7829 	  "{ A[i,j] -> B[i',j'] }",
7830 	  "F[{ A[i,j] -> [i]; B[i,j] -> [i] }]",
7831 	  "{ A[i,j] -> B[i,j'] }" },
7832 	{ &isl_union_map_eq_at_multi_union_pw_aff,
7833 	  "{ A[i,j] -> B[i',j'] }",
7834 	  "F[{ A[i,j] -> [i]; B[i,j] -> [i] }, "
7835 	    "{ A[i,j] -> [j]; B[i,j] -> [j] }]",
7836 	  "{ A[i,j] -> B[i,j] }" },
7837 	{ &isl_union_map_eq_at_multi_union_pw_aff,
7838 	  "{ A[i,j] -> B[i',j']; A[i,j] -> C[i',j'] }",
7839 	  "F[{ A[i,j] -> [i]; B[i,j] -> [i] }]",
7840 	  "{ A[i,j] -> B[i,j'] }" },
7841 	{ &isl_union_map_eq_at_multi_union_pw_aff,
7842 	  "{ A[i,j] -> B[i',j']; A[i,j] -> C[i',j'] }",
7843 	  "F[{ A[i,j] -> [i]; B[i,j] -> [i]; C[i,j] -> [0] }]",
7844 	  "{ A[i,j] -> B[i,j']; A[0,j] -> C[i',j'] }" },
7845 	{ &isl_union_map_eq_at_multi_union_pw_aff,
7846 	  "{ A[i,j] -> B[i',j'] }",
7847 	  "F[{ A[i,j] -> [i] : i > j; B[i,j] -> [i] }]",
7848 	  "{ A[i,j] -> B[i,j'] : i > j }" },
7849 	{ &isl_union_map_lex_lt_at_multi_union_pw_aff,
7850 	  "{ A[i,j] -> B[i',j'] }",
7851 	  "F[{ A[i,j] -> [i]; B[i,j] -> [i] }, "
7852 	    "{ A[i,j] -> [j]; B[i,j] -> [j] }]",
7853 	  "{ A[i,j] -> B[i',j'] : i,j << i',j' }" },
7854 	{ &isl_union_map_lex_gt_at_multi_union_pw_aff,
7855 	  "{ A[i,j] -> B[i',j'] }",
7856 	  "F[{ A[i,j] -> [i]; B[i,j] -> [i] }, "
7857 	    "{ A[i,j] -> [j]; B[i,j] -> [j] }]",
7858 	  "{ A[i,j] -> B[i',j'] : i,j >> i',j' }" },
7859 	{ &isl_union_map_eq_at_multi_union_pw_aff,
7860 	  "{ A[i,j] -> B[i',j']; A[i,j] -> C[i',j'] }",
7861 	  "(F[] : { A[i,j]; B[i,j] })",
7862 	  "{ A[i,j] -> B[i',j'] }" },
7863 	{ &isl_union_map_eq_at_multi_union_pw_aff,
7864 	  "{ A[i,j] -> B[i',j'] }",
7865 	  "(F[] : { A[i,j] : i > j; B[i,j] : i < j })",
7866 	  "{ A[i,j] -> B[i',j'] : i > j and i' < j' }" },
7867 	{ &isl_union_map_eq_at_multi_union_pw_aff,
7868 	  "[N] -> { A[i,j] -> B[i',j'] : i,i' <= N }",
7869 	  "(F[] : { A[i,j] : i > j; B[i,j] : i < j })",
7870 	  "[N] -> { A[i,j] -> B[i',j'] : i > j and i' < j' and i,i' <= N }" },
7871 	{ &isl_union_map_eq_at_multi_union_pw_aff,
7872 	  "{ A[i,j] -> B[i',j'] }",
7873 	  "[N] -> (F[] : { A[i,j] : i < N; B[i,j] : i < N })",
7874 	  "[N] -> { A[i,j] -> B[i',j'] : i,i' < N }" },
7875 	{ &isl_union_map_eq_at_multi_union_pw_aff,
7876 	  "{ A[i,j] -> B[i',j'] }",
7877 	  "[N] -> (F[] : { : N >= 0 })",
7878 	  "[N] -> { A[i,j] -> B[i',j'] : N >= 0 }" },
7879 };
7880 
7881 /* Perform some basic tests of functions that select
7882  * subparts of an isl_union_map based on a relation
7883  * specified by an isl_multi_union_pw_aff.
7884  */
test_bin_locus(isl_ctx * ctx)7885 static int test_bin_locus(isl_ctx *ctx)
7886 {
7887 	int i;
7888 	isl_bool ok;
7889 	isl_union_map *umap, *res;
7890 	isl_multi_union_pw_aff *mupa;
7891 
7892 	for (i = 0; i < ARRAY_SIZE(bin_locus_tests); ++i) {
7893 		umap = isl_union_map_read_from_str(ctx,
7894 						    bin_locus_tests[i].arg1);
7895 		mupa = isl_multi_union_pw_aff_read_from_str(ctx,
7896 						    bin_locus_tests[i].arg2);
7897 		res = isl_union_map_read_from_str(ctx, bin_locus_tests[i].res);
7898 		umap = bin_locus_tests[i].fn(umap, mupa);
7899 		ok = isl_union_map_is_equal(umap, res);
7900 		isl_union_map_free(umap);
7901 		isl_union_map_free(res);
7902 		if (ok < 0)
7903 			return -1;
7904 		if (!ok)
7905 			isl_die(ctx, isl_error_unknown,
7906 				"unexpected result", return -1);
7907 	}
7908 
7909 	return 0;
7910 }
7911 
7912 /* Perform basic locus tests.
7913  */
test_locus(isl_ctx * ctx)7914 static int test_locus(isl_ctx *ctx)
7915 {
7916 	if (test_un_locus(ctx) < 0)
7917 		return -1;
7918 	if (test_bin_locus(ctx) < 0)
7919 		return -1;
7920 	return 0;
7921 }
7922 
7923 /* Test that isl_union_pw_qpolynomial_eval picks up the function
7924  * defined over the correct domain space.
7925  */
test_eval_1(isl_ctx * ctx)7926 static int test_eval_1(isl_ctx *ctx)
7927 {
7928 	const char *str;
7929 	isl_point *pnt;
7930 	isl_set *set;
7931 	isl_union_pw_qpolynomial *upwqp;
7932 	isl_val *v;
7933 	int cmp;
7934 
7935 	str = "{ A[x] -> x^2; B[x] -> -x^2 }";
7936 	upwqp = isl_union_pw_qpolynomial_read_from_str(ctx, str);
7937 	str = "{ A[6] }";
7938 	set = isl_set_read_from_str(ctx, str);
7939 	pnt = isl_set_sample_point(set);
7940 	v = isl_union_pw_qpolynomial_eval(upwqp, pnt);
7941 	cmp = isl_val_cmp_si(v, 36);
7942 	isl_val_free(v);
7943 
7944 	if (!v)
7945 		return -1;
7946 	if (cmp != 0)
7947 		isl_die(ctx, isl_error_unknown, "unexpected value", return -1);
7948 
7949 	return 0;
7950 }
7951 
7952 /* Check that isl_qpolynomial_eval handles getting called on a void point.
7953  */
test_eval_2(isl_ctx * ctx)7954 static int test_eval_2(isl_ctx *ctx)
7955 {
7956 	const char *str;
7957 	isl_point *pnt;
7958 	isl_set *set;
7959 	isl_qpolynomial *qp;
7960 	isl_val *v;
7961 	isl_bool ok;
7962 
7963 	str = "{ A[x] -> [x] }";
7964 	qp = isl_qpolynomial_from_aff(isl_aff_read_from_str(ctx, str));
7965 	str = "{ A[x] : false }";
7966 	set = isl_set_read_from_str(ctx, str);
7967 	pnt = isl_set_sample_point(set);
7968 	v = isl_qpolynomial_eval(qp, pnt);
7969 	ok = isl_val_is_nan(v);
7970 	isl_val_free(v);
7971 
7972 	if (ok < 0)
7973 		return -1;
7974 	if (!ok)
7975 		isl_die(ctx, isl_error_unknown, "expecting NaN", return -1);
7976 
7977 	return 0;
7978 }
7979 
7980 /* Check that a polynomial (without local variables) can be evaluated
7981  * in a rational point.
7982  */
test_eval_3(isl_ctx * ctx)7983 static isl_stat test_eval_3(isl_ctx *ctx)
7984 {
7985 	isl_pw_qpolynomial *pwqp;
7986 	isl_point *pnt;
7987 	isl_val *v;
7988 	isl_stat r;
7989 
7990 	pwqp = isl_pw_qpolynomial_read_from_str(ctx, "{ [x] -> x^2 }");
7991 	pnt = isl_point_zero(isl_pw_qpolynomial_get_domain_space(pwqp));
7992 	v = isl_val_read_from_str(ctx, "1/2");
7993 	pnt = isl_point_set_coordinate_val(pnt, isl_dim_set, 0, v);
7994 	v = isl_pw_qpolynomial_eval(pwqp, pnt);
7995 	r = val_check_equal(v, "1/4");
7996 	isl_val_free(v);
7997 
7998 	return r;
7999 }
8000 
8001 /* Inputs for isl_pw_aff_eval test.
8002  * "f" is the affine function.
8003  * "p" is the point where the function should be evaluated.
8004  * "res" is the expected result.
8005  */
8006 struct {
8007 	const char *f;
8008 	const char *p;
8009 	const char *res;
8010 } aff_eval_tests[] = {
8011 	{ "{ [i] -> [2 * i] }", "{ [4] }", "8" },
8012 	{ "{ [i] -> [2 * i] }", "{ [x] : false }", "NaN" },
8013 	{ "{ [i] -> [i + floor(i/2) + floor(i/3)] }", "{ [0] }", "0" },
8014 	{ "{ [i] -> [i + floor(i/2) + floor(i/3)] }", "{ [1] }", "1" },
8015 	{ "{ [i] -> [i + floor(i/2) + floor(i/3)] }", "{ [2] }", "3" },
8016 	{ "{ [i] -> [i + floor(i/2) + floor(i/3)] }", "{ [3] }", "5" },
8017 	{ "{ [i] -> [i + floor(i/2) + floor(i/3)] }", "{ [4] }", "7" },
8018 	{ "{ [i] -> [floor((3 * floor(i/2))/5)] }", "{ [0] }", "0" },
8019 	{ "{ [i] -> [floor((3 * floor(i/2))/5)] }", "{ [1] }", "0" },
8020 	{ "{ [i] -> [floor((3 * floor(i/2))/5)] }", "{ [2] }", "0" },
8021 	{ "{ [i] -> [floor((3 * floor(i/2))/5)] }", "{ [3] }", "0" },
8022 	{ "{ [i] -> [floor((3 * floor(i/2))/5)] }", "{ [4] }", "1" },
8023 	{ "{ [i] -> [floor((3 * floor(i/2))/5)] }", "{ [6] }", "1" },
8024 	{ "{ [i] -> [floor((3 * floor(i/2))/5)] }", "{ [8] }", "2" },
8025 	{ "{ [i] -> [i] : i > 0; [i] -> [-i] : i < 0 }", "{ [4] }", "4" },
8026 	{ "{ [i] -> [i] : i > 0; [i] -> [-i] : i < 0 }", "{ [-2] }", "2" },
8027 	{ "{ [i] -> [i] : i > 0; [i] -> [-i] : i < 0 }", "{ [0] }", "NaN" },
8028 	{ "[N] -> { [2 * N] }", "[N] -> { : N = 4 }", "8" },
8029 	{ "{ [i, j] -> [(i + j)/2] }", "{ [1, 1] }", "1" },
8030 	{ "{ [i, j] -> [(i + j)/2] }", "{ [1, 2] }", "3/2" },
8031 	{ "{ [i] -> [i] : i mod 2 = 0 }", "{ [4] }", "4" },
8032 	{ "{ [i] -> [i] : i mod 2 = 0 }", "{ [3] }", "NaN" },
8033 	{ "{ [i] -> [i] : i mod 2 = 0 }", "{ [x] : false }", "NaN" },
8034 };
8035 
8036 /* Perform basic isl_pw_aff_eval tests.
8037  */
test_eval_aff(isl_ctx * ctx)8038 static int test_eval_aff(isl_ctx *ctx)
8039 {
8040 	int i;
8041 
8042 	for (i = 0; i < ARRAY_SIZE(aff_eval_tests); ++i) {
8043 		isl_stat r;
8044 		isl_pw_aff *pa;
8045 		isl_set *set;
8046 		isl_point *pnt;
8047 		isl_val *v;
8048 
8049 		pa = isl_pw_aff_read_from_str(ctx, aff_eval_tests[i].f);
8050 		set = isl_set_read_from_str(ctx, aff_eval_tests[i].p);
8051 		pnt = isl_set_sample_point(set);
8052 		v = isl_pw_aff_eval(pa, pnt);
8053 		r = val_check_equal(v, aff_eval_tests[i].res);
8054 		isl_val_free(v);
8055 		if (r < 0)
8056 			return -1;
8057 	}
8058 	return 0;
8059 }
8060 
8061 /* Perform basic evaluation tests.
8062  */
test_eval(isl_ctx * ctx)8063 static int test_eval(isl_ctx *ctx)
8064 {
8065 	if (test_eval_1(ctx) < 0)
8066 		return -1;
8067 	if (test_eval_2(ctx) < 0)
8068 		return -1;
8069 	if (test_eval_3(ctx) < 0)
8070 		return -1;
8071 	if (test_eval_aff(ctx) < 0)
8072 		return -1;
8073 	return 0;
8074 }
8075 
8076 /* Descriptions of sets that are tested for reparsing after printing.
8077  */
8078 const char *output_tests[] = {
8079 	"{ [1, y] : 0 <= y <= 1; [x, -x] : 0 <= x <= 1 }",
8080 	"{ [x] : 1 = 0 }",
8081 	"{ [x] : false }",
8082 	"{ [x] : x mod 2 = 0 }",
8083 	"{ [x] : x mod 2 = 1 }",
8084 	"{ [x, y] : x mod 2 = 0 and 3*floor(y/2) < x }",
8085 	"{ [y, x] : x mod 2 = 0 and 3*floor(y/2) < x }",
8086 	"{ [x, y] : x mod 2 = 0 and 3*floor(y/2) = x + y }",
8087 	"{ [y, x] : x mod 2 = 0 and 3*floor(y/2) = x + y }",
8088 	"[n] -> { [y, x] : 2*((x + 2y) mod 3) = n }",
8089 	"{ [x, y] : (2*floor(x/3) + 3*floor(y/4)) mod 5 = x }",
8090 };
8091 
8092 /* Check that printing a set and reparsing a set from the printed output
8093  * results in the same set.
8094  */
test_output_set(isl_ctx * ctx)8095 static int test_output_set(isl_ctx *ctx)
8096 {
8097 	int i;
8098 	char *str;
8099 	isl_set *set1, *set2;
8100 	isl_bool equal;
8101 
8102 	for (i = 0; i < ARRAY_SIZE(output_tests); ++i) {
8103 		set1 = isl_set_read_from_str(ctx, output_tests[i]);
8104 		str = isl_set_to_str(set1);
8105 		set2 = isl_set_read_from_str(ctx, str);
8106 		free(str);
8107 		equal = isl_set_is_equal(set1, set2);
8108 		isl_set_free(set1);
8109 		isl_set_free(set2);
8110 		if (equal < 0)
8111 			return -1;
8112 		if (!equal)
8113 			isl_die(ctx, isl_error_unknown,
8114 				"parsed output not the same", return -1);
8115 	}
8116 
8117 	return 0;
8118 }
8119 
8120 /* Check that an isl_multi_aff is printed using a consistent space.
8121  */
test_output_ma(isl_ctx * ctx)8122 static isl_stat test_output_ma(isl_ctx *ctx)
8123 {
8124 	char *str;
8125 	isl_bool equal;
8126 	isl_aff *aff;
8127 	isl_multi_aff *ma, *ma2;
8128 
8129 	ma = isl_multi_aff_read_from_str(ctx, "{ [a, b] -> [a + b] }");
8130 	aff = isl_aff_read_from_str(ctx, "{ [c, d] -> [c + d] }");
8131 	ma = isl_multi_aff_set_aff(ma, 0, aff);
8132 	str = isl_multi_aff_to_str(ma);
8133 	ma2 = isl_multi_aff_read_from_str(ctx, str);
8134 	free(str);
8135 	equal = isl_multi_aff_plain_is_equal(ma, ma2);
8136 	isl_multi_aff_free(ma2);
8137 	isl_multi_aff_free(ma);
8138 
8139 	if (equal < 0)
8140 		return isl_stat_error;
8141 	if (!equal)
8142 		isl_die(ctx, isl_error_unknown, "bad conversion",
8143 			return isl_stat_error);
8144 
8145 	return isl_stat_ok;
8146 }
8147 
8148 /* Check that an isl_multi_pw_aff is printed using a consistent space.
8149  */
test_output_mpa(isl_ctx * ctx)8150 static isl_stat test_output_mpa(isl_ctx *ctx)
8151 {
8152 	char *str;
8153 	isl_bool equal;
8154 	isl_pw_aff *pa;
8155 	isl_multi_pw_aff *mpa, *mpa2;
8156 
8157 	mpa = isl_multi_pw_aff_read_from_str(ctx, "{ [a, b] -> [a + b] }");
8158 	pa = isl_pw_aff_read_from_str(ctx, "{ [c, d] -> [c + d] }");
8159 	mpa = isl_multi_pw_aff_set_pw_aff(mpa, 0, pa);
8160 	str = isl_multi_pw_aff_to_str(mpa);
8161 	mpa2 = isl_multi_pw_aff_read_from_str(ctx, str);
8162 	free(str);
8163 	equal = isl_multi_pw_aff_plain_is_equal(mpa, mpa2);
8164 	isl_multi_pw_aff_free(mpa2);
8165 	isl_multi_pw_aff_free(mpa);
8166 
8167 	if (equal < 0)
8168 		return isl_stat_error;
8169 	if (!equal)
8170 		isl_die(ctx, isl_error_unknown, "bad conversion",
8171 			return isl_stat_error);
8172 
8173 	return isl_stat_ok;
8174 }
8175 
test_output(isl_ctx * ctx)8176 int test_output(isl_ctx *ctx)
8177 {
8178 	char *s;
8179 	const char *str;
8180 	isl_pw_aff *pa;
8181 	isl_printer *p;
8182 	int equal;
8183 
8184 	if (test_output_set(ctx) < 0)
8185 		return -1;
8186 	if (test_output_ma(ctx) < 0)
8187 		return -1;
8188 	if (test_output_mpa(ctx) < 0)
8189 		return -1;
8190 
8191 	str = "[x] -> { [1] : x % 4 <= 2; [2] : x = 3 }";
8192 	pa = isl_pw_aff_read_from_str(ctx, str);
8193 
8194 	p = isl_printer_to_str(ctx);
8195 	p = isl_printer_set_output_format(p, ISL_FORMAT_C);
8196 	p = isl_printer_print_pw_aff(p, pa);
8197 	s = isl_printer_get_str(p);
8198 	isl_printer_free(p);
8199 	isl_pw_aff_free(pa);
8200 	if (!s)
8201 		equal = -1;
8202 	else
8203 		equal = !strcmp(s, "4 * floord(x, 4) + 2 >= x ? 1 : 2");
8204 	free(s);
8205 	if (equal < 0)
8206 		return -1;
8207 	if (!equal)
8208 		isl_die(ctx, isl_error_unknown, "unexpected result", return -1);
8209 
8210 	return 0;
8211 }
8212 
test_sample(isl_ctx * ctx)8213 int test_sample(isl_ctx *ctx)
8214 {
8215 	const char *str;
8216 	isl_basic_set *bset1, *bset2;
8217 	int empty, subset;
8218 
8219 	str = "{ [a, b, c, d, e, f, g, h, i, j, k] : "
8220 	    "3i >= 1073741823b - c - 1073741823e + f and c >= 0 and "
8221 	    "3i >= -1 + 3221225466b + c + d - 3221225466e - f and "
8222 	    "2e >= a - b and 3e <= 2a and 3k <= -a and f <= -1 + a and "
8223 	    "3i <= 4 - a + 4b + 2c - e - 2f and 3k <= -a + c - f and "
8224 	    "3h >= -2 + a and 3g >= -3 - a and 3k >= -2 - a and "
8225 	    "3i >= -2 - a - 2c + 3e + 2f and 3h <= a + c - f and "
8226 	    "3h >= a + 2147483646b + 2c - 2147483646e - 2f and "
8227 	    "3g <= -1 - a and 3i <= 1 + c + d - f and a <= 1073741823 and "
8228 	    "f >= 1 - a + 1073741822b + c + d - 1073741822e and "
8229 	    "3i >= 1 + 2b - 2c + e + 2f + 3g and "
8230 	    "1073741822f <= 1073741822 - a + 1073741821b + 1073741822c +"
8231 		"d - 1073741821e and "
8232 	    "3j <= 3 - a + 3b and 3g <= -2 - 2b + c + d - e - f and "
8233 	    "3j >= 1 - a + b + 2e and "
8234 	    "3f >= -3 + a + 3221225462b + 3c + d - 3221225465e and "
8235 	    "3i <= 4 - a + 4b - e and "
8236 	    "f <= 1073741822 + 1073741822b - 1073741822e and 3h <= a and "
8237 	    "f >= 0 and 2e <= 4 - a + 5b - d and 2e <= a - b + d and "
8238 	    "c <= -1 + a and 3i >= -2 - a + 3e and "
8239 	    "1073741822e <= 1073741823 - a + 1073741822b + c and "
8240 	    "3g >= -4 + 3221225464b + 3c + d - 3221225467e - 3f and "
8241 	    "3i >= -1 + 3221225466b + 3c + d - 3221225466e - 3f and "
8242 	    "1073741823e >= 1 + 1073741823b - d and "
8243 	    "3i >= 1073741823b + c - 1073741823e - f and "
8244 	    "3i >= 1 + 2b + e + 3g }";
8245 	bset1 = isl_basic_set_read_from_str(ctx, str);
8246 	bset2 = isl_basic_set_sample(isl_basic_set_copy(bset1));
8247 	empty = isl_basic_set_is_empty(bset2);
8248 	subset = isl_basic_set_is_subset(bset2, bset1);
8249 	isl_basic_set_free(bset1);
8250 	isl_basic_set_free(bset2);
8251 	if (empty < 0 || subset < 0)
8252 		return -1;
8253 	if (empty)
8254 		isl_die(ctx, isl_error_unknown, "point not found", return -1);
8255 	if (!subset)
8256 		isl_die(ctx, isl_error_unknown, "bad point found", return -1);
8257 
8258 	return 0;
8259 }
8260 
test_fixed_power(isl_ctx * ctx)8261 int test_fixed_power(isl_ctx *ctx)
8262 {
8263 	const char *str;
8264 	isl_map *map;
8265 	isl_val *exp;
8266 	int equal;
8267 
8268 	str = "{ [i] -> [i + 1] }";
8269 	map = isl_map_read_from_str(ctx, str);
8270 	exp = isl_val_int_from_si(ctx, 23);
8271 	map = isl_map_fixed_power_val(map, exp);
8272 	equal = map_check_equal(map, "{ [i] -> [i + 23] }");
8273 	isl_map_free(map);
8274 	if (equal < 0)
8275 		return -1;
8276 
8277 	return 0;
8278 }
8279 
test_slice(isl_ctx * ctx)8280 int test_slice(isl_ctx *ctx)
8281 {
8282 	const char *str;
8283 	isl_map *map;
8284 	int equal;
8285 
8286 	str = "{ [i] -> [j] }";
8287 	map = isl_map_read_from_str(ctx, str);
8288 	map = isl_map_equate(map, isl_dim_in, 0, isl_dim_out, 0);
8289 	equal = map_check_equal(map, "{ [i] -> [i] }");
8290 	isl_map_free(map);
8291 	if (equal < 0)
8292 		return -1;
8293 
8294 	str = "{ [i] -> [j] }";
8295 	map = isl_map_read_from_str(ctx, str);
8296 	map = isl_map_equate(map, isl_dim_in, 0, isl_dim_in, 0);
8297 	equal = map_check_equal(map, "{ [i] -> [j] }");
8298 	isl_map_free(map);
8299 	if (equal < 0)
8300 		return -1;
8301 
8302 	str = "{ [i] -> [j] }";
8303 	map = isl_map_read_from_str(ctx, str);
8304 	map = isl_map_oppose(map, isl_dim_in, 0, isl_dim_out, 0);
8305 	equal = map_check_equal(map, "{ [i] -> [-i] }");
8306 	isl_map_free(map);
8307 	if (equal < 0)
8308 		return -1;
8309 
8310 	str = "{ [i] -> [j] }";
8311 	map = isl_map_read_from_str(ctx, str);
8312 	map = isl_map_oppose(map, isl_dim_in, 0, isl_dim_in, 0);
8313 	equal = map_check_equal(map, "{ [0] -> [j] }");
8314 	isl_map_free(map);
8315 	if (equal < 0)
8316 		return -1;
8317 
8318 	str = "{ [i] -> [j] }";
8319 	map = isl_map_read_from_str(ctx, str);
8320 	map = isl_map_order_gt(map, isl_dim_in, 0, isl_dim_out, 0);
8321 	equal = map_check_equal(map, "{ [i] -> [j] : i > j }");
8322 	isl_map_free(map);
8323 	if (equal < 0)
8324 		return -1;
8325 
8326 	str = "{ [i] -> [j] }";
8327 	map = isl_map_read_from_str(ctx, str);
8328 	map = isl_map_order_gt(map, isl_dim_in, 0, isl_dim_in, 0);
8329 	equal = map_check_equal(map, "{ [i] -> [j] : false }");
8330 	isl_map_free(map);
8331 	if (equal < 0)
8332 		return -1;
8333 
8334 	return 0;
8335 }
8336 
test_eliminate(isl_ctx * ctx)8337 int test_eliminate(isl_ctx *ctx)
8338 {
8339 	const char *str;
8340 	isl_map *map;
8341 	int equal;
8342 
8343 	str = "{ [i] -> [j] : i = 2j }";
8344 	map = isl_map_read_from_str(ctx, str);
8345 	map = isl_map_eliminate(map, isl_dim_out, 0, 1);
8346 	equal = map_check_equal(map, "{ [i] -> [j] : exists a : i = 2a }");
8347 	isl_map_free(map);
8348 	if (equal < 0)
8349 		return -1;
8350 
8351 	return 0;
8352 }
8353 
8354 /* Check basic functionality of isl_map_deltas_map.
8355  */
test_deltas_map(isl_ctx * ctx)8356 static int test_deltas_map(isl_ctx *ctx)
8357 {
8358 	const char *str;
8359 	isl_map *map;
8360 	int equal;
8361 
8362 	str = "{ A[i] -> A[i + 1] }";
8363 	map = isl_map_read_from_str(ctx, str);
8364 	map = isl_map_deltas_map(map);
8365 	equal = map_check_equal(map, "{ [A[i] -> A[i + 1]] -> A[1] }");
8366 	isl_map_free(map);
8367 	if (equal < 0)
8368 		return -1;
8369 
8370 	return 0;
8371 }
8372 
8373 /* Check that isl_set_dim_residue_class detects that the values of j
8374  * in the set below are all odd and that it does not detect any spurious
8375  * strides.
8376  */
test_residue_class(isl_ctx * ctx)8377 static int test_residue_class(isl_ctx *ctx)
8378 {
8379 	const char *str;
8380 	isl_set *set;
8381 	isl_int m, r;
8382 	isl_stat res;
8383 
8384 	str = "{ [i,j] : j = 4 i + 1 and 0 <= i <= 100; "
8385 		"[i,j] : j = 4 i + 3 and 500 <= i <= 600 }";
8386 	set = isl_set_read_from_str(ctx, str);
8387 	isl_int_init(m);
8388 	isl_int_init(r);
8389 	res = isl_set_dim_residue_class(set, 1, &m, &r);
8390 	if (res >= 0 &&
8391 	    (isl_int_cmp_si(m, 2) != 0 || isl_int_cmp_si(r, 1) != 0))
8392 		isl_die(ctx, isl_error_unknown, "incorrect residue class",
8393 			res = isl_stat_error);
8394 	isl_int_clear(r);
8395 	isl_int_clear(m);
8396 	isl_set_free(set);
8397 
8398 	return res;
8399 }
8400 
test_align_parameters_1(isl_ctx * ctx)8401 static int test_align_parameters_1(isl_ctx *ctx)
8402 {
8403 	const char *str;
8404 	isl_space *space;
8405 	isl_multi_aff *ma1, *ma2;
8406 	int equal;
8407 
8408 	str = "{ A[B[] -> C[]] -> D[E[] -> F[]] }";
8409 	ma1 = isl_multi_aff_read_from_str(ctx, str);
8410 
8411 	space = isl_space_params_alloc(ctx, 1);
8412 	space = isl_space_set_dim_name(space, isl_dim_param, 0, "N");
8413 	ma1 = isl_multi_aff_align_params(ma1, space);
8414 
8415 	str = "[N] -> { A[B[] -> C[]] -> D[E[] -> F[]] }";
8416 	ma2 = isl_multi_aff_read_from_str(ctx, str);
8417 
8418 	equal = isl_multi_aff_plain_is_equal(ma1, ma2);
8419 
8420 	isl_multi_aff_free(ma1);
8421 	isl_multi_aff_free(ma2);
8422 
8423 	if (equal < 0)
8424 		return -1;
8425 	if (!equal)
8426 		isl_die(ctx, isl_error_unknown,
8427 			"result not as expected", return -1);
8428 
8429 	return 0;
8430 }
8431 
8432 /* Check the isl_multi_*_from_*_list operation in case inputs
8433  * have unaligned parameters.
8434  * In particular, older versions of isl would simply fail
8435  * (without printing any error message).
8436  */
test_align_parameters_2(isl_ctx * ctx)8437 static isl_stat test_align_parameters_2(isl_ctx *ctx)
8438 {
8439 	isl_space *space;
8440 	isl_map *map;
8441 	isl_aff *aff;
8442 	isl_multi_aff *ma;
8443 
8444 	map = isl_map_read_from_str(ctx, "{ A[] -> M[x] }");
8445 	space = isl_map_get_space(map);
8446 	isl_map_free(map);
8447 
8448 	aff = isl_aff_read_from_str(ctx, "[N] -> { A[] -> [N] }");
8449 	ma = isl_multi_aff_from_aff_list(space, isl_aff_list_from_aff(aff));
8450 	isl_multi_aff_free(ma);
8451 
8452 	if (!ma)
8453 		return isl_stat_error;
8454 	return isl_stat_ok;
8455 }
8456 
8457 /* Perform basic parameter alignment tests.
8458  */
test_align_parameters(isl_ctx * ctx)8459 static int test_align_parameters(isl_ctx *ctx)
8460 {
8461 	if (test_align_parameters_1(ctx) < 0)
8462 		return -1;
8463 	if (test_align_parameters_2(ctx) < 0)
8464 		return -1;
8465 
8466 	return 0;
8467 }
8468 
8469 /* Check that isl_*_drop_unused_params actually drops the unused parameters
8470  * by comparing the result using isl_*_plain_is_equal.
8471  * Note that this assumes that isl_*_plain_is_equal does not consider
8472  * objects that only differ by unused parameters to be equal.
8473  */
test_drop_unused_parameters(isl_ctx * ctx)8474 int test_drop_unused_parameters(isl_ctx *ctx)
8475 {
8476 	const char *str_with, *str_without;
8477 	isl_basic_set *bset1, *bset2;
8478 	isl_set *set1, *set2;
8479 	isl_pw_aff *pwa1, *pwa2;
8480 	int equal;
8481 
8482 	str_with = "[n, m, o] -> { [m] }";
8483 	str_without = "[m] -> { [m] }";
8484 
8485 	bset1 = isl_basic_set_read_from_str(ctx, str_with);
8486 	bset2 = isl_basic_set_read_from_str(ctx, str_without);
8487 	bset1 = isl_basic_set_drop_unused_params(bset1);
8488 	equal = isl_basic_set_plain_is_equal(bset1, bset2);
8489 	isl_basic_set_free(bset1);
8490 	isl_basic_set_free(bset2);
8491 
8492 	if (equal < 0)
8493 		return -1;
8494 	if (!equal)
8495 		isl_die(ctx, isl_error_unknown,
8496 			"result not as expected", return -1);
8497 
8498 	set1 = isl_set_read_from_str(ctx, str_with);
8499 	set2 = isl_set_read_from_str(ctx, str_without);
8500 	set1 = isl_set_drop_unused_params(set1);
8501 	equal = isl_set_plain_is_equal(set1, set2);
8502 	isl_set_free(set1);
8503 	isl_set_free(set2);
8504 
8505 	if (equal < 0)
8506 		return -1;
8507 	if (!equal)
8508 		isl_die(ctx, isl_error_unknown,
8509 			"result not as expected", return -1);
8510 
8511 	pwa1 = isl_pw_aff_read_from_str(ctx, str_with);
8512 	pwa2 = isl_pw_aff_read_from_str(ctx, str_without);
8513 	pwa1 = isl_pw_aff_drop_unused_params(pwa1);
8514 	equal = isl_pw_aff_plain_is_equal(pwa1, pwa2);
8515 	isl_pw_aff_free(pwa1);
8516 	isl_pw_aff_free(pwa2);
8517 
8518 	if (equal < 0)
8519 		return -1;
8520 	if (!equal)
8521 		isl_die(ctx, isl_error_unknown,
8522 			"result not as expected", return -1);
8523 
8524 	return 0;
8525 }
8526 
test_list(isl_ctx * ctx)8527 static int test_list(isl_ctx *ctx)
8528 {
8529 	isl_id *a, *b, *c, *d, *id;
8530 	isl_id_list *list;
8531 	isl_size n;
8532 	int ok;
8533 
8534 	a = isl_id_alloc(ctx, "a", NULL);
8535 	b = isl_id_alloc(ctx, "b", NULL);
8536 	c = isl_id_alloc(ctx, "c", NULL);
8537 	d = isl_id_alloc(ctx, "d", NULL);
8538 
8539 	list = isl_id_list_alloc(ctx, 4);
8540 	list = isl_id_list_add(list, b);
8541 	list = isl_id_list_insert(list, 0, a);
8542 	list = isl_id_list_add(list, c);
8543 	list = isl_id_list_add(list, d);
8544 	list = isl_id_list_drop(list, 1, 1);
8545 
8546 	n = isl_id_list_n_id(list);
8547 	if (n < 0)
8548 		return -1;
8549 	if (n != 3) {
8550 		isl_id_list_free(list);
8551 		isl_die(ctx, isl_error_unknown,
8552 			"unexpected number of elements in list", return -1);
8553 	}
8554 
8555 	id = isl_id_list_get_id(list, 0);
8556 	ok = id == a;
8557 	isl_id_free(id);
8558 	id = isl_id_list_get_id(list, 1);
8559 	ok = ok && id == c;
8560 	isl_id_free(id);
8561 	id = isl_id_list_get_id(list, 2);
8562 	ok = ok && id == d;
8563 	isl_id_free(id);
8564 
8565 	isl_id_list_free(list);
8566 
8567 	if (!ok)
8568 		isl_die(ctx, isl_error_unknown,
8569 			"unexpected elements in list", return -1);
8570 
8571 	return 0;
8572 }
8573 
8574 /* Check the conversion from an isl_multi_aff to an isl_basic_set.
8575  */
test_ma_conversion(isl_ctx * ctx)8576 static isl_stat test_ma_conversion(isl_ctx *ctx)
8577 {
8578 	const char *str;
8579 	isl_bool equal;
8580 	isl_multi_aff *ma;
8581 	isl_basic_set *bset1, *bset2;
8582 
8583 	str = "[N] -> { A[0, N + 1] }";
8584 	ma = isl_multi_aff_read_from_str(ctx, str);
8585 	bset1 = isl_basic_set_read_from_str(ctx, str);
8586 	bset2 = isl_basic_set_from_multi_aff(ma);
8587 	equal = isl_basic_set_is_equal(bset1, bset2);
8588 	isl_basic_set_free(bset1);
8589 	isl_basic_set_free(bset2);
8590 	if (equal < 0)
8591 		return isl_stat_error;
8592 	if (!equal)
8593 		isl_die(ctx, isl_error_unknown, "bad conversion",
8594 			return isl_stat_error);
8595 	return isl_stat_ok;
8596 }
8597 
8598 const char *set_conversion_tests[] = {
8599 	"[N] -> { [i] : N - 1 <= 2 i <= N }",
8600 	"[N] -> { [i] : exists a : i = 4 a and N - 1 <= i <= N }",
8601 	"[N] -> { [i,j] : exists a : i = 4 a and N - 1 <= i, 2j <= N }",
8602 	"[N] -> { [[i]->[j]] : exists a : i = 4 a and N - 1 <= i, 2j <= N }",
8603 	"[N] -> { [3*floor(N/2) + 5*floor(N/3)] }",
8604 	"[a, b] -> { [c, d] : (4*floor((-a + c)/4) = -a + c and "
8605 			"32*floor((-b + d)/32) = -b + d and 5 <= c <= 8 and "
8606 			"-3 + c <= d <= 28 + c) }",
8607 };
8608 
8609 /* Check that converting from isl_set to isl_pw_multi_aff and back
8610  * to isl_set produces the original isl_set.
8611  */
test_set_conversion(isl_ctx * ctx)8612 static int test_set_conversion(isl_ctx *ctx)
8613 {
8614 	int i;
8615 	const char *str;
8616 	isl_set *set1, *set2;
8617 	isl_pw_multi_aff *pma;
8618 	int equal;
8619 
8620 	for (i = 0; i < ARRAY_SIZE(set_conversion_tests); ++i) {
8621 		str = set_conversion_tests[i];
8622 		set1 = isl_set_read_from_str(ctx, str);
8623 		pma = isl_pw_multi_aff_from_set(isl_set_copy(set1));
8624 		set2 = isl_set_from_pw_multi_aff(pma);
8625 		equal = isl_set_is_equal(set1, set2);
8626 		isl_set_free(set1);
8627 		isl_set_free(set2);
8628 
8629 		if (equal < 0)
8630 			return -1;
8631 		if (!equal)
8632 			isl_die(ctx, isl_error_unknown, "bad conversion",
8633 				return -1);
8634 	}
8635 
8636 	return 0;
8637 }
8638 
8639 const char *conversion_tests[] = {
8640 	"{ [a, b, c, d] -> s0[a, b, e, f] : "
8641 	    "exists (e0 = [(a - 2c)/3], e1 = [(-4 + b - 5d)/9], "
8642 	    "e2 = [(-d + f)/9]: 3e0 = a - 2c and 9e1 = -4 + b - 5d and "
8643 	    "9e2 = -d + f and f >= 0 and f <= 8 and 9e >= -5 - 2a and "
8644 	    "9e <= -2 - 2a) }",
8645 	"{ [a, b] -> [c] : exists (e0 = floor((-a - b + c)/5): "
8646 	    "5e0 = -a - b + c and c >= -a and c <= 4 - a) }",
8647 	"{ [a, b] -> [c] : exists d : 18 * d = -3 - a + 2c and 1 <= c <= 3 }",
8648 };
8649 
8650 /* Check that converting from isl_map to isl_pw_multi_aff and back
8651  * to isl_map produces the original isl_map.
8652  */
test_map_conversion(isl_ctx * ctx)8653 static int test_map_conversion(isl_ctx *ctx)
8654 {
8655 	int i;
8656 	isl_map *map1, *map2;
8657 	isl_pw_multi_aff *pma;
8658 	int equal;
8659 
8660 	for (i = 0; i < ARRAY_SIZE(conversion_tests); ++i) {
8661 		map1 = isl_map_read_from_str(ctx, conversion_tests[i]);
8662 		pma = isl_pw_multi_aff_from_map(isl_map_copy(map1));
8663 		map2 = isl_map_from_pw_multi_aff(pma);
8664 		equal = isl_map_is_equal(map1, map2);
8665 		isl_map_free(map1);
8666 		isl_map_free(map2);
8667 
8668 		if (equal < 0)
8669 			return -1;
8670 		if (!equal)
8671 			isl_die(ctx, isl_error_unknown, "bad conversion",
8672 				return -1);
8673 	}
8674 
8675 	return 0;
8676 }
8677 
8678 /* Descriptions of isl_pw_multi_aff objects for testing conversion
8679  * to isl_multi_pw_aff and back.
8680  */
8681 const char *mpa_conversion_tests[] = {
8682 	"{ [x] -> A[x] }",
8683 	"{ [x] -> A[x] : x >= 0 }",
8684 	"{ [x] -> A[x] : x >= 0; [x] -> A[-x] : x < 0 }",
8685 	"{ [x] -> A[x, x + 1] }",
8686 	"{ [x] -> A[] }",
8687 	"{ [x] -> A[] : x >= 0 }",
8688 };
8689 
8690 /* Check that conversion from isl_pw_multi_aff to isl_multi_pw_aff and
8691  * back to isl_pw_multi_aff preserves the original meaning.
8692  */
test_mpa_conversion(isl_ctx * ctx)8693 static int test_mpa_conversion(isl_ctx *ctx)
8694 {
8695 	int i;
8696 	isl_pw_multi_aff *pma1, *pma2;
8697 	isl_multi_pw_aff *mpa;
8698 	int equal;
8699 
8700 	for (i = 0; i < ARRAY_SIZE(mpa_conversion_tests); ++i) {
8701 		const char *str;
8702 		str = mpa_conversion_tests[i];
8703 		pma1 = isl_pw_multi_aff_read_from_str(ctx, str);
8704 		pma2 = isl_pw_multi_aff_copy(pma1);
8705 		mpa = isl_multi_pw_aff_from_pw_multi_aff(pma1);
8706 		pma1 = isl_pw_multi_aff_from_multi_pw_aff(mpa);
8707 		equal = isl_pw_multi_aff_plain_is_equal(pma1, pma2);
8708 		isl_pw_multi_aff_free(pma1);
8709 		isl_pw_multi_aff_free(pma2);
8710 
8711 		if (equal < 0)
8712 			return -1;
8713 		if (!equal)
8714 			isl_die(ctx, isl_error_unknown, "bad conversion",
8715 				return -1);
8716 	}
8717 
8718 	return 0;
8719 }
8720 
8721 /* Descriptions of union maps that should be convertible
8722  * to an isl_multi_union_pw_aff.
8723  */
8724 const char *umap_mupa_conversion_tests[] = {
8725 	"{ [a, b, c, d] -> s0[a, b, e, f] : "
8726 	    "exists (e0 = [(a - 2c)/3], e1 = [(-4 + b - 5d)/9], "
8727 	    "e2 = [(-d + f)/9]: 3e0 = a - 2c and 9e1 = -4 + b - 5d and "
8728 	    "9e2 = -d + f and f >= 0 and f <= 8 and 9e >= -5 - 2a and "
8729 	    "9e <= -2 - 2a) }",
8730 	"{ [a, b] -> [c] : exists (e0 = floor((-a - b + c)/5): "
8731 	    "5e0 = -a - b + c and c >= -a and c <= 4 - a) }",
8732 	"{ [a, b] -> [c] : exists d : 18 * d = -3 - a + 2c and 1 <= c <= 3 }",
8733 	"{ A[] -> B[0]; C[] -> B[1] }",
8734 	"{ A[] -> B[]; C[] -> B[] }",
8735 };
8736 
8737 /* Check that converting from isl_union_map to isl_multi_union_pw_aff and back
8738  * to isl_union_map produces the original isl_union_map.
8739  */
test_union_map_mupa_conversion(isl_ctx * ctx)8740 static int test_union_map_mupa_conversion(isl_ctx *ctx)
8741 {
8742 	int i;
8743 	isl_union_map *umap1, *umap2;
8744 	isl_multi_union_pw_aff *mupa;
8745 	int equal;
8746 
8747 	for (i = 0; i < ARRAY_SIZE(umap_mupa_conversion_tests); ++i) {
8748 		const char *str;
8749 		str = umap_mupa_conversion_tests[i];
8750 		umap1 = isl_union_map_read_from_str(ctx, str);
8751 		umap2 = isl_union_map_copy(umap1);
8752 		mupa = isl_multi_union_pw_aff_from_union_map(umap2);
8753 		umap2 = isl_union_map_from_multi_union_pw_aff(mupa);
8754 		equal = isl_union_map_is_equal(umap1, umap2);
8755 		isl_union_map_free(umap1);
8756 		isl_union_map_free(umap2);
8757 
8758 		if (equal < 0)
8759 			return -1;
8760 		if (!equal)
8761 			isl_die(ctx, isl_error_unknown, "bad conversion",
8762 				return -1);
8763 	}
8764 
8765 	return 0;
8766 }
8767 
test_conversion(isl_ctx * ctx)8768 static int test_conversion(isl_ctx *ctx)
8769 {
8770 	if (test_ma_conversion(ctx) < 0)
8771 		return -1;
8772 	if (test_set_conversion(ctx) < 0)
8773 		return -1;
8774 	if (test_map_conversion(ctx) < 0)
8775 		return -1;
8776 	if (test_mpa_conversion(ctx) < 0)
8777 		return -1;
8778 	if (test_union_map_mupa_conversion(ctx) < 0)
8779 		return -1;
8780 	return 0;
8781 }
8782 
8783 /* Check that isl_basic_map_curry does not modify input.
8784  */
test_curry(isl_ctx * ctx)8785 static int test_curry(isl_ctx *ctx)
8786 {
8787 	const char *str;
8788 	isl_basic_map *bmap1, *bmap2;
8789 	int equal;
8790 
8791 	str = "{ [A[] -> B[]] -> C[] }";
8792 	bmap1 = isl_basic_map_read_from_str(ctx, str);
8793 	bmap2 = isl_basic_map_curry(isl_basic_map_copy(bmap1));
8794 	equal = isl_basic_map_is_equal(bmap1, bmap2);
8795 	isl_basic_map_free(bmap1);
8796 	isl_basic_map_free(bmap2);
8797 
8798 	if (equal < 0)
8799 		return -1;
8800 	if (equal)
8801 		isl_die(ctx, isl_error_unknown,
8802 			"curried map should not be equal to original",
8803 			return -1);
8804 
8805 	return 0;
8806 }
8807 
8808 struct {
8809 	const char *set;
8810 	const char *ma;
8811 	const char *res;
8812 } preimage_tests[] = {
8813 	{ "{ B[i,j] : 0 <= i < 10 and 0 <= j < 100 }",
8814 	  "{ A[j,i] -> B[i,j] }",
8815 	  "{ A[j,i] : 0 <= i < 10 and 0 <= j < 100 }" },
8816 	{ "{ rat: B[i,j] : 0 <= i, j and 3 i + 5 j <= 100 }",
8817 	  "{ A[a,b] -> B[a/2,b/6] }",
8818 	  "{ rat: A[a,b] : 0 <= a, b and 9 a + 5 b <= 600 }" },
8819 	{ "{ B[i,j] : 0 <= i, j and 3 i + 5 j <= 100 }",
8820 	  "{ A[a,b] -> B[a/2,b/6] }",
8821 	  "{ A[a,b] : 0 <= a, b and 9 a + 5 b <= 600 and "
8822 		    "exists i,j : a = 2 i and b = 6 j }" },
8823 	{ "[n] -> { S[i] : 0 <= i <= 100 }", "[n] -> { S[n] }",
8824 	  "[n] -> { : 0 <= n <= 100 }" },
8825 	{ "{ B[i] : 0 <= i < 100 and exists a : i = 4 a }",
8826 	  "{ A[a] -> B[2a] }",
8827 	  "{ A[a] : 0 <= a < 50 and exists b : a = 2 b }" },
8828 	{ "{ B[i] : 0 <= i < 100 and exists a : i = 4 a }",
8829 	  "{ A[a] -> B[([a/2])] }",
8830 	  "{ A[a] : 0 <= a < 200 and exists b : [a/2] = 4 b }" },
8831 	{ "{ B[i,j,k] : 0 <= i,j,k <= 100 }",
8832 	  "{ A[a] -> B[a,a,a/3] }",
8833 	  "{ A[a] : 0 <= a <= 100 and exists b : a = 3 b }" },
8834 	{ "{ B[i,j] : j = [(i)/2] } ", "{ A[i,j] -> B[i/3,j] }",
8835 	  "{ A[i,j] : j = [(i)/6] and exists a : i = 3 a }" },
8836 };
8837 
test_preimage_basic_set(isl_ctx * ctx)8838 static int test_preimage_basic_set(isl_ctx *ctx)
8839 {
8840 	int i;
8841 	isl_basic_set *bset1, *bset2;
8842 	isl_multi_aff *ma;
8843 	int equal;
8844 
8845 	for (i = 0; i < ARRAY_SIZE(preimage_tests); ++i) {
8846 		bset1 = isl_basic_set_read_from_str(ctx, preimage_tests[i].set);
8847 		ma = isl_multi_aff_read_from_str(ctx, preimage_tests[i].ma);
8848 		bset2 = isl_basic_set_read_from_str(ctx, preimage_tests[i].res);
8849 		bset1 = isl_basic_set_preimage_multi_aff(bset1, ma);
8850 		equal = isl_basic_set_is_equal(bset1, bset2);
8851 		isl_basic_set_free(bset1);
8852 		isl_basic_set_free(bset2);
8853 		if (equal < 0)
8854 			return -1;
8855 		if (!equal)
8856 			isl_die(ctx, isl_error_unknown, "bad preimage",
8857 				return -1);
8858 	}
8859 
8860 	return 0;
8861 }
8862 
8863 struct {
8864 	const char *map;
8865 	const char *ma;
8866 	const char *res;
8867 } preimage_domain_tests[] = {
8868 	{ "{ B[i,j] -> C[2i + 3j] : 0 <= i < 10 and 0 <= j < 100 }",
8869 	  "{ A[j,i] -> B[i,j] }",
8870 	  "{ A[j,i] -> C[2i + 3j] : 0 <= i < 10 and 0 <= j < 100 }" },
8871 	{ "{ B[i] -> C[i]; D[i] -> E[i] }",
8872 	  "{ A[i] -> B[i + 1] }",
8873 	  "{ A[i] -> C[i + 1] }" },
8874 	{ "{ B[i] -> C[i]; B[i] -> E[i] }",
8875 	  "{ A[i] -> B[i + 1] }",
8876 	  "{ A[i] -> C[i + 1]; A[i] -> E[i + 1] }" },
8877 	{ "{ B[i] -> C[([i/2])] }",
8878 	  "{ A[i] -> B[2i] }",
8879 	  "{ A[i] -> C[i] }" },
8880 	{ "{ B[i,j] -> C[([i/2]), ([(i+j)/3])] }",
8881 	  "{ A[i] -> B[([i/5]), ([i/7])] }",
8882 	  "{ A[i] -> C[([([i/5])/2]), ([(([i/5])+([i/7]))/3])] }" },
8883 	{ "[N] -> { B[i] -> C[([N/2]), i, ([N/3])] }",
8884 	  "[N] -> { A[] -> B[([N/5])] }",
8885 	  "[N] -> { A[] -> C[([N/2]), ([N/5]), ([N/3])] }" },
8886 	{ "{ B[i] -> C[i] : exists a : i = 5 a }",
8887 	  "{ A[i] -> B[2i] }",
8888 	  "{ A[i] -> C[2i] : exists a : 2i = 5 a }" },
8889 	{ "{ B[i] -> C[i] : exists a : i = 2 a; "
8890 	    "B[i] -> D[i] : exists a : i = 2 a + 1 }",
8891 	  "{ A[i] -> B[2i] }",
8892 	  "{ A[i] -> C[2i] }" },
8893 	{ "{ A[i] -> B[i] }", "{ C[i] -> A[(i + floor(i/3))/2] }",
8894 	  "{ C[i] -> B[j] : 2j = i + floor(i/3) }" },
8895 };
8896 
test_preimage_union_map(isl_ctx * ctx)8897 static int test_preimage_union_map(isl_ctx *ctx)
8898 {
8899 	int i;
8900 	isl_union_map *umap1, *umap2;
8901 	isl_multi_aff *ma;
8902 	int equal;
8903 
8904 	for (i = 0; i < ARRAY_SIZE(preimage_domain_tests); ++i) {
8905 		umap1 = isl_union_map_read_from_str(ctx,
8906 						preimage_domain_tests[i].map);
8907 		ma = isl_multi_aff_read_from_str(ctx,
8908 						preimage_domain_tests[i].ma);
8909 		umap2 = isl_union_map_read_from_str(ctx,
8910 						preimage_domain_tests[i].res);
8911 		umap1 = isl_union_map_preimage_domain_multi_aff(umap1, ma);
8912 		equal = isl_union_map_is_equal(umap1, umap2);
8913 		isl_union_map_free(umap1);
8914 		isl_union_map_free(umap2);
8915 		if (equal < 0)
8916 			return -1;
8917 		if (!equal)
8918 			isl_die(ctx, isl_error_unknown, "bad preimage",
8919 				return -1);
8920 	}
8921 
8922 	return 0;
8923 }
8924 
test_preimage(isl_ctx * ctx)8925 static int test_preimage(isl_ctx *ctx)
8926 {
8927 	if (test_preimage_basic_set(ctx) < 0)
8928 		return -1;
8929 	if (test_preimage_union_map(ctx) < 0)
8930 		return -1;
8931 
8932 	return 0;
8933 }
8934 
8935 struct {
8936 	const char *ma1;
8937 	const char *ma;
8938 	const char *res;
8939 } pullback_tests[] = {
8940 	{ "{ B[i,j] -> C[i + 2j] }" , "{ A[a,b] -> B[b,a] }",
8941 	  "{ A[a,b] -> C[b + 2a] }" },
8942 	{ "{ B[i] -> C[2i] }", "{ A[a] -> B[(a)/2] }", "{ A[a] -> C[a] }" },
8943 	{ "{ B[i] -> C[(i)/2] }", "{ A[a] -> B[2a] }", "{ A[a] -> C[a] }" },
8944 	{ "{ B[i] -> C[(i)/2] }", "{ A[a] -> B[(a)/3] }",
8945 	  "{ A[a] -> C[(a)/6] }" },
8946 	{ "{ B[i] -> C[2i] }", "{ A[a] -> B[5a] }", "{ A[a] -> C[10a] }" },
8947 	{ "{ B[i] -> C[2i] }", "{ A[a] -> B[(a)/3] }",
8948 	  "{ A[a] -> C[(2a)/3] }" },
8949 	{ "{ B[i,j] -> C[i + j] }", "{ A[a] -> B[a,a] }", "{ A[a] -> C[2a] }"},
8950 	{ "{ B[a] -> C[a,a] }", "{ A[i,j] -> B[i + j] }",
8951 	  "{ A[i,j] -> C[i + j, i + j] }"},
8952 	{ "{ B[i] -> C[([i/2])] }", "{ B[5] }", "{ C[2] }" },
8953 	{ "[n] -> { B[i,j] -> C[([i/2]) + 2j] }",
8954 	  "[n] -> { B[n,[n/3]] }", "[n] -> { C[([n/2]) + 2*[n/3]] }", },
8955 	{ "{ [i, j] -> [floor((i)/4) + floor((2*i+j)/5)] }",
8956 	  "{ [i, j] -> [floor((i)/3), j] }",
8957 	  "{ [i, j] -> [(floor((i)/12) + floor((j + 2*floor((i)/3))/5))] }" },
8958 };
8959 
test_pullback(isl_ctx * ctx)8960 static int test_pullback(isl_ctx *ctx)
8961 {
8962 	int i;
8963 	isl_multi_aff *ma1, *ma2;
8964 	isl_multi_aff *ma;
8965 	int equal;
8966 
8967 	for (i = 0; i < ARRAY_SIZE(pullback_tests); ++i) {
8968 		ma1 = isl_multi_aff_read_from_str(ctx, pullback_tests[i].ma1);
8969 		ma = isl_multi_aff_read_from_str(ctx, pullback_tests[i].ma);
8970 		ma2 = isl_multi_aff_read_from_str(ctx, pullback_tests[i].res);
8971 		ma1 = isl_multi_aff_pullback_multi_aff(ma1, ma);
8972 		equal = isl_multi_aff_plain_is_equal(ma1, ma2);
8973 		isl_multi_aff_free(ma1);
8974 		isl_multi_aff_free(ma2);
8975 		if (equal < 0)
8976 			return -1;
8977 		if (!equal)
8978 			isl_die(ctx, isl_error_unknown, "bad pullback",
8979 				return -1);
8980 	}
8981 
8982 	return 0;
8983 }
8984 
8985 /* Check that negation is printed correctly and that equal expressions
8986  * are correctly identified.
8987  */
test_ast(isl_ctx * ctx)8988 static int test_ast(isl_ctx *ctx)
8989 {
8990 	isl_ast_expr *expr, *expr1, *expr2, *expr3;
8991 	char *str;
8992 	int ok, equal;
8993 
8994 	expr1 = isl_ast_expr_from_id(isl_id_alloc(ctx, "A", NULL));
8995 	expr2 = isl_ast_expr_from_id(isl_id_alloc(ctx, "B", NULL));
8996 	expr = isl_ast_expr_add(expr1, expr2);
8997 	expr2 = isl_ast_expr_copy(expr);
8998 	expr = isl_ast_expr_neg(expr);
8999 	expr2 = isl_ast_expr_neg(expr2);
9000 	equal = isl_ast_expr_is_equal(expr, expr2);
9001 	str = isl_ast_expr_to_C_str(expr);
9002 	ok = str ? !strcmp(str, "-(A + B)") : -1;
9003 	free(str);
9004 	isl_ast_expr_free(expr);
9005 	isl_ast_expr_free(expr2);
9006 
9007 	if (ok < 0 || equal < 0)
9008 		return -1;
9009 	if (!equal)
9010 		isl_die(ctx, isl_error_unknown,
9011 			"equal expressions not considered equal", return -1);
9012 	if (!ok)
9013 		isl_die(ctx, isl_error_unknown,
9014 			"isl_ast_expr printed incorrectly", return -1);
9015 
9016 	expr1 = isl_ast_expr_from_id(isl_id_alloc(ctx, "A", NULL));
9017 	expr2 = isl_ast_expr_from_id(isl_id_alloc(ctx, "B", NULL));
9018 	expr = isl_ast_expr_add(expr1, expr2);
9019 	expr3 = isl_ast_expr_from_id(isl_id_alloc(ctx, "C", NULL));
9020 	expr = isl_ast_expr_sub(expr3, expr);
9021 	str = isl_ast_expr_to_C_str(expr);
9022 	ok = str ? !strcmp(str, "C - (A + B)") : -1;
9023 	free(str);
9024 	isl_ast_expr_free(expr);
9025 
9026 	if (ok < 0)
9027 		return -1;
9028 	if (!ok)
9029 		isl_die(ctx, isl_error_unknown,
9030 			"isl_ast_expr printed incorrectly", return -1);
9031 
9032 	return 0;
9033 }
9034 
9035 /* Check that isl_ast_build_expr_from_set returns a valid expression
9036  * for an empty set.  Note that isl_ast_build_expr_from_set getting
9037  * called on an empty set probably indicates a bug in the caller.
9038  */
test_ast_build(isl_ctx * ctx)9039 static int test_ast_build(isl_ctx *ctx)
9040 {
9041 	isl_set *set;
9042 	isl_ast_build *build;
9043 	isl_ast_expr *expr;
9044 
9045 	set = isl_set_universe(isl_space_params_alloc(ctx, 0));
9046 	build = isl_ast_build_from_context(set);
9047 
9048 	set = isl_set_empty(isl_space_params_alloc(ctx, 0));
9049 	expr = isl_ast_build_expr_from_set(build, set);
9050 
9051 	isl_ast_expr_free(expr);
9052 	isl_ast_build_free(build);
9053 
9054 	if (!expr)
9055 		return -1;
9056 
9057 	return 0;
9058 }
9059 
9060 /* Internal data structure for before_for and after_for callbacks.
9061  *
9062  * depth is the current depth
9063  * before is the number of times before_for has been called
9064  * after is the number of times after_for has been called
9065  */
9066 struct isl_test_codegen_data {
9067 	int depth;
9068 	int before;
9069 	int after;
9070 };
9071 
9072 /* This function is called before each for loop in the AST generated
9073  * from test_ast_gen1.
9074  *
9075  * Increment the number of calls and the depth.
9076  * Check that the space returned by isl_ast_build_get_schedule_space
9077  * matches the target space of the schedule returned by
9078  * isl_ast_build_get_schedule.
9079  * Return an isl_id that is checked by the corresponding call
9080  * to after_for.
9081  */
before_for(__isl_keep isl_ast_build * build,void * user)9082 static __isl_give isl_id *before_for(__isl_keep isl_ast_build *build,
9083 	void *user)
9084 {
9085 	struct isl_test_codegen_data *data = user;
9086 	isl_ctx *ctx;
9087 	isl_space *space;
9088 	isl_union_map *schedule;
9089 	isl_union_set *uset;
9090 	isl_set *set;
9091 	isl_bool empty;
9092 	isl_size n;
9093 	char name[] = "d0";
9094 
9095 	ctx = isl_ast_build_get_ctx(build);
9096 
9097 	if (data->before >= 3)
9098 		isl_die(ctx, isl_error_unknown,
9099 			"unexpected number of for nodes", return NULL);
9100 	if (data->depth >= 2)
9101 		isl_die(ctx, isl_error_unknown,
9102 			"unexpected depth", return NULL);
9103 
9104 	snprintf(name, sizeof(name), "d%d", data->depth);
9105 	data->before++;
9106 	data->depth++;
9107 
9108 	schedule = isl_ast_build_get_schedule(build);
9109 	uset = isl_union_map_range(schedule);
9110 	n = isl_union_set_n_set(uset);
9111 	if (n != 1) {
9112 		isl_union_set_free(uset);
9113 		if (n < 0)
9114 			return NULL;
9115 		isl_die(ctx, isl_error_unknown,
9116 			"expecting single range space", return NULL);
9117 	}
9118 
9119 	space = isl_ast_build_get_schedule_space(build);
9120 	set = isl_union_set_extract_set(uset, space);
9121 	isl_union_set_free(uset);
9122 	empty = isl_set_is_empty(set);
9123 	isl_set_free(set);
9124 
9125 	if (empty < 0)
9126 		return NULL;
9127 	if (empty)
9128 		isl_die(ctx, isl_error_unknown,
9129 			"spaces don't match", return NULL);
9130 
9131 	return isl_id_alloc(ctx, name, NULL);
9132 }
9133 
9134 /* This function is called after each for loop in the AST generated
9135  * from test_ast_gen1.
9136  *
9137  * Increment the number of calls and decrement the depth.
9138  * Check that the annotation attached to the node matches
9139  * the isl_id returned by the corresponding call to before_for.
9140  */
after_for(__isl_take isl_ast_node * node,__isl_keep isl_ast_build * build,void * user)9141 static __isl_give isl_ast_node *after_for(__isl_take isl_ast_node *node,
9142 	__isl_keep isl_ast_build *build, void *user)
9143 {
9144 	struct isl_test_codegen_data *data = user;
9145 	isl_id *id;
9146 	const char *name;
9147 	int valid;
9148 
9149 	data->after++;
9150 	data->depth--;
9151 
9152 	if (data->after > data->before)
9153 		isl_die(isl_ast_node_get_ctx(node), isl_error_unknown,
9154 			"mismatch in number of for nodes",
9155 			return isl_ast_node_free(node));
9156 
9157 	id = isl_ast_node_get_annotation(node);
9158 	if (!id)
9159 		isl_die(isl_ast_node_get_ctx(node), isl_error_unknown,
9160 			"missing annotation", return isl_ast_node_free(node));
9161 
9162 	name = isl_id_get_name(id);
9163 	valid = name && atoi(name + 1) == data->depth;
9164 	isl_id_free(id);
9165 
9166 	if (!valid)
9167 		isl_die(isl_ast_node_get_ctx(node), isl_error_unknown,
9168 			"wrong annotation", return isl_ast_node_free(node));
9169 
9170 	return node;
9171 }
9172 
9173 /* Check that the before_each_for and after_each_for callbacks
9174  * are called for each for loop in the generated code,
9175  * that they are called in the right order and that the isl_id
9176  * returned from the before_each_for callback is attached to
9177  * the isl_ast_node passed to the corresponding after_each_for call.
9178  */
test_ast_gen1(isl_ctx * ctx)9179 static int test_ast_gen1(isl_ctx *ctx)
9180 {
9181 	const char *str;
9182 	isl_set *set;
9183 	isl_union_map *schedule;
9184 	isl_ast_build *build;
9185 	isl_ast_node *tree;
9186 	struct isl_test_codegen_data data;
9187 
9188 	str = "[N] -> { : N >= 10 }";
9189 	set = isl_set_read_from_str(ctx, str);
9190 	str = "[N] -> { A[i,j] -> S[8,i,3,j] : 0 <= i,j <= N; "
9191 		    "B[i,j] -> S[8,j,9,i] : 0 <= i,j <= N }";
9192 	schedule = isl_union_map_read_from_str(ctx, str);
9193 
9194 	data.before = 0;
9195 	data.after = 0;
9196 	data.depth = 0;
9197 	build = isl_ast_build_from_context(set);
9198 	build = isl_ast_build_set_before_each_for(build,
9199 			&before_for, &data);
9200 	build = isl_ast_build_set_after_each_for(build,
9201 			&after_for, &data);
9202 	tree = isl_ast_build_node_from_schedule_map(build, schedule);
9203 	isl_ast_build_free(build);
9204 	if (!tree)
9205 		return -1;
9206 
9207 	isl_ast_node_free(tree);
9208 
9209 	if (data.before != 3 || data.after != 3)
9210 		isl_die(ctx, isl_error_unknown,
9211 			"unexpected number of for nodes", return -1);
9212 
9213 	return 0;
9214 }
9215 
9216 /* Check that the AST generator handles domains that are integrally disjoint
9217  * but not rationally disjoint.
9218  */
test_ast_gen2(isl_ctx * ctx)9219 static int test_ast_gen2(isl_ctx *ctx)
9220 {
9221 	const char *str;
9222 	isl_set *set;
9223 	isl_union_map *schedule;
9224 	isl_union_map *options;
9225 	isl_ast_build *build;
9226 	isl_ast_node *tree;
9227 
9228 	str = "{ A[i,j] -> [i,j] : 0 <= i,j <= 1 }";
9229 	schedule = isl_union_map_read_from_str(ctx, str);
9230 	set = isl_set_universe(isl_space_params_alloc(ctx, 0));
9231 	build = isl_ast_build_from_context(set);
9232 
9233 	str = "{ [i,j] -> atomic[1] : i + j = 1; [i,j] -> unroll[1] : i = j }";
9234 	options = isl_union_map_read_from_str(ctx, str);
9235 	build = isl_ast_build_set_options(build, options);
9236 	tree = isl_ast_build_node_from_schedule_map(build, schedule);
9237 	isl_ast_build_free(build);
9238 	if (!tree)
9239 		return -1;
9240 	isl_ast_node_free(tree);
9241 
9242 	return 0;
9243 }
9244 
9245 /* Increment *user on each call.
9246  */
count_domains(__isl_take isl_ast_node * node,__isl_keep isl_ast_build * build,void * user)9247 static __isl_give isl_ast_node *count_domains(__isl_take isl_ast_node *node,
9248 	__isl_keep isl_ast_build *build, void *user)
9249 {
9250 	int *n = user;
9251 
9252 	(*n)++;
9253 
9254 	return node;
9255 }
9256 
9257 /* Test that unrolling tries to minimize the number of instances.
9258  * In particular, for the schedule given below, make sure it generates
9259  * 3 nodes (rather than 101).
9260  */
test_ast_gen3(isl_ctx * ctx)9261 static int test_ast_gen3(isl_ctx *ctx)
9262 {
9263 	const char *str;
9264 	isl_set *set;
9265 	isl_union_map *schedule;
9266 	isl_union_map *options;
9267 	isl_ast_build *build;
9268 	isl_ast_node *tree;
9269 	int n_domain = 0;
9270 
9271 	str = "[n] -> { A[i] -> [i] : 0 <= i <= 100 and n <= i <= n + 2 }";
9272 	schedule = isl_union_map_read_from_str(ctx, str);
9273 	set = isl_set_universe(isl_space_params_alloc(ctx, 0));
9274 
9275 	str = "{ [i] -> unroll[0] }";
9276 	options = isl_union_map_read_from_str(ctx, str);
9277 
9278 	build = isl_ast_build_from_context(set);
9279 	build = isl_ast_build_set_options(build, options);
9280 	build = isl_ast_build_set_at_each_domain(build,
9281 			&count_domains, &n_domain);
9282 	tree = isl_ast_build_node_from_schedule_map(build, schedule);
9283 	isl_ast_build_free(build);
9284 	if (!tree)
9285 		return -1;
9286 
9287 	isl_ast_node_free(tree);
9288 
9289 	if (n_domain != 3)
9290 		isl_die(ctx, isl_error_unknown,
9291 			"unexpected number of for nodes", return -1);
9292 
9293 	return 0;
9294 }
9295 
9296 /* Check that if the ast_build_exploit_nested_bounds options is set,
9297  * we do not get an outer if node in the generated AST,
9298  * while we do get such an outer if node if the options is not set.
9299  */
test_ast_gen4(isl_ctx * ctx)9300 static int test_ast_gen4(isl_ctx *ctx)
9301 {
9302 	const char *str;
9303 	isl_set *set;
9304 	isl_union_map *schedule;
9305 	isl_ast_build *build;
9306 	isl_ast_node *tree;
9307 	enum isl_ast_node_type type;
9308 	int enb;
9309 
9310 	enb = isl_options_get_ast_build_exploit_nested_bounds(ctx);
9311 	str = "[N,M] -> { A[i,j] -> [i,j] : 0 <= i <= N and 0 <= j <= M }";
9312 
9313 	isl_options_set_ast_build_exploit_nested_bounds(ctx, 1);
9314 
9315 	schedule = isl_union_map_read_from_str(ctx, str);
9316 	set = isl_set_universe(isl_space_params_alloc(ctx, 0));
9317 	build = isl_ast_build_from_context(set);
9318 	tree = isl_ast_build_node_from_schedule_map(build, schedule);
9319 	isl_ast_build_free(build);
9320 	if (!tree)
9321 		return -1;
9322 
9323 	type = isl_ast_node_get_type(tree);
9324 	isl_ast_node_free(tree);
9325 
9326 	if (type == isl_ast_node_if)
9327 		isl_die(ctx, isl_error_unknown,
9328 			"not expecting if node", return -1);
9329 
9330 	isl_options_set_ast_build_exploit_nested_bounds(ctx, 0);
9331 
9332 	schedule = isl_union_map_read_from_str(ctx, str);
9333 	set = isl_set_universe(isl_space_params_alloc(ctx, 0));
9334 	build = isl_ast_build_from_context(set);
9335 	tree = isl_ast_build_node_from_schedule_map(build, schedule);
9336 	isl_ast_build_free(build);
9337 	if (!tree)
9338 		return -1;
9339 
9340 	type = isl_ast_node_get_type(tree);
9341 	isl_ast_node_free(tree);
9342 
9343 	if (type != isl_ast_node_if)
9344 		isl_die(ctx, isl_error_unknown,
9345 			"expecting if node", return -1);
9346 
9347 	isl_options_set_ast_build_exploit_nested_bounds(ctx, enb);
9348 
9349 	return 0;
9350 }
9351 
9352 /* This function is called for each leaf in the AST generated
9353  * from test_ast_gen5.
9354  *
9355  * We finalize the AST generation by extending the outer schedule
9356  * with a zero-dimensional schedule.  If this results in any for loops,
9357  * then this means that we did not pass along enough information
9358  * about the outer schedule to the inner AST generation.
9359  */
create_leaf(__isl_take isl_ast_build * build,void * user)9360 static __isl_give isl_ast_node *create_leaf(__isl_take isl_ast_build *build,
9361 	void *user)
9362 {
9363 	isl_union_map *schedule, *extra;
9364 	isl_ast_node *tree;
9365 
9366 	schedule = isl_ast_build_get_schedule(build);
9367 	extra = isl_union_map_copy(schedule);
9368 	extra = isl_union_map_from_domain(isl_union_map_domain(extra));
9369 	schedule = isl_union_map_range_product(schedule, extra);
9370 	tree = isl_ast_build_node_from_schedule_map(build, schedule);
9371 	isl_ast_build_free(build);
9372 
9373 	if (!tree)
9374 		return NULL;
9375 
9376 	if (isl_ast_node_get_type(tree) == isl_ast_node_for)
9377 		isl_die(isl_ast_node_get_ctx(tree), isl_error_unknown,
9378 			"code should not contain any for loop",
9379 			return isl_ast_node_free(tree));
9380 
9381 	return tree;
9382 }
9383 
9384 /* Check that we do not lose any information when going back and
9385  * forth between internal and external schedule.
9386  *
9387  * In particular, we create an AST where we unroll the only
9388  * non-constant dimension in the schedule.  We therefore do
9389  * not expect any for loops in the AST.  However, older versions
9390  * of isl would not pass along enough information about the outer
9391  * schedule when performing an inner code generation from a create_leaf
9392  * callback, resulting in the inner code generation producing a for loop.
9393  */
test_ast_gen5(isl_ctx * ctx)9394 static int test_ast_gen5(isl_ctx *ctx)
9395 {
9396 	const char *str;
9397 	isl_set *set;
9398 	isl_union_map *schedule, *options;
9399 	isl_ast_build *build;
9400 	isl_ast_node *tree;
9401 
9402 	str = "{ A[] -> [1, 1, 2]; B[i] -> [1, i, 0] : i >= 1 and i <= 2 }";
9403 	schedule = isl_union_map_read_from_str(ctx, str);
9404 
9405 	str = "{ [a, b, c] -> unroll[1] : exists (e0 = [(a)/4]: "
9406 				"4e0 >= -1 + a - b and 4e0 <= -2 + a + b) }";
9407 	options = isl_union_map_read_from_str(ctx, str);
9408 
9409 	set = isl_set_universe(isl_space_params_alloc(ctx, 0));
9410 	build = isl_ast_build_from_context(set);
9411 	build = isl_ast_build_set_options(build, options);
9412         build = isl_ast_build_set_create_leaf(build, &create_leaf, NULL);
9413 	tree = isl_ast_build_node_from_schedule_map(build, schedule);
9414 	isl_ast_build_free(build);
9415 	isl_ast_node_free(tree);
9416 	if (!tree)
9417 		return -1;
9418 
9419 	return 0;
9420 }
9421 
9422 /* Check that the expression
9423  *
9424  *	[n] -> { [n/2] : n <= 0 and n % 2 = 0; [0] : n > 0 }
9425  *
9426  * is not combined into
9427  *
9428  *	min(n/2, 0)
9429  *
9430  * as this would result in n/2 being evaluated in parts of
9431  * the definition domain where n is not a multiple of 2.
9432  */
test_ast_expr(isl_ctx * ctx)9433 static int test_ast_expr(isl_ctx *ctx)
9434 {
9435 	const char *str;
9436 	isl_pw_aff *pa;
9437 	isl_ast_build *build;
9438 	isl_ast_expr *expr;
9439 	int min_max;
9440 	int is_min;
9441 
9442 	min_max = isl_options_get_ast_build_detect_min_max(ctx);
9443 	isl_options_set_ast_build_detect_min_max(ctx, 1);
9444 
9445 	str = "[n] -> { [n/2] : n <= 0 and n % 2 = 0; [0] : n > 0 }";
9446 	pa = isl_pw_aff_read_from_str(ctx, str);
9447 	build = isl_ast_build_alloc(ctx);
9448 	expr = isl_ast_build_expr_from_pw_aff(build, pa);
9449 	is_min = isl_ast_expr_get_type(expr) == isl_ast_expr_op &&
9450 		 isl_ast_expr_get_op_type(expr) == isl_ast_expr_op_min;
9451 	isl_ast_build_free(build);
9452 	isl_ast_expr_free(expr);
9453 
9454 	isl_options_set_ast_build_detect_min_max(ctx, min_max);
9455 
9456 	if (!expr)
9457 		return -1;
9458 	if (is_min)
9459 		isl_die(ctx, isl_error_unknown,
9460 			"expressions should not be combined", return -1);
9461 
9462 	return 0;
9463 }
9464 
test_ast_gen(isl_ctx * ctx)9465 static int test_ast_gen(isl_ctx *ctx)
9466 {
9467 	if (test_ast_gen1(ctx) < 0)
9468 		return -1;
9469 	if (test_ast_gen2(ctx) < 0)
9470 		return -1;
9471 	if (test_ast_gen3(ctx) < 0)
9472 		return -1;
9473 	if (test_ast_gen4(ctx) < 0)
9474 		return -1;
9475 	if (test_ast_gen5(ctx) < 0)
9476 		return -1;
9477 	if (test_ast_expr(ctx) < 0)
9478 		return -1;
9479 	return 0;
9480 }
9481 
9482 /* Check if dropping output dimensions from an isl_pw_multi_aff
9483  * works properly.
9484  */
test_pw_multi_aff(isl_ctx * ctx)9485 static int test_pw_multi_aff(isl_ctx *ctx)
9486 {
9487 	const char *str;
9488 	isl_pw_multi_aff *pma1, *pma2;
9489 	int equal;
9490 
9491 	str = "{ [i,j] -> [i+j, 4i-j] }";
9492 	pma1 = isl_pw_multi_aff_read_from_str(ctx, str);
9493 	str = "{ [i,j] -> [4i-j] }";
9494 	pma2 = isl_pw_multi_aff_read_from_str(ctx, str);
9495 
9496 	pma1 = isl_pw_multi_aff_drop_dims(pma1, isl_dim_out, 0, 1);
9497 
9498 	equal = isl_pw_multi_aff_plain_is_equal(pma1, pma2);
9499 
9500 	isl_pw_multi_aff_free(pma1);
9501 	isl_pw_multi_aff_free(pma2);
9502 	if (equal < 0)
9503 		return -1;
9504 	if (!equal)
9505 		isl_die(ctx, isl_error_unknown,
9506 			"expressions not equal", return -1);
9507 
9508 	return 0;
9509 }
9510 
9511 /* Check that we can properly parse multi piecewise affine expressions
9512  * where the piecewise affine expressions have different domains.
9513  */
test_multi_pw_aff_1(isl_ctx * ctx)9514 static int test_multi_pw_aff_1(isl_ctx *ctx)
9515 {
9516 	const char *str;
9517 	isl_set *dom, *dom2;
9518 	isl_multi_pw_aff *mpa1, *mpa2;
9519 	isl_pw_aff *pa;
9520 	int equal;
9521 	int equal_domain;
9522 
9523 	mpa1 = isl_multi_pw_aff_read_from_str(ctx, "{ [i] -> [i] }");
9524 	dom = isl_set_read_from_str(ctx, "{ [i] : i > 0 }");
9525 	mpa1 = isl_multi_pw_aff_intersect_domain(mpa1, dom);
9526 	mpa2 = isl_multi_pw_aff_read_from_str(ctx, "{ [i] -> [2i] }");
9527 	mpa2 = isl_multi_pw_aff_flat_range_product(mpa1, mpa2);
9528 	str = "{ [i] -> [(i : i > 0), 2i] }";
9529 	mpa1 = isl_multi_pw_aff_read_from_str(ctx, str);
9530 
9531 	equal = isl_multi_pw_aff_plain_is_equal(mpa1, mpa2);
9532 
9533 	pa = isl_multi_pw_aff_get_pw_aff(mpa1, 0);
9534 	dom = isl_pw_aff_domain(pa);
9535 	pa = isl_multi_pw_aff_get_pw_aff(mpa1, 1);
9536 	dom2 = isl_pw_aff_domain(pa);
9537 	equal_domain = isl_set_is_equal(dom, dom2);
9538 
9539 	isl_set_free(dom);
9540 	isl_set_free(dom2);
9541 	isl_multi_pw_aff_free(mpa1);
9542 	isl_multi_pw_aff_free(mpa2);
9543 
9544 	if (equal < 0)
9545 		return -1;
9546 	if (!equal)
9547 		isl_die(ctx, isl_error_unknown,
9548 			"expressions not equal", return -1);
9549 
9550 	if (equal_domain < 0)
9551 		return -1;
9552 	if (equal_domain)
9553 		isl_die(ctx, isl_error_unknown,
9554 			"domains unexpectedly equal", return -1);
9555 
9556 	return 0;
9557 }
9558 
9559 /* Check that the dimensions in the explicit domain
9560  * of a multi piecewise affine expression are properly
9561  * taken into account.
9562  */
test_multi_pw_aff_2(isl_ctx * ctx)9563 static int test_multi_pw_aff_2(isl_ctx *ctx)
9564 {
9565 	const char *str;
9566 	isl_bool involves1, involves2, involves3, equal;
9567 	isl_multi_pw_aff *mpa, *mpa1, *mpa2;
9568 
9569 	str = "{ A[x,y] -> B[] : x >= y }";
9570 	mpa = isl_multi_pw_aff_read_from_str(ctx, str);
9571 	involves1 = isl_multi_pw_aff_involves_dims(mpa, isl_dim_in, 0, 2);
9572 	mpa1 = isl_multi_pw_aff_copy(mpa);
9573 
9574 	mpa = isl_multi_pw_aff_insert_dims(mpa, isl_dim_in, 0, 1);
9575 	involves2 = isl_multi_pw_aff_involves_dims(mpa, isl_dim_in, 0, 1);
9576 	involves3 = isl_multi_pw_aff_involves_dims(mpa, isl_dim_in, 1, 2);
9577 	str = "{ [a,x,y] -> B[] : x >= y }";
9578 	mpa2 = isl_multi_pw_aff_read_from_str(ctx, str);
9579 	equal = isl_multi_pw_aff_plain_is_equal(mpa, mpa2);
9580 	isl_multi_pw_aff_free(mpa2);
9581 
9582 	mpa = isl_multi_pw_aff_drop_dims(mpa, isl_dim_in, 0, 1);
9583 	mpa = isl_multi_pw_aff_set_tuple_name(mpa, isl_dim_in, "A");
9584 	if (equal >= 0 && equal)
9585 		equal = isl_multi_pw_aff_plain_is_equal(mpa, mpa1);
9586 	isl_multi_pw_aff_free(mpa1);
9587 	isl_multi_pw_aff_free(mpa);
9588 
9589 	if (involves1 < 0 || involves2 < 0 || involves3 < 0 || equal < 0)
9590 		return -1;
9591 	if (!equal)
9592 		isl_die(ctx, isl_error_unknown,
9593 			"incorrect result of dimension insertion/removal",
9594 			return isl_stat_error);
9595 	if (!involves1 || involves2 || !involves3)
9596 		isl_die(ctx, isl_error_unknown,
9597 			"incorrect characterization of involved dimensions",
9598 			return isl_stat_error);
9599 
9600 	return 0;
9601 }
9602 
9603 /* Check that isl_multi_union_pw_aff_multi_val_on_domain
9604  * sets the explicit domain of a zero-dimensional result,
9605  * such that it can be converted to an isl_union_map.
9606  */
test_multi_pw_aff_3(isl_ctx * ctx)9607 static isl_stat test_multi_pw_aff_3(isl_ctx *ctx)
9608 {
9609 	isl_space *space;
9610 	isl_union_set *dom;
9611 	isl_multi_val *mv;
9612 	isl_multi_union_pw_aff *mupa;
9613 	isl_union_map *umap;
9614 
9615 	dom = isl_union_set_read_from_str(ctx, "{ A[]; B[] }");
9616 	space = isl_union_set_get_space(dom);
9617 	mv = isl_multi_val_zero(isl_space_set_from_params(space));
9618 	mupa = isl_multi_union_pw_aff_multi_val_on_domain(dom, mv);
9619 	umap = isl_union_map_from_multi_union_pw_aff(mupa);
9620 	isl_union_map_free(umap);
9621 	if (!umap)
9622 		return isl_stat_error;
9623 
9624 	return isl_stat_ok;
9625 }
9626 
9627 /* Perform some tests on multi piecewise affine expressions.
9628  */
test_multi_pw_aff(isl_ctx * ctx)9629 static int test_multi_pw_aff(isl_ctx *ctx)
9630 {
9631 	if (test_multi_pw_aff_1(ctx) < 0)
9632 		return -1;
9633 	if (test_multi_pw_aff_2(ctx) < 0)
9634 		return -1;
9635 	if (test_multi_pw_aff_3(ctx) < 0)
9636 		return -1;
9637 	return 0;
9638 }
9639 
9640 /* This is a regression test for a bug where isl_basic_map_simplify
9641  * would end up in an infinite loop.  In particular, we construct
9642  * an empty basic set that is not obviously empty.
9643  * isl_basic_set_is_empty marks the basic set as empty.
9644  * After projecting out i3, the variable can be dropped completely,
9645  * but isl_basic_map_simplify refrains from doing so if the basic set
9646  * is empty and would end up in an infinite loop if it didn't test
9647  * explicitly for empty basic maps in the outer loop.
9648  */
test_simplify_1(isl_ctx * ctx)9649 static int test_simplify_1(isl_ctx *ctx)
9650 {
9651 	const char *str;
9652 	isl_basic_set *bset;
9653 	int empty;
9654 
9655 	str = "{ [i0, i1, i2, i3] : i0 >= -2 and 6i2 <= 4 + i0 + 5i1 and "
9656 		"i2 <= 22 and 75i2 <= 111 + 13i0 + 60i1 and "
9657 		"25i2 >= 38 + 6i0 + 20i1 and i0 <= -1 and i2 >= 20 and "
9658 		"i3 >= i2 }";
9659 	bset = isl_basic_set_read_from_str(ctx, str);
9660 	empty = isl_basic_set_is_empty(bset);
9661 	bset = isl_basic_set_project_out(bset, isl_dim_set, 3, 1);
9662 	isl_basic_set_free(bset);
9663 	if (!bset)
9664 		return -1;
9665 	if (!empty)
9666 		isl_die(ctx, isl_error_unknown,
9667 			"basic set should be empty", return -1);
9668 
9669 	return 0;
9670 }
9671 
9672 /* Check that the equality in the set description below
9673  * is simplified away.
9674  */
test_simplify_2(isl_ctx * ctx)9675 static int test_simplify_2(isl_ctx *ctx)
9676 {
9677 	const char *str;
9678 	isl_basic_set *bset;
9679 	isl_bool universe;
9680 
9681 	str = "{ [a] : exists e0, e1: 32e1 = 31 + 31a + 31e0 }";
9682 	bset = isl_basic_set_read_from_str(ctx, str);
9683 	universe = isl_basic_set_plain_is_universe(bset);
9684 	isl_basic_set_free(bset);
9685 
9686 	if (universe < 0)
9687 		return -1;
9688 	if (!universe)
9689 		isl_die(ctx, isl_error_unknown,
9690 			"equality not simplified away", return -1);
9691 	return 0;
9692 }
9693 
9694 /* Some simplification tests.
9695  */
test_simplify(isl_ctx * ctx)9696 static int test_simplify(isl_ctx *ctx)
9697 {
9698 	if (test_simplify_1(ctx) < 0)
9699 		return -1;
9700 	if (test_simplify_2(ctx) < 0)
9701 		return -1;
9702 	return 0;
9703 }
9704 
9705 /* This is a regression test for a bug where isl_tab_basic_map_partial_lexopt
9706  * with gbr context would fail to disable the use of the shifted tableau
9707  * when transferring equalities for the input to the context, resulting
9708  * in invalid sample values.
9709  */
test_partial_lexmin(isl_ctx * ctx)9710 static int test_partial_lexmin(isl_ctx *ctx)
9711 {
9712 	const char *str;
9713 	isl_basic_set *bset;
9714 	isl_basic_map *bmap;
9715 	isl_map *map;
9716 
9717 	str = "{ [1, b, c, 1 - c] -> [e] : 2e <= -c and 2e >= -3 + c }";
9718 	bmap = isl_basic_map_read_from_str(ctx, str);
9719 	str = "{ [a, b, c, d] : c <= 1 and 2d >= 6 - 4b - c }";
9720 	bset = isl_basic_set_read_from_str(ctx, str);
9721 	map = isl_basic_map_partial_lexmin(bmap, bset, NULL);
9722 	isl_map_free(map);
9723 
9724 	if (!map)
9725 		return -1;
9726 
9727 	return 0;
9728 }
9729 
9730 /* Check that the variable compression performed on the existentially
9731  * quantified variables inside isl_basic_set_compute_divs is not confused
9732  * by the implicit equalities among the parameters.
9733  */
test_compute_divs(isl_ctx * ctx)9734 static int test_compute_divs(isl_ctx *ctx)
9735 {
9736 	const char *str;
9737 	isl_basic_set *bset;
9738 	isl_set *set;
9739 
9740 	str = "[a, b, c, d, e] -> { [] : exists (e0: 2d = b and a <= 124 and "
9741 		"b <= 2046 and b >= 0 and b <= 60 + 64a and 2e >= b + 2c and "
9742 		"2e >= b and 2e <= 1 + b and 2e <= 1 + b + 2c and "
9743 		"32768e0 >= -124 + a and 2097152e0 <= 60 + 64a - b) }";
9744 	bset = isl_basic_set_read_from_str(ctx, str);
9745 	set = isl_basic_set_compute_divs(bset);
9746 	isl_set_free(set);
9747 	if (!set)
9748 		return -1;
9749 
9750 	return 0;
9751 }
9752 
9753 /* Check that isl_schedule_get_map is not confused by a schedule tree
9754  * with divergent filter node parameters, as can result from a call
9755  * to isl_schedule_intersect_domain.
9756  */
test_schedule_tree(isl_ctx * ctx)9757 static int test_schedule_tree(isl_ctx *ctx)
9758 {
9759 	const char *str;
9760 	isl_union_set *uset;
9761 	isl_schedule *sched1, *sched2;
9762 	isl_union_map *umap;
9763 
9764 	uset = isl_union_set_read_from_str(ctx, "{ A[i] }");
9765 	sched1 = isl_schedule_from_domain(uset);
9766 	uset = isl_union_set_read_from_str(ctx, "{ B[] }");
9767 	sched2 = isl_schedule_from_domain(uset);
9768 
9769 	sched1 = isl_schedule_sequence(sched1, sched2);
9770 	str = "[n] -> { A[i] : 0 <= i < n; B[] }";
9771 	uset = isl_union_set_read_from_str(ctx, str);
9772 	sched1 = isl_schedule_intersect_domain(sched1, uset);
9773 	umap = isl_schedule_get_map(sched1);
9774 	isl_schedule_free(sched1);
9775 	isl_union_map_free(umap);
9776 	if (!umap)
9777 		return -1;
9778 
9779 	return 0;
9780 }
9781 
9782 /* Check that a zero-dimensional prefix schedule keeps track
9783  * of the domain and outer filters.
9784  */
test_schedule_tree_prefix(isl_ctx * ctx)9785 static int test_schedule_tree_prefix(isl_ctx *ctx)
9786 {
9787 	const char *str;
9788 	isl_bool equal;
9789 	isl_union_set *uset;
9790 	isl_union_set_list *filters;
9791 	isl_multi_union_pw_aff *mupa, *mupa2;
9792 	isl_schedule_node *node;
9793 
9794 	str = "{ S1[i,j] : 0 <= i,j < 10; S2[i,j] : 0 <= i,j < 10 }";
9795 	uset = isl_union_set_read_from_str(ctx, str);
9796 	node = isl_schedule_node_from_domain(uset);
9797 	node = isl_schedule_node_child(node, 0);
9798 
9799 	str = "{ S1[i,j] : i > j }";
9800 	uset = isl_union_set_read_from_str(ctx, str);
9801 	filters = isl_union_set_list_from_union_set(uset);
9802 	str = "{ S1[i,j] : i <= j; S2[i,j] }";
9803 	uset = isl_union_set_read_from_str(ctx, str);
9804 	filters = isl_union_set_list_add(filters, uset);
9805 	node = isl_schedule_node_insert_sequence(node, filters);
9806 
9807 	node = isl_schedule_node_child(node, 0);
9808 	node = isl_schedule_node_child(node, 0);
9809 	mupa = isl_schedule_node_get_prefix_schedule_multi_union_pw_aff(node);
9810 	str = "([] : { S1[i,j] : i > j })";
9811 	mupa2 = isl_multi_union_pw_aff_read_from_str(ctx, str);
9812 	equal = isl_multi_union_pw_aff_plain_is_equal(mupa, mupa2);
9813 	isl_multi_union_pw_aff_free(mupa2);
9814 	isl_multi_union_pw_aff_free(mupa);
9815 	isl_schedule_node_free(node);
9816 
9817 	if (equal < 0)
9818 		return -1;
9819 	if (!equal)
9820 		isl_die(ctx, isl_error_unknown, "unexpected prefix schedule",
9821 			return -1);
9822 
9823 	return 0;
9824 }
9825 
9826 /* Check that the reaching domain elements and the prefix schedule
9827  * at a leaf node are the same before and after grouping.
9828  */
test_schedule_tree_group_1(isl_ctx * ctx)9829 static int test_schedule_tree_group_1(isl_ctx *ctx)
9830 {
9831 	int equal;
9832 	const char *str;
9833 	isl_id *id;
9834 	isl_union_set *uset;
9835 	isl_multi_union_pw_aff *mupa;
9836 	isl_union_pw_multi_aff *upma1, *upma2;
9837 	isl_union_set *domain1, *domain2;
9838 	isl_union_map *umap1, *umap2;
9839 	isl_schedule_node *node;
9840 
9841 	str = "{ S1[i,j] : 0 <= i,j < 10; S2[i,j] : 0 <= i,j < 10 }";
9842 	uset = isl_union_set_read_from_str(ctx, str);
9843 	node = isl_schedule_node_from_domain(uset);
9844 	node = isl_schedule_node_child(node, 0);
9845 	str = "[{ S1[i,j] -> [i]; S2[i,j] -> [9 - i] }]";
9846 	mupa = isl_multi_union_pw_aff_read_from_str(ctx, str);
9847 	node = isl_schedule_node_insert_partial_schedule(node, mupa);
9848 	node = isl_schedule_node_child(node, 0);
9849 	str = "[{ S1[i,j] -> [j]; S2[i,j] -> [j] }]";
9850 	mupa = isl_multi_union_pw_aff_read_from_str(ctx, str);
9851 	node = isl_schedule_node_insert_partial_schedule(node, mupa);
9852 	node = isl_schedule_node_child(node, 0);
9853 	umap1 = isl_schedule_node_get_prefix_schedule_union_map(node);
9854 	upma1 = isl_schedule_node_get_prefix_schedule_union_pw_multi_aff(node);
9855 	domain1 = isl_schedule_node_get_domain(node);
9856 	id = isl_id_alloc(ctx, "group", NULL);
9857 	node = isl_schedule_node_parent(node);
9858 	node = isl_schedule_node_group(node, id);
9859 	node = isl_schedule_node_child(node, 0);
9860 	umap2 = isl_schedule_node_get_prefix_schedule_union_map(node);
9861 	upma2 = isl_schedule_node_get_prefix_schedule_union_pw_multi_aff(node);
9862 	domain2 = isl_schedule_node_get_domain(node);
9863 	equal = isl_union_pw_multi_aff_plain_is_equal(upma1, upma2);
9864 	if (equal >= 0 && equal)
9865 		equal = isl_union_set_is_equal(domain1, domain2);
9866 	if (equal >= 0 && equal)
9867 		equal = isl_union_map_is_equal(umap1, umap2);
9868 	isl_union_map_free(umap1);
9869 	isl_union_map_free(umap2);
9870 	isl_union_set_free(domain1);
9871 	isl_union_set_free(domain2);
9872 	isl_union_pw_multi_aff_free(upma1);
9873 	isl_union_pw_multi_aff_free(upma2);
9874 	isl_schedule_node_free(node);
9875 
9876 	if (equal < 0)
9877 		return -1;
9878 	if (!equal)
9879 		isl_die(ctx, isl_error_unknown,
9880 			"expressions not equal", return -1);
9881 
9882 	return 0;
9883 }
9884 
9885 /* Check that we can have nested groupings and that the union map
9886  * schedule representation is the same before and after the grouping.
9887  * Note that after the grouping, the union map representation contains
9888  * the domain constraints from the ranges of the expansion nodes,
9889  * while they are missing from the union map representation of
9890  * the tree without expansion nodes.
9891  *
9892  * Also check that the global expansion is as expected.
9893  */
test_schedule_tree_group_2(isl_ctx * ctx)9894 static int test_schedule_tree_group_2(isl_ctx *ctx)
9895 {
9896 	int equal, equal_expansion;
9897 	const char *str;
9898 	isl_id *id;
9899 	isl_union_set *uset;
9900 	isl_union_map *umap1, *umap2;
9901 	isl_union_map *expansion1, *expansion2;
9902 	isl_union_set_list *filters;
9903 	isl_multi_union_pw_aff *mupa;
9904 	isl_schedule *schedule;
9905 	isl_schedule_node *node;
9906 
9907 	str = "{ S1[i,j] : 0 <= i,j < 10; S2[i,j] : 0 <= i,j < 10; "
9908 		"S3[i,j] : 0 <= i,j < 10 }";
9909 	uset = isl_union_set_read_from_str(ctx, str);
9910 	node = isl_schedule_node_from_domain(uset);
9911 	node = isl_schedule_node_child(node, 0);
9912 	str = "[{ S1[i,j] -> [i]; S2[i,j] -> [i]; S3[i,j] -> [i] }]";
9913 	mupa = isl_multi_union_pw_aff_read_from_str(ctx, str);
9914 	node = isl_schedule_node_insert_partial_schedule(node, mupa);
9915 	node = isl_schedule_node_child(node, 0);
9916 	str = "{ S1[i,j] }";
9917 	uset = isl_union_set_read_from_str(ctx, str);
9918 	filters = isl_union_set_list_from_union_set(uset);
9919 	str = "{ S2[i,j]; S3[i,j] }";
9920 	uset = isl_union_set_read_from_str(ctx, str);
9921 	filters = isl_union_set_list_add(filters, uset);
9922 	node = isl_schedule_node_insert_sequence(node, filters);
9923 	node = isl_schedule_node_child(node, 1);
9924 	node = isl_schedule_node_child(node, 0);
9925 	str = "{ S2[i,j] }";
9926 	uset = isl_union_set_read_from_str(ctx, str);
9927 	filters = isl_union_set_list_from_union_set(uset);
9928 	str = "{ S3[i,j] }";
9929 	uset = isl_union_set_read_from_str(ctx, str);
9930 	filters = isl_union_set_list_add(filters, uset);
9931 	node = isl_schedule_node_insert_sequence(node, filters);
9932 
9933 	schedule = isl_schedule_node_get_schedule(node);
9934 	umap1 = isl_schedule_get_map(schedule);
9935 	uset = isl_schedule_get_domain(schedule);
9936 	umap1 = isl_union_map_intersect_domain(umap1, uset);
9937 	isl_schedule_free(schedule);
9938 
9939 	node = isl_schedule_node_parent(node);
9940 	node = isl_schedule_node_parent(node);
9941 	id = isl_id_alloc(ctx, "group1", NULL);
9942 	node = isl_schedule_node_group(node, id);
9943 	node = isl_schedule_node_child(node, 1);
9944 	node = isl_schedule_node_child(node, 0);
9945 	id = isl_id_alloc(ctx, "group2", NULL);
9946 	node = isl_schedule_node_group(node, id);
9947 
9948 	schedule = isl_schedule_node_get_schedule(node);
9949 	umap2 = isl_schedule_get_map(schedule);
9950 	isl_schedule_free(schedule);
9951 
9952 	node = isl_schedule_node_root(node);
9953 	node = isl_schedule_node_child(node, 0);
9954 	expansion1 = isl_schedule_node_get_subtree_expansion(node);
9955 	isl_schedule_node_free(node);
9956 
9957 	str = "{ group1[i] -> S1[i,j] : 0 <= i,j < 10; "
9958 		"group1[i] -> S2[i,j] : 0 <= i,j < 10; "
9959 		"group1[i] -> S3[i,j] : 0 <= i,j < 10 }";
9960 
9961 	expansion2 = isl_union_map_read_from_str(ctx, str);
9962 
9963 	equal = isl_union_map_is_equal(umap1, umap2);
9964 	equal_expansion = isl_union_map_is_equal(expansion1, expansion2);
9965 
9966 	isl_union_map_free(umap1);
9967 	isl_union_map_free(umap2);
9968 	isl_union_map_free(expansion1);
9969 	isl_union_map_free(expansion2);
9970 
9971 	if (equal < 0 || equal_expansion < 0)
9972 		return -1;
9973 	if (!equal)
9974 		isl_die(ctx, isl_error_unknown,
9975 			"expressions not equal", return -1);
9976 	if (!equal_expansion)
9977 		isl_die(ctx, isl_error_unknown,
9978 			"unexpected expansion", return -1);
9979 
9980 	return 0;
9981 }
9982 
9983 /* Some tests for the isl_schedule_node_group function.
9984  */
test_schedule_tree_group(isl_ctx * ctx)9985 static int test_schedule_tree_group(isl_ctx *ctx)
9986 {
9987 	if (test_schedule_tree_group_1(ctx) < 0)
9988 		return -1;
9989 	if (test_schedule_tree_group_2(ctx) < 0)
9990 		return -1;
9991 	return 0;
9992 }
9993 
9994 struct {
9995 	const char *set;
9996 	const char *dual;
9997 } coef_tests[] = {
9998 	{ "{ rat: [i] : 0 <= i <= 10 }",
9999 	  "{ rat: coefficients[[cst] -> [a]] : cst >= 0 and 10a + cst >= 0 }" },
10000 	{ "{ rat: [i] : FALSE }",
10001 	  "{ rat: coefficients[[cst] -> [a]] }" },
10002 	{ "{ rat: [i] : }",
10003 	  "{ rat: coefficients[[cst] -> [0]] : cst >= 0 }" },
10004 };
10005 
10006 struct {
10007 	const char *set;
10008 	const char *dual;
10009 } sol_tests[] = {
10010 	{ "{ rat: coefficients[[cst] -> [a]] : cst >= 0 and 10a + cst >= 0 }",
10011 	  "{ rat: [i] : 0 <= i <= 10 }" },
10012 	{ "{ rat: coefficients[[cst] -> [a]] : FALSE }",
10013 	  "{ rat: [i] }" },
10014 	{ "{ rat: coefficients[[cst] -> [a]] }",
10015 	  "{ rat: [i] : FALSE }" },
10016 };
10017 
10018 /* Test the basic functionality of isl_basic_set_coefficients and
10019  * isl_basic_set_solutions.
10020  */
test_dual(isl_ctx * ctx)10021 static int test_dual(isl_ctx *ctx)
10022 {
10023 	int i;
10024 
10025 	for (i = 0; i < ARRAY_SIZE(coef_tests); ++i) {
10026 		int equal;
10027 		isl_basic_set *bset1, *bset2;
10028 
10029 		bset1 = isl_basic_set_read_from_str(ctx, coef_tests[i].set);
10030 		bset2 = isl_basic_set_read_from_str(ctx, coef_tests[i].dual);
10031 		bset1 = isl_basic_set_coefficients(bset1);
10032 		equal = isl_basic_set_is_equal(bset1, bset2);
10033 		isl_basic_set_free(bset1);
10034 		isl_basic_set_free(bset2);
10035 		if (equal < 0)
10036 			return -1;
10037 		if (!equal)
10038 			isl_die(ctx, isl_error_unknown,
10039 				"incorrect dual", return -1);
10040 	}
10041 
10042 	for (i = 0; i < ARRAY_SIZE(sol_tests); ++i) {
10043 		int equal;
10044 		isl_basic_set *bset1, *bset2;
10045 
10046 		bset1 = isl_basic_set_read_from_str(ctx, sol_tests[i].set);
10047 		bset2 = isl_basic_set_read_from_str(ctx, sol_tests[i].dual);
10048 		bset1 = isl_basic_set_solutions(bset1);
10049 		equal = isl_basic_set_is_equal(bset1, bset2);
10050 		isl_basic_set_free(bset1);
10051 		isl_basic_set_free(bset2);
10052 		if (equal < 0)
10053 			return -1;
10054 		if (!equal)
10055 			isl_die(ctx, isl_error_unknown,
10056 				"incorrect dual", return -1);
10057 	}
10058 
10059 	return 0;
10060 }
10061 
10062 struct {
10063 	int scale_tile;
10064 	int shift_point;
10065 	const char *domain;
10066 	const char *schedule;
10067 	const char *sizes;
10068 	const char *tile;
10069 	const char *point;
10070 } tile_tests[] = {
10071 	{ 0, 0, "[n] -> { S[i,j] : 0 <= i,j < n }",
10072 	  "[{ S[i,j] -> [i] }, { S[i,j] -> [j] }]",
10073 	  "{ [32,32] }",
10074 	  "[{ S[i,j] -> [floor(i/32)] }, { S[i,j] -> [floor(j/32)] }]",
10075 	  "[{ S[i,j] -> [i] }, { S[i,j] -> [j] }]",
10076 	},
10077 	{ 1, 0, "[n] -> { S[i,j] : 0 <= i,j < n }",
10078 	  "[{ S[i,j] -> [i] }, { S[i,j] -> [j] }]",
10079 	  "{ [32,32] }",
10080 	  "[{ S[i,j] -> [32*floor(i/32)] }, { S[i,j] -> [32*floor(j/32)] }]",
10081 	  "[{ S[i,j] -> [i] }, { S[i,j] -> [j] }]",
10082 	},
10083 	{ 0, 1, "[n] -> { S[i,j] : 0 <= i,j < n }",
10084 	  "[{ S[i,j] -> [i] }, { S[i,j] -> [j] }]",
10085 	  "{ [32,32] }",
10086 	  "[{ S[i,j] -> [floor(i/32)] }, { S[i,j] -> [floor(j/32)] }]",
10087 	  "[{ S[i,j] -> [i%32] }, { S[i,j] -> [j%32] }]",
10088 	},
10089 	{ 1, 1, "[n] -> { S[i,j] : 0 <= i,j < n }",
10090 	  "[{ S[i,j] -> [i] }, { S[i,j] -> [j] }]",
10091 	  "{ [32,32] }",
10092 	  "[{ S[i,j] -> [32*floor(i/32)] }, { S[i,j] -> [32*floor(j/32)] }]",
10093 	  "[{ S[i,j] -> [i%32] }, { S[i,j] -> [j%32] }]",
10094 	},
10095 };
10096 
10097 /* Basic tiling tests.  Create a schedule tree with a domain and a band node,
10098  * tile the band and then check if the tile and point bands have the
10099  * expected partial schedule.
10100  */
test_tile(isl_ctx * ctx)10101 static int test_tile(isl_ctx *ctx)
10102 {
10103 	int i;
10104 	int scale;
10105 	int shift;
10106 
10107 	scale = isl_options_get_tile_scale_tile_loops(ctx);
10108 	shift = isl_options_get_tile_shift_point_loops(ctx);
10109 
10110 	for (i = 0; i < ARRAY_SIZE(tile_tests); ++i) {
10111 		int opt;
10112 		int equal;
10113 		const char *str;
10114 		isl_union_set *domain;
10115 		isl_multi_union_pw_aff *mupa, *mupa2;
10116 		isl_schedule_node *node;
10117 		isl_multi_val *sizes;
10118 
10119 		opt = tile_tests[i].scale_tile;
10120 		isl_options_set_tile_scale_tile_loops(ctx, opt);
10121 		opt = tile_tests[i].shift_point;
10122 		isl_options_set_tile_shift_point_loops(ctx, opt);
10123 
10124 		str = tile_tests[i].domain;
10125 		domain = isl_union_set_read_from_str(ctx, str);
10126 		node = isl_schedule_node_from_domain(domain);
10127 		node = isl_schedule_node_child(node, 0);
10128 		str = tile_tests[i].schedule;
10129 		mupa = isl_multi_union_pw_aff_read_from_str(ctx, str);
10130 		node = isl_schedule_node_insert_partial_schedule(node, mupa);
10131 		str = tile_tests[i].sizes;
10132 		sizes = isl_multi_val_read_from_str(ctx, str);
10133 		node = isl_schedule_node_band_tile(node, sizes);
10134 
10135 		str = tile_tests[i].tile;
10136 		mupa = isl_multi_union_pw_aff_read_from_str(ctx, str);
10137 		mupa2 = isl_schedule_node_band_get_partial_schedule(node);
10138 		equal = isl_multi_union_pw_aff_plain_is_equal(mupa, mupa2);
10139 		isl_multi_union_pw_aff_free(mupa);
10140 		isl_multi_union_pw_aff_free(mupa2);
10141 
10142 		node = isl_schedule_node_child(node, 0);
10143 
10144 		str = tile_tests[i].point;
10145 		mupa = isl_multi_union_pw_aff_read_from_str(ctx, str);
10146 		mupa2 = isl_schedule_node_band_get_partial_schedule(node);
10147 		if (equal >= 0 && equal)
10148 			equal = isl_multi_union_pw_aff_plain_is_equal(mupa,
10149 									mupa2);
10150 		isl_multi_union_pw_aff_free(mupa);
10151 		isl_multi_union_pw_aff_free(mupa2);
10152 
10153 		isl_schedule_node_free(node);
10154 
10155 		if (equal < 0)
10156 			return -1;
10157 		if (!equal)
10158 			isl_die(ctx, isl_error_unknown,
10159 				"unexpected result", return -1);
10160 	}
10161 
10162 	isl_options_set_tile_scale_tile_loops(ctx, scale);
10163 	isl_options_set_tile_shift_point_loops(ctx, shift);
10164 
10165 	return 0;
10166 }
10167 
10168 /* Check that the domain hash of a space is equal to the hash
10169  * of the domain of the space.
10170  */
test_domain_hash(isl_ctx * ctx)10171 static int test_domain_hash(isl_ctx *ctx)
10172 {
10173 	isl_map *map;
10174 	isl_space *space;
10175 	uint32_t hash1, hash2;
10176 
10177 	map = isl_map_read_from_str(ctx, "[n] -> { A[B[x] -> C[]] -> D[] }");
10178 	space = isl_map_get_space(map);
10179 	isl_map_free(map);
10180 	hash1 = isl_space_get_domain_hash(space);
10181 	space = isl_space_domain(space);
10182 	hash2 = isl_space_get_hash(space);
10183 	isl_space_free(space);
10184 
10185 	if (!space)
10186 		return -1;
10187 	if (hash1 != hash2)
10188 		isl_die(ctx, isl_error_unknown,
10189 			"domain hash not equal to hash of domain", return -1);
10190 
10191 	return 0;
10192 }
10193 
10194 /* Check that a universe basic set that is not obviously equal to the universe
10195  * is still recognized as being equal to the universe.
10196  */
test_universe(isl_ctx * ctx)10197 static int test_universe(isl_ctx *ctx)
10198 {
10199 	const char *s;
10200 	isl_basic_set *bset;
10201 	isl_bool is_univ;
10202 
10203 	s = "{ [] : exists x, y : 3y <= 2x and y >= -3 + 2x and 2y >= 2 - x }";
10204 	bset = isl_basic_set_read_from_str(ctx, s);
10205 	is_univ = isl_basic_set_is_universe(bset);
10206 	isl_basic_set_free(bset);
10207 
10208 	if (is_univ < 0)
10209 		return -1;
10210 	if (!is_univ)
10211 		isl_die(ctx, isl_error_unknown,
10212 			"not recognized as universe set", return -1);
10213 
10214 	return 0;
10215 }
10216 
10217 /* Sets for which chambers are computed and checked.
10218  */
10219 const char *chambers_tests[] = {
10220 	"[A, B, C] -> { [x, y, z] : x >= 0 and y >= 0 and y <= A - x and "
10221 				"z >= 0 and z <= C - y and z <= B - x - y }",
10222 };
10223 
10224 /* Add the domain of "cell" to "cells".
10225  */
add_cell(__isl_take isl_cell * cell,void * user)10226 static isl_stat add_cell(__isl_take isl_cell *cell, void *user)
10227 {
10228 	isl_basic_set_list **cells = user;
10229 	isl_basic_set *dom;
10230 
10231 	dom = isl_cell_get_domain(cell);
10232 	isl_cell_free(cell);
10233 	*cells = isl_basic_set_list_add(*cells, dom);
10234 
10235 	return *cells ? isl_stat_ok : isl_stat_error;
10236 }
10237 
10238 /* Check that the elements of "list" are pairwise disjoint.
10239  */
check_pairwise_disjoint(__isl_keep isl_basic_set_list * list)10240 static isl_stat check_pairwise_disjoint(__isl_keep isl_basic_set_list *list)
10241 {
10242 	int i, j;
10243 	isl_size n;
10244 
10245 	n = isl_basic_set_list_n_basic_set(list);
10246 	if (n < 0)
10247 		return isl_stat_error;
10248 
10249 	for (i = 0; i < n; ++i) {
10250 		isl_basic_set *bset_i;
10251 
10252 		bset_i = isl_basic_set_list_get_basic_set(list, i);
10253 		for (j = i + 1; j < n; ++j) {
10254 			isl_basic_set *bset_j;
10255 			isl_bool disjoint;
10256 
10257 			bset_j = isl_basic_set_list_get_basic_set(list, j);
10258 			disjoint = isl_basic_set_is_disjoint(bset_i, bset_j);
10259 			isl_basic_set_free(bset_j);
10260 			if (!disjoint)
10261 				isl_die(isl_basic_set_list_get_ctx(list),
10262 					isl_error_unknown, "not disjoint",
10263 					break);
10264 			if (disjoint < 0 || !disjoint)
10265 				break;
10266 		}
10267 		isl_basic_set_free(bset_i);
10268 		if (j < n)
10269 			return isl_stat_error;
10270 	}
10271 
10272 	return isl_stat_ok;
10273 }
10274 
10275 /* Check that the chambers computed by isl_vertices_foreach_disjoint_cell
10276  * are pairwise disjoint.
10277  */
test_chambers(isl_ctx * ctx)10278 static int test_chambers(isl_ctx *ctx)
10279 {
10280 	int i;
10281 
10282 	for (i = 0; i < ARRAY_SIZE(chambers_tests); ++i) {
10283 		isl_basic_set *bset;
10284 		isl_vertices *vertices;
10285 		isl_basic_set_list *cells;
10286 		isl_stat ok;
10287 
10288 		bset = isl_basic_set_read_from_str(ctx, chambers_tests[i]);
10289 		vertices = isl_basic_set_compute_vertices(bset);
10290 		cells = isl_basic_set_list_alloc(ctx, 0);
10291 		if (isl_vertices_foreach_disjoint_cell(vertices, &add_cell,
10292 							&cells) < 0)
10293 			cells = isl_basic_set_list_free(cells);
10294 		ok = check_pairwise_disjoint(cells);
10295 		isl_basic_set_list_free(cells);
10296 		isl_vertices_free(vertices);
10297 		isl_basic_set_free(bset);
10298 
10299 		if (ok < 0)
10300 			return -1;
10301 	}
10302 
10303 	return 0;
10304 }
10305 
10306 struct {
10307 	const char *name;
10308 	int (*fn)(isl_ctx *ctx);
10309 } tests [] = {
10310 	{ "universe", &test_universe },
10311 	{ "domain hash", &test_domain_hash },
10312 	{ "dual", &test_dual },
10313 	{ "dependence analysis", &test_flow },
10314 	{ "val", &test_val },
10315 	{ "compute divs", &test_compute_divs },
10316 	{ "partial lexmin", &test_partial_lexmin },
10317 	{ "simplify", &test_simplify },
10318 	{ "curry", &test_curry },
10319 	{ "piecewise multi affine expressions", &test_pw_multi_aff },
10320 	{ "multi piecewise affine expressions", &test_multi_pw_aff },
10321 	{ "conversion", &test_conversion },
10322 	{ "list", &test_list },
10323 	{ "align parameters", &test_align_parameters },
10324 	{ "drop unused parameters", &test_drop_unused_parameters },
10325 	{ "preimage", &test_preimage },
10326 	{ "pullback", &test_pullback },
10327 	{ "AST", &test_ast },
10328 	{ "AST build", &test_ast_build },
10329 	{ "AST generation", &test_ast_gen },
10330 	{ "eliminate", &test_eliminate },
10331 	{ "deltas_map", &test_deltas_map },
10332 	{ "residue class", &test_residue_class },
10333 	{ "div", &test_div },
10334 	{ "slice", &test_slice },
10335 	{ "fixed power", &test_fixed_power },
10336 	{ "sample", &test_sample },
10337 	{ "output", &test_output },
10338 	{ "vertices", &test_vertices },
10339 	{ "chambers", &test_chambers },
10340 	{ "fixed", &test_fixed },
10341 	{ "equal", &test_equal },
10342 	{ "disjoint", &test_disjoint },
10343 	{ "product", &test_product },
10344 	{ "dim_max", &test_dim_max },
10345 	{ "affine", &test_aff },
10346 	{ "injective", &test_injective },
10347 	{ "schedule (whole component)", &test_schedule_whole },
10348 	{ "schedule (incremental)", &test_schedule_incremental },
10349 	{ "schedule tree", &test_schedule_tree },
10350 	{ "schedule tree prefix", &test_schedule_tree_prefix },
10351 	{ "schedule tree grouping", &test_schedule_tree_group },
10352 	{ "tile", &test_tile },
10353 	{ "union map", &test_union_map },
10354 	{ "union_pw", &test_union_pw },
10355 	{ "locus", &test_locus },
10356 	{ "eval", &test_eval },
10357 	{ "parse", &test_parse },
10358 	{ "single-valued", &test_sv },
10359 	{ "recession cone", &test_recession_cone },
10360 	{ "affine hull", &test_affine_hull },
10361 	{ "simple_hull", &test_simple_hull },
10362 	{ "box hull", &test_box_hull },
10363 	{ "coalesce", &test_coalesce },
10364 	{ "factorize", &test_factorize },
10365 	{ "subset", &test_subset },
10366 	{ "subtract", &test_subtract },
10367 	{ "intersect", &test_intersect },
10368 	{ "lexmin", &test_lexmin },
10369 	{ "min", &test_min },
10370 	{ "gist", &test_gist },
10371 	{ "piecewise quasi-polynomials", &test_pwqp },
10372 	{ "lift", &test_lift },
10373 	{ "bind parameters", &test_bind },
10374 	{ "unbind parameters", &test_unbind },
10375 	{ "bound", &test_bound },
10376 	{ "get lists", &test_get_list },
10377 	{ "union", &test_union },
10378 	{ "split periods", &test_split_periods },
10379 	{ "lexicographic order", &test_lex },
10380 	{ "bijectivity", &test_bijective },
10381 	{ "dataflow analysis", &test_dep },
10382 	{ "reading", &test_read },
10383 	{ "bounded", &test_bounded },
10384 	{ "construction", &test_construction },
10385 	{ "dimension manipulation", &test_dim },
10386 	{ "map application", &test_application },
10387 	{ "convex hull", &test_convex_hull },
10388 	{ "transitive closure", &test_closure },
10389 	{ "isl_bool", &test_isl_bool},
10390 };
10391 
main(int argc,char ** argv)10392 int main(int argc, char **argv)
10393 {
10394 	int i;
10395 	struct isl_ctx *ctx;
10396 	struct isl_options *options;
10397 
10398 	options = isl_options_new_with_defaults();
10399 	assert(options);
10400 	argc = isl_options_parse(options, argc, argv, ISL_ARG_ALL);
10401 
10402 	ctx = isl_ctx_alloc_with_options(&isl_options_args, options);
10403 	for (i = 0; i < ARRAY_SIZE(tests); ++i) {
10404 		printf("%s\n", tests[i].name);
10405 		if (tests[i].fn(ctx) < 0)
10406 			goto error;
10407 	}
10408 	isl_ctx_free(ctx);
10409 	return 0;
10410 error:
10411 	isl_ctx_free(ctx);
10412 	return -1;
10413 }
10414