export isl_set_n_basic_set
[isl.git] / isl_test.c
blob2d0965097c47b0bce02362d650c24243de4edbe7
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
7 * Use of this software is governed by the MIT license
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
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>
43 #include "isl_srcdir.c"
45 #define ARRAY_SIZE(array) (sizeof(array)/sizeof(*array))
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";
52 length = strlen(pattern) - 6 + strlen(srcdir) + strlen(name)
53 + strlen(suffix) + 1;
54 filename = isl_alloc_array(ctx, char, length);
56 if (!filename)
57 return NULL;
59 sprintf(filename, pattern, srcdir, name, suffix);
61 return filename;
64 void test_parse_map(isl_ctx *ctx, const char *str)
66 isl_map *map;
68 map = isl_map_read_from_str(ctx, str);
69 assert(map);
70 isl_map_free(map);
73 int test_parse_map_equal(isl_ctx *ctx, const char *str, const char *str2)
75 isl_map *map, *map2;
76 int equal;
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);
84 if (equal < 0)
85 return -1;
86 if (!equal)
87 isl_die(ctx, isl_error_unknown, "maps not equal",
88 return -1);
90 return 0;
93 void test_parse_pwqp(isl_ctx *ctx, const char *str)
95 isl_pw_qpolynomial *pwqp;
97 pwqp = isl_pw_qpolynomial_read_from_str(ctx, str);
98 assert(pwqp);
99 isl_pw_qpolynomial_free(pwqp);
102 static void test_parse_pwaff(isl_ctx *ctx, const char *str)
104 isl_pw_aff *pwaff;
106 pwaff = isl_pw_aff_read_from_str(ctx, str);
107 assert(pwaff);
108 isl_pw_aff_free(pwaff);
111 /* Check that we can read an isl_multi_val from "str" without errors.
113 static int test_parse_multi_val(isl_ctx *ctx, const char *str)
115 isl_multi_val *mv;
117 mv = isl_multi_val_read_from_str(ctx, str);
118 isl_multi_val_free(mv);
120 return mv ? 0 : -1;
123 /* String descriptions of multi piecewise affine expressions
124 * that are used for testing printing and parsing.
126 static const char *reparse_multi_pw_aff_tests[] = {
127 "{ A[x, y] -> [] : x + y >= 0 }",
128 "{ A[x, y] -> B[] : x + y >= 0 }",
129 "{ A[x, y] -> [x] : x + y >= 0 }",
130 "[N] -> { A[x, y] -> [x] : x + y <= N }",
131 "{ A[x, y] -> [x, y] : x + y >= 0 }",
132 "{ A[x, y] -> [(x : x >= 0), (y : y >= 0)] : x + y >= 0 }",
133 "[N] -> { [] : N >= 0 }",
134 "[N] -> { [] : N >= 0 }",
135 "[N] -> { [N] : N >= 0 }",
136 "[N] -> { [N, N + 1] : N >= 0 }",
137 "[N, M] -> { [(N : N >= 0), (M : M >= 0)] : N + M >= 0 }",
138 "{ [a] -> [b = a] }",
139 "{ [a] -> [b = a] : a >= 0 }",
142 #undef BASE
143 #define BASE multi_pw_aff
145 #include "check_reparse_templ.c"
146 #include "check_reparse_test_templ.c"
148 /* String descriptions that cannot be parsed
149 * as multi piecewise affine expressions.
151 static const char *parse_multi_pw_aff_fail_tests[] = {
152 "{ [a] -> [b] : b = a }",
153 "{ [a] -> [b = a] : b >= 0 }",
156 #include "check_parse_fail_test_templ.c"
158 /* String descriptions of piecewise multi affine expressions
159 * that are used for testing printing and parsing.
161 static const char *reparse_pw_multi_aff_tests[] = {
162 "{ [x] -> [x] }",
163 "{ [x] -> [x % 4] }",
164 "{ [x] -> [x % 4] : x mod 3 = 1 }",
165 "{ [x, x] -> [x % 4] }",
166 "{ [x, x + 1] -> [x % 4] : x mod 3 = 1 }",
167 "{ [x, x mod 2] -> [x % 4] }",
170 #undef BASE
171 #define BASE pw_multi_aff
173 #include "check_reparse_templ.c"
174 #include "check_reparse_test_templ.c"
176 /* Test parsing of piecewise multi affine expressions by printing
177 * the expressions and checking that parsing the output results
178 * in the same expression.
179 * Do this for an expression converted from a map with an output
180 * dimension name that is equal to an automatically generated name, and
181 * a set of expressions parsed from strings.
183 static isl_stat test_parse_pma(isl_ctx *ctx)
185 isl_map *map;
186 isl_pw_multi_aff *pma;
188 map = isl_map_read_from_str(ctx, "{ [a, a] -> [i1 = a + 1] }");
189 pma = isl_pw_multi_aff_from_map(map);
190 if (check_reparse_pw_multi_aff(ctx, pma) < 0)
191 return isl_stat_error;
193 if (check_reparse_pw_multi_aff_tests(ctx) < 0)
194 return isl_stat_error;
196 return isl_stat_ok;
199 /* String descriptions that cannot be parsed
200 * as union piecewise multi affine expressions.
202 static const char *parse_union_pw_multi_aff_fail_tests[] = {
203 "{ [a] -> [b] : b = a }",
204 "{ [a] -> [b = a] : b >= 0 }",
207 #undef BASE
208 #define BASE union_pw_multi_aff
210 #include "check_parse_fail_test_templ.c"
212 /* Test parsing of union piecewise multi affine expressions.
214 * In particular, check some cases where parsing is supposed to fail.
216 static isl_stat test_parse_upma(isl_ctx *ctx)
218 if (check_parse_union_pw_multi_aff_fail_tests(ctx) < 0)
219 return isl_stat_error;
221 return isl_stat_ok;
224 /* Test parsing of multi piecewise affine expressions by printing
225 * the expressions and checking that parsing the output results
226 * in the same expression.
227 * Do this for a couple of manually constructed expressions,
228 * an expression converted from a map with an output dimension name
229 * that is equal to an automatically generated name, and
230 * a set of expressions parsed from strings.
232 * Additionally, check some cases where parsing is supposed to fail.
234 static int test_parse_mpa(isl_ctx *ctx)
236 isl_space *space;
237 isl_set *dom;
238 isl_map *map;
239 isl_pw_multi_aff *pma;
240 isl_multi_pw_aff *mpa;
241 isl_stat r;
243 space = isl_space_set_alloc(ctx, 0, 0);
244 space = isl_space_set_tuple_name(space, isl_dim_set, "A");
245 mpa = isl_multi_pw_aff_zero(space);
246 r = check_reparse_multi_pw_aff(ctx, mpa);
247 if (r < 0)
248 return -1;
250 space = isl_space_set_alloc(ctx, 1, 0);
251 space = isl_space_set_dim_name(space, isl_dim_param, 0, "N");
252 space = isl_space_set_tuple_name(space, isl_dim_set, "A");
253 dom = isl_set_universe(isl_space_params(isl_space_copy(space)));
254 dom = isl_set_lower_bound_si(dom, isl_dim_param, 0, 5);
255 mpa = isl_multi_pw_aff_zero(space);
256 mpa = isl_multi_pw_aff_intersect_domain(mpa, dom);
257 r = check_reparse_multi_pw_aff(ctx, mpa);
258 if (r < 0)
259 return -1;
261 map = isl_map_read_from_str(ctx, "{ [a, a] -> [i1 = a + 1] }");
262 pma = isl_pw_multi_aff_from_map(map);
263 mpa = isl_multi_pw_aff_from_pw_multi_aff(pma);
264 if (check_reparse_multi_pw_aff(ctx, mpa) < 0)
265 return -1;
267 if (check_reparse_multi_pw_aff_tests(ctx) < 0)
268 return -1;
269 if (check_parse_multi_pw_aff_fail_tests(ctx) < 0)
270 return -1;
272 return 0;
275 /* String descriptions of multi union piecewise affine expressions
276 * that are used for testing printing and parsing.
278 static const char *reparse_multi_union_pw_aff_tests[] = {
279 "[]",
280 "A[]",
281 "A[B[] -> C[]]",
282 "(A[] : { S[x] : x > 0; T[y] : y >= 0 })",
283 "(A[] : { })",
284 "[N] -> (A[] : { })",
285 "[N] -> (A[] : { : N >= 0 })",
286 "[N] -> (A[] : { S[x] : x > N; T[y] : y >= 0 })",
287 "(A[] : [N] -> { S[x] : x > N; T[y] : y >= 0 })",
288 "A[{ S[x] -> [x + 1]; T[x] -> [x] }]",
289 "(A[{ S[x] -> [x + 1]; T[x] -> [x] }] : "
290 "{ S[x] : x > 0; T[y] : y >= 0 })",
293 #undef BASE
294 #define BASE multi_union_pw_aff
296 #include "check_reparse_templ.c"
297 #include "check_reparse_test_templ.c"
299 /* Test parsing of multi union piecewise affine expressions by printing
300 * the expressions and checking that parsing the output results
301 * in the same expression.
302 * Do this for a couple of manually constructed expressions and
303 * a set of expressions parsed from strings.
305 static int test_parse_mupa(isl_ctx *ctx)
307 isl_space *space;
308 isl_multi_union_pw_aff *mupa;
309 isl_set *dom;
310 isl_union_set *uset;
311 isl_stat r;
313 space = isl_space_set_alloc(ctx, 0, 0);
314 space = isl_space_set_tuple_name(space, isl_dim_set, "A");
315 mupa = isl_multi_union_pw_aff_zero(space);
316 r = check_reparse_multi_union_pw_aff(ctx, mupa);
317 if (r < 0)
318 return -1;
320 space = isl_space_set_alloc(ctx, 1, 0);
321 space = isl_space_set_dim_name(space, isl_dim_param, 0, "N");
322 space = isl_space_set_tuple_name(space, isl_dim_set, "A");
323 dom = isl_set_universe(space);
324 dom = isl_set_lower_bound_si(dom, isl_dim_param, 0, 5);
325 uset = isl_union_set_from_set(dom);
326 space = isl_space_set_alloc(ctx, 1, 0);
327 space = isl_space_set_dim_name(space, isl_dim_param, 0, "N");
328 space = isl_space_set_tuple_name(space, isl_dim_set, "B");
329 mupa = isl_multi_union_pw_aff_zero(space);
330 mupa = isl_multi_union_pw_aff_intersect_domain(mupa, uset);
331 r = check_reparse_multi_union_pw_aff(ctx, mupa);
332 if (r < 0)
333 return -1;
335 if (check_reparse_multi_union_pw_aff_tests(ctx) < 0)
336 return -1;
338 return 0;
341 /* Test parsing of multi expressions.
343 static int test_parse_multi(isl_ctx *ctx)
345 if (test_parse_mpa(ctx) < 0)
346 return -1;
347 if (test_parse_mupa(ctx) < 0)
348 return -1;
350 return 0;
353 /* Pairs of binary relation representations that should represent
354 * the same binary relations.
356 struct {
357 const char *map1;
358 const char *map2;
359 } parse_map_equal_tests[] = {
360 { "{ [x,y] : [([x/2]+y)/3] >= 1 }",
361 "{ [x, y] : 2y >= 6 - x }" },
362 { "{ [x,y] : x <= min(y, 2*y+3) }",
363 "{ [x,y] : x <= y, 2*y + 3 }" },
364 { "{ [x,y] : x >= min(y, 2*y+3) }",
365 "{ [x, y] : (y <= x and y >= -3) or (2y <= -3 + x and y <= -4) }" },
366 { "[n] -> { [c1] : c1>=0 and c1<=floord(n-4,3) }",
367 "[n] -> { [c1] : c1 >= 0 and 3c1 <= -4 + n }" },
368 { "{ [i,j] -> [i] : i < j; [i,j] -> [j] : j <= i }",
369 "{ [i,j] -> [min(i,j)] }" },
370 { "{ [i,j] : i != j }",
371 "{ [i,j] : i < j or i > j }" },
372 { "{ [i,j] : (i+1)*2 >= j }",
373 "{ [i, j] : j <= 2 + 2i }" },
374 { "{ [i] -> [i > 0 ? 4 : 5] }",
375 "{ [i] -> [5] : i <= 0; [i] -> [4] : i >= 1 }" },
376 { "[N=2,M] -> { [i=[(M+N)/4]] }",
377 "[N, M] -> { [i] : N = 2 and 4i <= 2 + M and 4i >= -1 + M }" },
378 { "{ [x] : x >= 0 }",
379 "{ [x] : x-0 >= 0 }" },
380 { "{ [i] : ((i > 10)) }",
381 "{ [i] : i >= 11 }" },
382 { "{ [i] -> [0] }",
383 "{ [i] -> [0 * i] }" },
384 { "{ [a] -> [b] : (not false) }",
385 "{ [a] -> [b] : true }" },
386 { "{ [i] : i/2 <= 5 }",
387 "{ [i] : i <= 10 }" },
388 { "{Sym=[n] [i] : i <= n }",
389 "[n] -> { [i] : i <= n }" },
390 { "{ [*] }",
391 "{ [a] }" },
392 { "{ [i] : 2*floor(i/2) = i }",
393 "{ [i] : exists a : i = 2 a }" },
394 { "{ [a] -> [b] : a = 5 implies b = 5 }",
395 "{ [a] -> [b] : a != 5 or b = 5 }" },
396 { "{ [a] -> [a - 1 : a > 0] }",
397 "{ [a] -> [a - 1] : a > 0 }" },
398 { "{ [a] -> [a - 1 : a > 0; a : a <= 0] }",
399 "{ [a] -> [a - 1] : a > 0; [a] -> [a] : a <= 0 }" },
400 { "{ [a] -> [(a) * 2 : a >= 0; 0 : a < 0] }",
401 "{ [a] -> [2a] : a >= 0; [a] -> [0] : a < 0 }" },
402 { "{ [a] -> [(a * 2) : a >= 0; 0 : a < 0] }",
403 "{ [a] -> [2a] : a >= 0; [a] -> [0] : a < 0 }" },
404 { "{ [a] -> [(a * 2 : a >= 0); 0 : a < 0] }",
405 "{ [a] -> [2a] : a >= 0; [a] -> [0] : a < 0 }" },
406 { "{ [a] -> [(a * 2 : a >= 0; 0 : a < 0)] }",
407 "{ [a] -> [2a] : a >= 0; [a] -> [0] : a < 0 }" },
408 { "{ [a,b] -> [i,j] : a,b << i,j }",
409 "{ [a,b] -> [i,j] : a < i or (a = i and b < j) }" },
410 { "{ [a,b] -> [i,j] : a,b <<= i,j }",
411 "{ [a,b] -> [i,j] : a < i or (a = i and b <= j) }" },
412 { "{ [a,b] -> [i,j] : a,b >> i,j }",
413 "{ [a,b] -> [i,j] : a > i or (a = i and b > j) }" },
414 { "{ [a,b] -> [i,j] : a,b >>= i,j }",
415 "{ [a,b] -> [i,j] : a > i or (a = i and b >= j) }" },
416 { "{ [n] -> [i] : exists (a, b, c: 8b <= i - 32a and "
417 "8b >= -7 + i - 32 a and b >= 0 and b <= 3 and "
418 "8c < n - 32a and i < n and c >= 0 and "
419 "c <= 3 and c >= -4a) }",
420 "{ [n] -> [i] : 0 <= i < n }" },
421 { "{ [x] -> [] : exists (a, b: 0 <= a <= 1 and 0 <= b <= 3 and "
422 "2b <= x - 8a and 2b >= -1 + x - 8a) }",
423 "{ [x] -> [] : 0 <= x <= 15 }" },
424 { "{ [x] -> [x] : }",
425 "{ [x] -> [x] }" },
426 { "{ [x=4:5] -> [x + 1] }",
427 "{ [x] -> [x + 1] : 4 <= x <= 5 }" },
428 { "{ [x=4:5] -> [x + 1 : x + 1] }",
429 "{ [x=4:5] -> [x + 1] }" },
430 { "{ [x] -> [x - 1 : x + 1] }",
431 "{ [x] -> [y] : x - 1 <= y <= x + 1 }" },
432 { "{ [x=4:] -> [x + 1] }",
433 "{ [x] -> [x + 1] : 4 <= x }" },
434 { "{ [x=:5] -> [x + 1] }",
435 "{ [x] -> [x + 1] : x <= 5 }" },
436 { "{ [x=:] -> [x + 1] }",
437 "{ [x] -> [x + 1] }" },
438 { "{ [:] -> [:] }",
439 "{ [x] -> [y] }" },
440 { "{ [x, x//4] }",
441 "{ [x, floor(x/4)] }" },
442 { "{ [10//4] }",
443 "{ [2] }" },
446 int test_parse(struct isl_ctx *ctx)
448 int i;
449 isl_map *map, *map2;
450 const char *str, *str2;
452 if (test_parse_multi_val(ctx, "{ A[B[2] -> C[5, 7]] }") < 0)
453 return -1;
454 if (test_parse_multi_val(ctx, "[n] -> { [2] }") < 0)
455 return -1;
456 if (test_parse_multi_val(ctx, "{ A[4, infty, NaN, -1/2, 2/3] }") < 0)
457 return -1;
458 if (test_parse_multi(ctx) < 0)
459 return -1;
460 if (test_parse_pma(ctx) < 0)
461 return -1;
462 if (test_parse_upma(ctx) < 0)
463 return -1;
465 str = "{ [i] -> [-i] }";
466 map = isl_map_read_from_str(ctx, str);
467 assert(map);
468 isl_map_free(map);
470 str = "{ A[i] -> L[([i/3])] }";
471 map = isl_map_read_from_str(ctx, str);
472 assert(map);
473 isl_map_free(map);
475 test_parse_map(ctx, "{[[s] -> A[i]] -> [[s+1] -> A[i]]}");
476 test_parse_map(ctx, "{ [p1, y1, y2] -> [2, y1, y2] : "
477 "p1 = 1 && (y1 <= y2 || y2 = 0) }");
479 for (i = 0; i < ARRAY_SIZE(parse_map_equal_tests); ++i) {
480 str = parse_map_equal_tests[i].map1;
481 str2 = parse_map_equal_tests[i].map2;
482 if (test_parse_map_equal(ctx, str, str2) < 0)
483 return -1;
486 str = "{[new,old] -> [new+1-2*[(new+1)/2],old+1-2*[(old+1)/2]]}";
487 map = isl_map_read_from_str(ctx, str);
488 str = "{ [new, old] -> [o0, o1] : "
489 "exists (e0 = [(-1 - new + o0)/2], e1 = [(-1 - old + o1)/2]: "
490 "2e0 = -1 - new + o0 and 2e1 = -1 - old + o1 and o0 >= 0 and "
491 "o0 <= 1 and o1 >= 0 and o1 <= 1) }";
492 map2 = isl_map_read_from_str(ctx, str);
493 assert(isl_map_is_equal(map, map2));
494 isl_map_free(map);
495 isl_map_free(map2);
497 str = "{[new,old] -> [new+1-2*[(new+1)/2],old+1-2*[(old+1)/2]]}";
498 map = isl_map_read_from_str(ctx, str);
499 str = "{[new,old] -> [(new+1)%2,(old+1)%2]}";
500 map2 = isl_map_read_from_str(ctx, str);
501 assert(isl_map_is_equal(map, map2));
502 isl_map_free(map);
503 isl_map_free(map2);
505 test_parse_pwqp(ctx, "{ [i] -> i + [ (i + [i/3])/2 ] }");
506 test_parse_map(ctx, "{ S1[i] -> [([i/10]),i%10] : 0 <= i <= 45 }");
507 test_parse_pwaff(ctx, "{ [i] -> [i + 1] : i > 0; [a] -> [a] : a < 0 }");
508 test_parse_pwqp(ctx, "{ [x] -> ([(x)/2] * [(x)/3]) }");
509 test_parse_pwaff(ctx, "{ [] -> [(100)] }");
511 return 0;
514 static int test_read(isl_ctx *ctx)
516 char *filename;
517 FILE *input;
518 isl_basic_set *bset1, *bset2;
519 const char *str = "{[y]: Exists ( alpha : 2alpha = y)}";
520 int equal;
522 filename = get_filename(ctx, "set", "omega");
523 assert(filename);
524 input = fopen(filename, "r");
525 assert(input);
527 bset1 = isl_basic_set_read_from_file(ctx, input);
528 bset2 = isl_basic_set_read_from_str(ctx, str);
530 equal = isl_basic_set_is_equal(bset1, bset2);
532 isl_basic_set_free(bset1);
533 isl_basic_set_free(bset2);
534 free(filename);
536 fclose(input);
538 if (equal < 0)
539 return -1;
540 if (!equal)
541 isl_die(ctx, isl_error_unknown,
542 "read sets not equal", return -1);
544 return 0;
547 static int test_bounded(isl_ctx *ctx)
549 isl_set *set;
550 isl_bool bounded;
552 set = isl_set_read_from_str(ctx, "[n] -> {[i] : 0 <= i <= n }");
553 bounded = isl_set_is_bounded(set);
554 isl_set_free(set);
556 if (bounded < 0)
557 return -1;
558 if (!bounded)
559 isl_die(ctx, isl_error_unknown,
560 "set not considered bounded", return -1);
562 set = isl_set_read_from_str(ctx, "{[n, i] : 0 <= i <= n }");
563 bounded = isl_set_is_bounded(set);
564 assert(!bounded);
565 isl_set_free(set);
567 if (bounded < 0)
568 return -1;
569 if (bounded)
570 isl_die(ctx, isl_error_unknown,
571 "set considered bounded", return -1);
573 set = isl_set_read_from_str(ctx, "[n] -> {[i] : i <= n }");
574 bounded = isl_set_is_bounded(set);
575 isl_set_free(set);
577 if (bounded < 0)
578 return -1;
579 if (bounded)
580 isl_die(ctx, isl_error_unknown,
581 "set considered bounded", return -1);
583 return 0;
586 /* Construct the basic set { [i] : 5 <= i <= N } */
587 static int test_construction_1(isl_ctx *ctx)
589 isl_space *space;
590 isl_local_space *ls;
591 isl_basic_set *bset;
592 isl_constraint *c;
594 space = isl_space_set_alloc(ctx, 1, 1);
595 bset = isl_basic_set_universe(isl_space_copy(space));
596 ls = isl_local_space_from_space(space);
598 c = isl_constraint_alloc_inequality(isl_local_space_copy(ls));
599 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, -1);
600 c = isl_constraint_set_coefficient_si(c, isl_dim_param, 0, 1);
601 bset = isl_basic_set_add_constraint(bset, c);
603 c = isl_constraint_alloc_inequality(isl_local_space_copy(ls));
604 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, 1);
605 c = isl_constraint_set_constant_si(c, -5);
606 bset = isl_basic_set_add_constraint(bset, c);
608 isl_local_space_free(ls);
609 isl_basic_set_free(bset);
611 return 0;
614 /* Construct the basic set { [x] : -100 <= x <= 100 }
615 * using isl_basic_set_{lower,upper}_bound_val and
616 * check that it is equal the same basic set parsed from a string.
618 static int test_construction_2(isl_ctx *ctx)
620 isl_bool equal;
621 isl_val *v;
622 isl_space *space;
623 isl_basic_set *bset1, *bset2;
625 v = isl_val_int_from_si(ctx, 100);
626 space = isl_space_set_alloc(ctx, 0, 1);
627 bset1 = isl_basic_set_universe(space);
628 bset1 = isl_basic_set_upper_bound_val(bset1, isl_dim_set, 0,
629 isl_val_copy(v));
630 bset1 = isl_basic_set_lower_bound_val(bset1, isl_dim_set, 0,
631 isl_val_neg(v));
632 bset2 = isl_basic_set_read_from_str(ctx, "{ [x] : -100 <= x <= 100 }");
633 equal = isl_basic_set_is_equal(bset1, bset2);
634 isl_basic_set_free(bset1);
635 isl_basic_set_free(bset2);
637 if (equal < 0)
638 return -1;
639 if (!equal)
640 isl_die(ctx, isl_error_unknown,
641 "failed construction", return -1);
643 return 0;
646 /* Basic tests for constructing basic sets.
648 static int test_construction(isl_ctx *ctx)
650 if (test_construction_1(ctx) < 0)
651 return -1;
652 if (test_construction_2(ctx) < 0)
653 return -1;
654 return 0;
657 static int test_dim(isl_ctx *ctx)
659 const char *str;
660 isl_map *map1, *map2;
661 int equal;
663 map1 = isl_map_read_from_str(ctx,
664 "[n] -> { [i] -> [j] : exists (a = [i/10] : i - 10a <= n ) }");
665 map1 = isl_map_add_dims(map1, isl_dim_in, 1);
666 map2 = isl_map_read_from_str(ctx,
667 "[n] -> { [i,k] -> [j] : exists (a = [i/10] : i - 10a <= n ) }");
668 equal = isl_map_is_equal(map1, map2);
669 isl_map_free(map2);
671 map1 = isl_map_project_out(map1, isl_dim_in, 0, 1);
672 map2 = isl_map_read_from_str(ctx, "[n] -> { [i] -> [j] : n >= 0 }");
673 if (equal >= 0 && equal)
674 equal = isl_map_is_equal(map1, map2);
676 isl_map_free(map1);
677 isl_map_free(map2);
679 if (equal < 0)
680 return -1;
681 if (!equal)
682 isl_die(ctx, isl_error_unknown,
683 "unexpected result", return -1);
685 str = "[n] -> { [i] -> [] : exists a : 0 <= i <= n and i = 2 a }";
686 map1 = isl_map_read_from_str(ctx, str);
687 str = "{ [i] -> [j] : exists a : 0 <= i <= j and i = 2 a }";
688 map2 = isl_map_read_from_str(ctx, str);
689 map1 = isl_map_move_dims(map1, isl_dim_out, 0, isl_dim_param, 0, 1);
690 equal = isl_map_is_equal(map1, map2);
691 isl_map_free(map1);
692 isl_map_free(map2);
694 if (equal < 0)
695 return -1;
696 if (!equal)
697 isl_die(ctx, isl_error_unknown,
698 "unexpected result", return -1);
700 return 0;
703 #undef BASE
704 #define BASE multi_val
705 #include "isl_test_plain_equal_templ.c"
707 #undef BASE
708 #define BASE multi_aff
709 #include "isl_test_plain_equal_templ.c"
711 /* Check that "val" is equal to the value described by "str".
712 * If "str" is "NaN", then check for a NaN value explicitly.
714 static isl_stat val_check_equal(__isl_keep isl_val *val, const char *str)
716 isl_bool ok, is_nan;
717 isl_ctx *ctx;
718 isl_val *res;
720 if (!val)
721 return isl_stat_error;
723 ctx = isl_val_get_ctx(val);
724 res = isl_val_read_from_str(ctx, str);
725 is_nan = isl_val_is_nan(res);
726 if (is_nan < 0)
727 ok = isl_bool_error;
728 else if (is_nan)
729 ok = isl_val_is_nan(val);
730 else
731 ok = isl_val_eq(val, res);
732 isl_val_free(res);
733 if (ok < 0)
734 return isl_stat_error;
735 if (!ok)
736 isl_die(ctx, isl_error_unknown,
737 "unexpected result", return isl_stat_error);
738 return isl_stat_ok;
741 struct {
742 __isl_give isl_val *(*op)(__isl_take isl_val *v);
743 const char *arg;
744 const char *res;
745 } val_un_tests[] = {
746 { &isl_val_neg, "0", "0" },
747 { &isl_val_abs, "0", "0" },
748 { &isl_val_pow2, "0", "1" },
749 { &isl_val_floor, "0", "0" },
750 { &isl_val_ceil, "0", "0" },
751 { &isl_val_neg, "1", "-1" },
752 { &isl_val_neg, "-1", "1" },
753 { &isl_val_neg, "1/2", "-1/2" },
754 { &isl_val_neg, "-1/2", "1/2" },
755 { &isl_val_neg, "infty", "-infty" },
756 { &isl_val_neg, "-infty", "infty" },
757 { &isl_val_neg, "NaN", "NaN" },
758 { &isl_val_abs, "1", "1" },
759 { &isl_val_abs, "-1", "1" },
760 { &isl_val_abs, "1/2", "1/2" },
761 { &isl_val_abs, "-1/2", "1/2" },
762 { &isl_val_abs, "infty", "infty" },
763 { &isl_val_abs, "-infty", "infty" },
764 { &isl_val_abs, "NaN", "NaN" },
765 { &isl_val_floor, "1", "1" },
766 { &isl_val_floor, "-1", "-1" },
767 { &isl_val_floor, "1/2", "0" },
768 { &isl_val_floor, "-1/2", "-1" },
769 { &isl_val_floor, "infty", "infty" },
770 { &isl_val_floor, "-infty", "-infty" },
771 { &isl_val_floor, "NaN", "NaN" },
772 { &isl_val_ceil, "1", "1" },
773 { &isl_val_ceil, "-1", "-1" },
774 { &isl_val_ceil, "1/2", "1" },
775 { &isl_val_ceil, "-1/2", "0" },
776 { &isl_val_ceil, "infty", "infty" },
777 { &isl_val_ceil, "-infty", "-infty" },
778 { &isl_val_ceil, "NaN", "NaN" },
779 { &isl_val_pow2, "-3", "1/8" },
780 { &isl_val_pow2, "-1", "1/2" },
781 { &isl_val_pow2, "1", "2" },
782 { &isl_val_pow2, "2", "4" },
783 { &isl_val_pow2, "3", "8" },
784 { &isl_val_inv, "1", "1" },
785 { &isl_val_inv, "2", "1/2" },
786 { &isl_val_inv, "1/2", "2" },
787 { &isl_val_inv, "-2", "-1/2" },
788 { &isl_val_inv, "-1/2", "-2" },
789 { &isl_val_inv, "0", "NaN" },
790 { &isl_val_inv, "NaN", "NaN" },
791 { &isl_val_inv, "infty", "0" },
792 { &isl_val_inv, "-infty", "0" },
795 /* Perform some basic tests of unary operations on isl_val objects.
797 static int test_un_val(isl_ctx *ctx)
799 int i;
800 isl_val *v;
801 __isl_give isl_val *(*fn)(__isl_take isl_val *v);
803 for (i = 0; i < ARRAY_SIZE(val_un_tests); ++i) {
804 isl_stat r;
806 v = isl_val_read_from_str(ctx, val_un_tests[i].arg);
807 fn = val_un_tests[i].op;
808 v = fn(v);
809 r = val_check_equal(v, val_un_tests[i].res);
810 isl_val_free(v);
811 if (r < 0)
812 return -1;
815 return 0;
818 struct {
819 __isl_give isl_val *(*fn)(__isl_take isl_val *v1,
820 __isl_take isl_val *v2);
821 } val_bin_op[] = {
822 ['+'] = { &isl_val_add },
823 ['-'] = { &isl_val_sub },
824 ['*'] = { &isl_val_mul },
825 ['/'] = { &isl_val_div },
826 ['g'] = { &isl_val_gcd },
827 ['m'] = { &isl_val_min },
828 ['M'] = { &isl_val_max },
831 struct {
832 const char *arg1;
833 unsigned char op;
834 const char *arg2;
835 const char *res;
836 } val_bin_tests[] = {
837 { "0", '+', "0", "0" },
838 { "1", '+', "0", "1" },
839 { "1", '+', "1", "2" },
840 { "1", '-', "1", "0" },
841 { "1", '*', "1", "1" },
842 { "1", '/', "1", "1" },
843 { "2", '*', "3", "6" },
844 { "2", '*', "1/2", "1" },
845 { "2", '*', "1/3", "2/3" },
846 { "2/3", '*', "3/5", "2/5" },
847 { "2/3", '*', "7/5", "14/15" },
848 { "2", '/', "1/2", "4" },
849 { "-2", '/', "-1/2", "4" },
850 { "-2", '/', "1/2", "-4" },
851 { "2", '/', "-1/2", "-4" },
852 { "2", '/', "2", "1" },
853 { "2", '/', "3", "2/3" },
854 { "2/3", '/', "5/3", "2/5" },
855 { "2/3", '/', "5/7", "14/15" },
856 { "0", '/', "0", "NaN" },
857 { "42", '/', "0", "NaN" },
858 { "-42", '/', "0", "NaN" },
859 { "infty", '/', "0", "NaN" },
860 { "-infty", '/', "0", "NaN" },
861 { "NaN", '/', "0", "NaN" },
862 { "0", '/', "NaN", "NaN" },
863 { "42", '/', "NaN", "NaN" },
864 { "-42", '/', "NaN", "NaN" },
865 { "infty", '/', "NaN", "NaN" },
866 { "-infty", '/', "NaN", "NaN" },
867 { "NaN", '/', "NaN", "NaN" },
868 { "0", '/', "infty", "0" },
869 { "42", '/', "infty", "0" },
870 { "-42", '/', "infty", "0" },
871 { "infty", '/', "infty", "NaN" },
872 { "-infty", '/', "infty", "NaN" },
873 { "NaN", '/', "infty", "NaN" },
874 { "0", '/', "-infty", "0" },
875 { "42", '/', "-infty", "0" },
876 { "-42", '/', "-infty", "0" },
877 { "infty", '/', "-infty", "NaN" },
878 { "-infty", '/', "-infty", "NaN" },
879 { "NaN", '/', "-infty", "NaN" },
880 { "1", '-', "1/3", "2/3" },
881 { "1/3", '+', "1/2", "5/6" },
882 { "1/2", '+', "1/2", "1" },
883 { "3/4", '-', "1/4", "1/2" },
884 { "1/2", '-', "1/3", "1/6" },
885 { "infty", '+', "42", "infty" },
886 { "infty", '+', "infty", "infty" },
887 { "42", '+', "infty", "infty" },
888 { "infty", '-', "infty", "NaN" },
889 { "infty", '*', "infty", "infty" },
890 { "infty", '*', "-infty", "-infty" },
891 { "-infty", '*', "infty", "-infty" },
892 { "-infty", '*', "-infty", "infty" },
893 { "0", '*', "infty", "NaN" },
894 { "1", '*', "infty", "infty" },
895 { "infty", '*', "0", "NaN" },
896 { "infty", '*', "42", "infty" },
897 { "42", '-', "infty", "-infty" },
898 { "infty", '+', "-infty", "NaN" },
899 { "4", 'g', "6", "2" },
900 { "5", 'g', "6", "1" },
901 { "42", 'm', "3", "3" },
902 { "42", 'M', "3", "42" },
903 { "3", 'm', "42", "3" },
904 { "3", 'M', "42", "42" },
905 { "42", 'm', "infty", "42" },
906 { "42", 'M', "infty", "infty" },
907 { "42", 'm', "-infty", "-infty" },
908 { "42", 'M', "-infty", "42" },
909 { "42", 'm', "NaN", "NaN" },
910 { "42", 'M', "NaN", "NaN" },
911 { "infty", 'm', "-infty", "-infty" },
912 { "infty", 'M', "-infty", "infty" },
915 /* Perform some basic tests of binary operations on isl_val objects.
917 static int test_bin_val(isl_ctx *ctx)
919 int i;
920 isl_val *v1, *v2, *res;
921 __isl_give isl_val *(*fn)(__isl_take isl_val *v1,
922 __isl_take isl_val *v2);
923 int ok;
925 for (i = 0; i < ARRAY_SIZE(val_bin_tests); ++i) {
926 v1 = isl_val_read_from_str(ctx, val_bin_tests[i].arg1);
927 v2 = isl_val_read_from_str(ctx, val_bin_tests[i].arg2);
928 res = isl_val_read_from_str(ctx, val_bin_tests[i].res);
929 fn = val_bin_op[val_bin_tests[i].op].fn;
930 v1 = fn(v1, v2);
931 if (isl_val_is_nan(res))
932 ok = isl_val_is_nan(v1);
933 else
934 ok = isl_val_eq(v1, res);
935 isl_val_free(v1);
936 isl_val_free(res);
937 if (ok < 0)
938 return -1;
939 if (!ok)
940 isl_die(ctx, isl_error_unknown,
941 "unexpected result", return -1);
944 return 0;
947 /* Perform some basic tests on isl_val objects.
949 static int test_val(isl_ctx *ctx)
951 if (test_un_val(ctx) < 0)
952 return -1;
953 if (test_bin_val(ctx) < 0)
954 return -1;
955 return 0;
958 /* Sets described using existentially quantified variables that
959 * can also be described without.
961 static const char *elimination_tests[] = {
962 "{ [i,j] : 2 * [i/2] + 3 * [j/4] <= 10 and 2 i = j }",
963 "{ [m, w] : exists a : w - 2m - 5 <= 3a <= m - 2w }",
964 "{ [m, w] : exists a : w >= 0 and a < m and -1 + w <= a <= 2m - w }",
967 /* Check that redundant existentially quantified variables are
968 * getting removed.
970 static int test_elimination(isl_ctx *ctx)
972 int i;
973 isl_size n;
974 isl_basic_set *bset;
976 for (i = 0; i < ARRAY_SIZE(elimination_tests); ++i) {
977 bset = isl_basic_set_read_from_str(ctx, elimination_tests[i]);
978 n = isl_basic_set_dim(bset, isl_dim_div);
979 isl_basic_set_free(bset);
980 if (n < 0)
981 return -1;
982 if (n != 0)
983 isl_die(ctx, isl_error_unknown,
984 "expecting no existentials", return -1);
987 return 0;
990 static int test_div(isl_ctx *ctx)
992 const char *str;
993 int empty;
994 isl_space *space;
995 isl_set *set;
996 isl_local_space *ls;
997 struct isl_basic_set *bset;
998 struct isl_constraint *c;
1000 /* test 1 */
1001 space = isl_space_set_alloc(ctx, 0, 3);
1002 bset = isl_basic_set_universe(isl_space_copy(space));
1003 ls = isl_local_space_from_space(space);
1005 c = isl_constraint_alloc_equality(isl_local_space_copy(ls));
1006 c = isl_constraint_set_constant_si(c, -1);
1007 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, 1);
1008 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 1, 3);
1009 bset = isl_basic_set_add_constraint(bset, c);
1011 c = isl_constraint_alloc_equality(isl_local_space_copy(ls));
1012 c = isl_constraint_set_constant_si(c, 1);
1013 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, -1);
1014 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 2, 3);
1015 bset = isl_basic_set_add_constraint(bset, c);
1017 bset = isl_basic_set_project_out(bset, isl_dim_set, 1, 2);
1019 assert(bset && bset->n_div == 1);
1020 isl_local_space_free(ls);
1021 isl_basic_set_free(bset);
1023 /* test 2 */
1024 space = isl_space_set_alloc(ctx, 0, 3);
1025 bset = isl_basic_set_universe(isl_space_copy(space));
1026 ls = isl_local_space_from_space(space);
1028 c = isl_constraint_alloc_equality(isl_local_space_copy(ls));
1029 c = isl_constraint_set_constant_si(c, 1);
1030 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, -1);
1031 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 1, 3);
1032 bset = isl_basic_set_add_constraint(bset, c);
1034 c = isl_constraint_alloc_equality(isl_local_space_copy(ls));
1035 c = isl_constraint_set_constant_si(c, -1);
1036 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, 1);
1037 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 2, 3);
1038 bset = isl_basic_set_add_constraint(bset, c);
1040 bset = isl_basic_set_project_out(bset, isl_dim_set, 1, 2);
1042 assert(bset && bset->n_div == 1);
1043 isl_local_space_free(ls);
1044 isl_basic_set_free(bset);
1046 /* test 3 */
1047 space = isl_space_set_alloc(ctx, 0, 3);
1048 bset = isl_basic_set_universe(isl_space_copy(space));
1049 ls = isl_local_space_from_space(space);
1051 c = isl_constraint_alloc_equality(isl_local_space_copy(ls));
1052 c = isl_constraint_set_constant_si(c, 1);
1053 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, -1);
1054 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 1, 3);
1055 bset = isl_basic_set_add_constraint(bset, c);
1057 c = isl_constraint_alloc_equality(isl_local_space_copy(ls));
1058 c = isl_constraint_set_constant_si(c, -3);
1059 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, 1);
1060 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 2, 4);
1061 bset = isl_basic_set_add_constraint(bset, c);
1063 bset = isl_basic_set_project_out(bset, isl_dim_set, 1, 2);
1065 assert(bset && bset->n_div == 1);
1066 isl_local_space_free(ls);
1067 isl_basic_set_free(bset);
1069 /* test 4 */
1070 space = isl_space_set_alloc(ctx, 0, 3);
1071 bset = isl_basic_set_universe(isl_space_copy(space));
1072 ls = isl_local_space_from_space(space);
1074 c = isl_constraint_alloc_equality(isl_local_space_copy(ls));
1075 c = isl_constraint_set_constant_si(c, 2);
1076 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, -1);
1077 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 1, 3);
1078 bset = isl_basic_set_add_constraint(bset, c);
1080 c = isl_constraint_alloc_equality(isl_local_space_copy(ls));
1081 c = isl_constraint_set_constant_si(c, -1);
1082 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, 1);
1083 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 2, 6);
1084 bset = isl_basic_set_add_constraint(bset, c);
1086 bset = isl_basic_set_project_out(bset, isl_dim_set, 1, 2);
1088 assert(isl_basic_set_is_empty(bset));
1089 isl_local_space_free(ls);
1090 isl_basic_set_free(bset);
1092 /* test 5 */
1093 space = isl_space_set_alloc(ctx, 0, 3);
1094 bset = isl_basic_set_universe(isl_space_copy(space));
1095 ls = isl_local_space_from_space(space);
1097 c = isl_constraint_alloc_equality(isl_local_space_copy(ls));
1098 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, -1);
1099 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 2, 3);
1100 bset = isl_basic_set_add_constraint(bset, c);
1102 c = isl_constraint_alloc_equality(isl_local_space_copy(ls));
1103 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, 1);
1104 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 1, -3);
1105 bset = isl_basic_set_add_constraint(bset, c);
1107 bset = isl_basic_set_project_out(bset, isl_dim_set, 2, 1);
1109 assert(bset && bset->n_div == 0);
1110 isl_basic_set_free(bset);
1111 isl_local_space_free(ls);
1113 /* test 6 */
1114 space = isl_space_set_alloc(ctx, 0, 3);
1115 bset = isl_basic_set_universe(isl_space_copy(space));
1116 ls = isl_local_space_from_space(space);
1118 c = isl_constraint_alloc_equality(isl_local_space_copy(ls));
1119 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, -1);
1120 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 2, 6);
1121 bset = isl_basic_set_add_constraint(bset, c);
1123 c = isl_constraint_alloc_equality(isl_local_space_copy(ls));
1124 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, 1);
1125 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 1, -3);
1126 bset = isl_basic_set_add_constraint(bset, c);
1128 bset = isl_basic_set_project_out(bset, isl_dim_set, 2, 1);
1130 assert(bset && bset->n_div == 1);
1131 isl_basic_set_free(bset);
1132 isl_local_space_free(ls);
1134 /* test 7 */
1135 /* This test is a bit tricky. We set up an equality
1136 * a + 3b + 3c = 6 e0
1137 * Normalization of divs creates _two_ divs
1138 * a = 3 e0
1139 * c - b - e0 = 2 e1
1140 * Afterwards e0 is removed again because it has coefficient -1
1141 * and we end up with the original equality and div again.
1142 * Perhaps we can avoid the introduction of this temporary div.
1144 space = isl_space_set_alloc(ctx, 0, 4);
1145 bset = isl_basic_set_universe(isl_space_copy(space));
1146 ls = isl_local_space_from_space(space);
1148 c = isl_constraint_alloc_equality(isl_local_space_copy(ls));
1149 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, -1);
1150 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 1, -3);
1151 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 2, -3);
1152 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 3, 6);
1153 bset = isl_basic_set_add_constraint(bset, c);
1155 bset = isl_basic_set_project_out(bset, isl_dim_set, 3, 1);
1157 /* Test disabled for now */
1159 assert(bset && bset->n_div == 1);
1161 isl_local_space_free(ls);
1162 isl_basic_set_free(bset);
1164 /* test 8 */
1165 space = isl_space_set_alloc(ctx, 0, 5);
1166 bset = isl_basic_set_universe(isl_space_copy(space));
1167 ls = isl_local_space_from_space(space);
1169 c = isl_constraint_alloc_equality(isl_local_space_copy(ls));
1170 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, -1);
1171 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 1, -3);
1172 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 3, -3);
1173 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 4, 6);
1174 bset = isl_basic_set_add_constraint(bset, c);
1176 c = isl_constraint_alloc_equality(isl_local_space_copy(ls));
1177 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, -1);
1178 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 2, 1);
1179 c = isl_constraint_set_constant_si(c, 1);
1180 bset = isl_basic_set_add_constraint(bset, c);
1182 bset = isl_basic_set_project_out(bset, isl_dim_set, 4, 1);
1184 /* Test disabled for now */
1186 assert(bset && bset->n_div == 1);
1188 isl_local_space_free(ls);
1189 isl_basic_set_free(bset);
1191 /* test 9 */
1192 space = isl_space_set_alloc(ctx, 0, 4);
1193 bset = isl_basic_set_universe(isl_space_copy(space));
1194 ls = isl_local_space_from_space(space);
1196 c = isl_constraint_alloc_equality(isl_local_space_copy(ls));
1197 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, 1);
1198 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 1, -1);
1199 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 2, -2);
1200 bset = isl_basic_set_add_constraint(bset, c);
1202 c = isl_constraint_alloc_equality(isl_local_space_copy(ls));
1203 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, -1);
1204 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 3, 3);
1205 c = isl_constraint_set_constant_si(c, 2);
1206 bset = isl_basic_set_add_constraint(bset, c);
1208 bset = isl_basic_set_project_out(bset, isl_dim_set, 2, 2);
1210 bset = isl_basic_set_fix_si(bset, isl_dim_set, 0, 2);
1212 assert(!isl_basic_set_is_empty(bset));
1214 isl_local_space_free(ls);
1215 isl_basic_set_free(bset);
1217 /* test 10 */
1218 space = isl_space_set_alloc(ctx, 0, 3);
1219 bset = isl_basic_set_universe(isl_space_copy(space));
1220 ls = isl_local_space_from_space(space);
1222 c = isl_constraint_alloc_equality(isl_local_space_copy(ls));
1223 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, 1);
1224 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 2, -2);
1225 bset = isl_basic_set_add_constraint(bset, c);
1227 bset = isl_basic_set_project_out(bset, isl_dim_set, 2, 1);
1229 bset = isl_basic_set_fix_si(bset, isl_dim_set, 0, 2);
1231 isl_local_space_free(ls);
1232 isl_basic_set_free(bset);
1234 str = "{ [i] : exists (e0, e1: 3e1 >= 1 + 2e0 and "
1235 "8e1 <= -1 + 5i - 5e0 and 2e1 >= 1 + 2i - 5e0) }";
1236 set = isl_set_read_from_str(ctx, str);
1237 set = isl_set_compute_divs(set);
1238 isl_set_free(set);
1239 if (!set)
1240 return -1;
1242 if (test_elimination(ctx) < 0)
1243 return -1;
1245 str = "{ [i,j,k] : 3 + i + 2j >= 0 and 2 * [(i+2j)/4] <= k }";
1246 set = isl_set_read_from_str(ctx, str);
1247 set = isl_set_remove_divs_involving_dims(set, isl_dim_set, 0, 2);
1248 set = isl_set_fix_si(set, isl_dim_set, 2, -3);
1249 empty = isl_set_is_empty(set);
1250 isl_set_free(set);
1251 if (empty < 0)
1252 return -1;
1253 if (!empty)
1254 isl_die(ctx, isl_error_unknown,
1255 "result not as accurate as expected", return -1);
1257 return 0;
1260 void test_application_case(struct isl_ctx *ctx, const char *name)
1262 char *filename;
1263 FILE *input;
1264 struct isl_basic_set *bset1, *bset2;
1265 struct isl_basic_map *bmap;
1267 filename = get_filename(ctx, name, "omega");
1268 assert(filename);
1269 input = fopen(filename, "r");
1270 assert(input);
1272 bset1 = isl_basic_set_read_from_file(ctx, input);
1273 bmap = isl_basic_map_read_from_file(ctx, input);
1275 bset1 = isl_basic_set_apply(bset1, bmap);
1277 bset2 = isl_basic_set_read_from_file(ctx, input);
1279 assert(isl_basic_set_is_equal(bset1, bset2) == 1);
1281 isl_basic_set_free(bset1);
1282 isl_basic_set_free(bset2);
1283 free(filename);
1285 fclose(input);
1288 static int test_application(isl_ctx *ctx)
1290 test_application_case(ctx, "application");
1291 test_application_case(ctx, "application2");
1293 return 0;
1296 void test_affine_hull_case(struct isl_ctx *ctx, const char *name)
1298 char *filename;
1299 FILE *input;
1300 struct isl_basic_set *bset1, *bset2;
1302 filename = get_filename(ctx, name, "polylib");
1303 assert(filename);
1304 input = fopen(filename, "r");
1305 assert(input);
1307 bset1 = isl_basic_set_read_from_file(ctx, input);
1308 bset2 = isl_basic_set_read_from_file(ctx, input);
1310 bset1 = isl_basic_set_affine_hull(bset1);
1312 assert(isl_basic_set_is_equal(bset1, bset2) == 1);
1314 isl_basic_set_free(bset1);
1315 isl_basic_set_free(bset2);
1316 free(filename);
1318 fclose(input);
1321 /* Pairs of sets and the corresponding expected results of
1322 * isl_basic_set_recession_cone.
1324 struct {
1325 const char *set;
1326 const char *cone;
1327 } recession_cone_tests[] = {
1328 { "{ [i] : 0 <= i <= 10 }", "{ [0] }" },
1329 { "{ [i] : 0 <= i }", "{ [i] : 0 <= i }" },
1330 { "{ [i] : i <= 10 }", "{ [i] : i <= 0 }" },
1331 { "{ [i] : false }", "{ [i] : false }" },
1334 /* Perform some basic isl_basic_set_recession_cone tests.
1336 static int test_recession_cone(struct isl_ctx *ctx)
1338 int i;
1340 for (i = 0; i < ARRAY_SIZE(recession_cone_tests); ++i) {
1341 const char *str;
1342 isl_basic_set *bset;
1343 isl_basic_set *cone, *expected;
1344 isl_bool equal;
1346 str = recession_cone_tests[i].set;
1347 bset = isl_basic_set_read_from_str(ctx, str);
1348 str = recession_cone_tests[i].cone;
1349 expected = isl_basic_set_read_from_str(ctx, str);
1350 cone = isl_basic_set_recession_cone(bset);
1351 equal = isl_basic_set_is_equal(cone, expected);
1352 isl_basic_set_free(cone);
1353 isl_basic_set_free(expected);
1354 if (equal < 0)
1355 return -1;
1356 if (!equal)
1357 isl_die(ctx, isl_error_unknown, "unexpected cone",
1358 return -1);
1361 return 0;
1364 int test_affine_hull(struct isl_ctx *ctx)
1366 const char *str;
1367 isl_set *set;
1368 isl_basic_set *bset, *bset2;
1369 isl_size n;
1370 isl_bool subset;
1372 test_affine_hull_case(ctx, "affine2");
1373 test_affine_hull_case(ctx, "affine");
1374 test_affine_hull_case(ctx, "affine3");
1376 str = "[m] -> { [i0] : exists (e0, e1: e1 <= 1 + i0 and "
1377 "m >= 3 and 4i0 <= 2 + m and e1 >= i0 and "
1378 "e1 >= 0 and e1 <= 2 and e1 >= 1 + 2e0 and "
1379 "2e1 <= 1 + m + 4e0 and 2e1 >= 2 - m + 4i0 - 4e0) }";
1380 set = isl_set_read_from_str(ctx, str);
1381 bset = isl_set_affine_hull(set);
1382 n = isl_basic_set_dim(bset, isl_dim_div);
1383 isl_basic_set_free(bset);
1384 if (n < 0)
1385 return -1;
1386 if (n != 0)
1387 isl_die(ctx, isl_error_unknown, "not expecting any divs",
1388 return -1);
1390 /* Check that isl_map_affine_hull is not confused by
1391 * the reordering of divs in isl_map_align_divs.
1393 str = "{ [a, b, c, 0] : exists (e0 = [(b)/32], e1 = [(c)/32]: "
1394 "32e0 = b and 32e1 = c); "
1395 "[a, 0, c, 0] : exists (e0 = [(c)/32]: 32e0 = c) }";
1396 set = isl_set_read_from_str(ctx, str);
1397 bset = isl_set_affine_hull(set);
1398 isl_basic_set_free(bset);
1399 if (!bset)
1400 return -1;
1402 str = "{ [a] : exists e0, e1, e2: 32e1 = 31 + 31a + 31e0 and "
1403 "32e2 = 31 + 31e0 }";
1404 set = isl_set_read_from_str(ctx, str);
1405 bset = isl_set_affine_hull(set);
1406 str = "{ [a] : exists e : a = 32 e }";
1407 bset2 = isl_basic_set_read_from_str(ctx, str);
1408 subset = isl_basic_set_is_subset(bset, bset2);
1409 isl_basic_set_free(bset);
1410 isl_basic_set_free(bset2);
1411 if (subset < 0)
1412 return -1;
1413 if (!subset)
1414 isl_die(ctx, isl_error_unknown, "not as accurate as expected",
1415 return -1);
1417 return 0;
1420 /* Test a special case of isl_set_plain_unshifted_simple_hull
1421 * where older versions of isl would include a redundant constraint
1422 * in the result.
1423 * Check that the result does not have any constraints.
1425 static isl_stat test_plain_unshifted_simple_hull_special(isl_ctx *ctx)
1427 const char *str;
1428 isl_bool is_universe;
1429 isl_set *set;
1430 isl_basic_set *bset;
1432 str = "{[x, y] : x = 0 or 2*((x+y)//2) <= y + 2 }";
1433 set = isl_set_read_from_str(ctx, str);
1434 bset = isl_set_plain_unshifted_simple_hull(set);
1435 is_universe = isl_basic_set_plain_is_universe(bset);
1436 isl_basic_set_free(bset);
1438 if (is_universe < 0)
1439 return isl_stat_error;
1440 if (!is_universe)
1441 isl_die(ctx, isl_error_unknown,
1442 "hull should not have any constraints",
1443 return isl_stat_error);
1445 return isl_stat_ok;
1448 /* Inputs for simple hull tests, consisting of
1449 * the specific simple hull function, the input set and the expected result.
1451 struct {
1452 __isl_give isl_basic_set *(*fn)(__isl_take isl_set *set);
1453 const char *set;
1454 const char *hull;
1455 } simple_hull_tests[] = {
1456 { &isl_set_plain_unshifted_simple_hull,
1457 "{ [i,j] : i >= 1 and j >= 1 or i >= 2 and j <= 10 }",
1458 "{ [i,j] : i >= 1 }" },
1459 { &isl_set_plain_unshifted_simple_hull,
1460 "{ [n,i,j,k] : (i mod 3 = 2 and j mod 4 = 2) or "
1461 "(j mod 4 = 2 and k mod 6 = n) }",
1462 "{ [n,i,j,k] : j mod 4 = 2 }" },
1463 { &isl_set_unshifted_simple_hull,
1464 "{ [0,x,y] : x <= -1; [1,x,y] : x <= y <= -x; [2,x,y] : x <= 1 }",
1465 "{ [t,x,y] : 0 <= t <= 2 and x <= 1 }" },
1466 { &isl_set_simple_hull,
1467 "{ [a, b] : b <= 0 and "
1468 "2*floor((-2*floor((b)/2))/5) >= a - floor((b)/2); "
1469 "[a, b] : a mod 2 = 0 }",
1470 "{ [a, b] }" },
1473 /* Basic tests for various simple hull functions.
1475 static int test_various_simple_hull(isl_ctx *ctx)
1477 int i;
1478 isl_set *set;
1479 isl_basic_set *hull, *expected;
1480 isl_bool equal;
1482 for (i = 0; i < ARRAY_SIZE(simple_hull_tests); ++i) {
1483 const char *str;
1484 str = simple_hull_tests[i].set;
1485 set = isl_set_read_from_str(ctx, str);
1486 str = simple_hull_tests[i].hull;
1487 expected = isl_basic_set_read_from_str(ctx, str);
1488 hull = simple_hull_tests[i].fn(set);
1489 equal = isl_basic_set_is_equal(hull, expected);
1490 isl_basic_set_free(hull);
1491 isl_basic_set_free(expected);
1492 if (equal < 0)
1493 return -1;
1494 if (!equal)
1495 isl_die(ctx, isl_error_unknown, "unexpected hull",
1496 return -1);
1499 return 0;
1502 static int test_simple_hull(struct isl_ctx *ctx)
1504 const char *str;
1505 isl_set *set;
1506 isl_basic_set *bset;
1507 isl_bool is_empty;
1509 str = "{ [x, y] : 3y <= 2x and y >= -2 + 2x and 2y >= 2 - x;"
1510 "[y, x] : 3y <= 2x and y >= -2 + 2x and 2y >= 2 - x }";
1511 set = isl_set_read_from_str(ctx, str);
1512 bset = isl_set_simple_hull(set);
1513 is_empty = isl_basic_set_is_empty(bset);
1514 isl_basic_set_free(bset);
1516 if (is_empty == isl_bool_error)
1517 return -1;
1519 if (is_empty == isl_bool_false)
1520 isl_die(ctx, isl_error_unknown, "Empty set should be detected",
1521 return -1);
1523 if (test_plain_unshifted_simple_hull_special(ctx) < 0)
1524 return -1;
1525 if (test_various_simple_hull(ctx) < 0)
1526 return -1;
1528 return 0;
1531 /* Inputs for isl_set_get_simple_fixed_box_hull tests.
1532 * "set" is the input set.
1533 * "offset" is the expected box offset.
1534 * "size" is the expected box size.
1536 static struct {
1537 const char *set;
1538 const char *offset;
1539 const char *size;
1540 } box_hull_tests[] = {
1541 { "{ S[x, y] : 0 <= x, y < 10 }", "{ S[0, 0] }", "{ S[10, 10] }" },
1542 { "[N] -> { S[x, y] : N <= x, y < N + 10 }",
1543 "[N] -> { S[N, N] }", "{ S[10, 10] }" },
1544 { "{ S[x, y] : 0 <= x + y, x - y < 10 }",
1545 "{ S[0, -4] }", "{ S[10, 9] }" },
1546 { "{ [i=0:10] : exists (e0, e1: 3e1 >= 1 + 2e0 and "
1547 "8e1 <= -1 + 5i - 5e0 and 2e1 >= 1 + 2i - 5e0) }",
1548 "{ [3] }", "{ [8] }" },
1549 { "[N] -> { [w = 0:17] : exists (e0: w < 2N and "
1550 "-1 + w <= e0 <= w and 2e0 >= N + w and w <= 2e0 <= 15 + w) }",
1551 "[N] -> { [N] }", "{ [9] }" },
1554 /* Perform basic isl_set_get_simple_fixed_box_hull tests.
1556 static int test_box_hull(struct isl_ctx *ctx)
1558 int i;
1560 for (i = 0; i < ARRAY_SIZE(box_hull_tests); ++i) {
1561 const char *str;
1562 isl_stat r;
1563 isl_set *set;
1564 isl_multi_aff *offset;
1565 isl_multi_val *size;
1566 isl_fixed_box *box;
1568 set = isl_set_read_from_str(ctx, box_hull_tests[i].set);
1569 box = isl_set_get_simple_fixed_box_hull(set);
1570 offset = isl_fixed_box_get_offset(box);
1571 size = isl_fixed_box_get_size(box);
1572 str = box_hull_tests[i].offset;
1573 r = multi_aff_check_plain_equal(offset, str);
1574 str = box_hull_tests[i].size;
1575 if (r >= 0)
1576 r = multi_val_check_plain_equal(size, str);
1577 isl_multi_aff_free(offset);
1578 isl_multi_val_free(size);
1579 isl_fixed_box_free(box);
1580 isl_set_free(set);
1581 if (r < 0)
1582 return -1;
1585 return 0;
1588 void test_convex_hull_case(struct isl_ctx *ctx, const char *name)
1590 char *filename;
1591 FILE *input;
1592 struct isl_basic_set *bset1, *bset2;
1593 struct isl_set *set;
1595 filename = get_filename(ctx, name, "polylib");
1596 assert(filename);
1597 input = fopen(filename, "r");
1598 assert(input);
1600 bset1 = isl_basic_set_read_from_file(ctx, input);
1601 bset2 = isl_basic_set_read_from_file(ctx, input);
1603 set = isl_basic_set_union(bset1, bset2);
1604 bset1 = isl_set_convex_hull(set);
1606 bset2 = isl_basic_set_read_from_file(ctx, input);
1608 assert(isl_basic_set_is_equal(bset1, bset2) == 1);
1610 isl_basic_set_free(bset1);
1611 isl_basic_set_free(bset2);
1612 free(filename);
1614 fclose(input);
1617 struct {
1618 const char *set;
1619 const char *hull;
1620 } convex_hull_tests[] = {
1621 { "{ [i0, i1, i2] : (i2 = 1 and i0 = 0 and i1 >= 0) or "
1622 "(i0 = 1 and i1 = 0 and i2 = 1) or "
1623 "(i0 = 0 and i1 = 0 and i2 = 0) }",
1624 "{ [i0, i1, i2] : i0 >= 0 and i2 >= i0 and i2 <= 1 and i1 >= 0 }" },
1625 { "[n] -> { [i0, i1, i0] : i0 <= -4 + n; "
1626 "[i0, i0, i2] : n = 6 and i0 >= 0 and i2 <= 7 - i0 and "
1627 "i2 <= 5 and i2 >= 4; "
1628 "[3, i1, 3] : n = 5 and i1 <= 2 and i1 >= 0 }",
1629 "[n] -> { [i0, i1, i2] : i2 <= -1 + n and 2i2 <= -6 + 3n - i0 and "
1630 "i2 <= 5 + i0 and i2 >= i0 }" },
1631 { "{ [x, y] : 3y <= 2x and y >= -2 + 2x and 2y >= 2 - x }",
1632 "{ [x, y] : 1 = 0 }" },
1633 { "{ [x, y, z] : 0 <= x, y, z <= 10; [x, y, 0] : x >= 0 and y > 0; "
1634 "[x, y, 0] : x >= 0 and y < 0 }",
1635 "{ [x, y, z] : x >= 0 and 0 <= z <= 10 }" },
1636 { "{ [a, b, c] : a <= 1 and -a < b <= 1 and 0 <= c <= 2 - a - b and "
1637 "c <= a; "
1638 "[0, 2, 0]; [3, 1, 0] }",
1639 "{ [a, b, c] : b > -a and 2b >= -1 + a and 0 <= c <= a and "
1640 "5c <= 6 - a - 3b }" },
1643 static int test_convex_hull_algo(isl_ctx *ctx, int convex)
1645 int i;
1646 int orig_convex = ctx->opt->convex;
1647 ctx->opt->convex = convex;
1649 test_convex_hull_case(ctx, "convex0");
1650 test_convex_hull_case(ctx, "convex1");
1651 test_convex_hull_case(ctx, "convex2");
1652 test_convex_hull_case(ctx, "convex3");
1653 test_convex_hull_case(ctx, "convex4");
1654 test_convex_hull_case(ctx, "convex5");
1655 test_convex_hull_case(ctx, "convex6");
1656 test_convex_hull_case(ctx, "convex7");
1657 test_convex_hull_case(ctx, "convex8");
1658 test_convex_hull_case(ctx, "convex9");
1659 test_convex_hull_case(ctx, "convex10");
1660 test_convex_hull_case(ctx, "convex11");
1661 test_convex_hull_case(ctx, "convex12");
1662 test_convex_hull_case(ctx, "convex13");
1663 test_convex_hull_case(ctx, "convex14");
1664 test_convex_hull_case(ctx, "convex15");
1666 for (i = 0; i < ARRAY_SIZE(convex_hull_tests); ++i) {
1667 isl_set *set1, *set2;
1668 int equal;
1670 set1 = isl_set_read_from_str(ctx, convex_hull_tests[i].set);
1671 set2 = isl_set_read_from_str(ctx, convex_hull_tests[i].hull);
1672 set1 = isl_set_from_basic_set(isl_set_convex_hull(set1));
1673 equal = isl_set_is_equal(set1, set2);
1674 isl_set_free(set1);
1675 isl_set_free(set2);
1677 if (equal < 0)
1678 return -1;
1679 if (!equal)
1680 isl_die(ctx, isl_error_unknown,
1681 "unexpected convex hull", return -1);
1684 ctx->opt->convex = orig_convex;
1686 return 0;
1689 static int test_convex_hull(isl_ctx *ctx)
1691 if (test_convex_hull_algo(ctx, ISL_CONVEX_HULL_FM) < 0)
1692 return -1;
1693 if (test_convex_hull_algo(ctx, ISL_CONVEX_HULL_WRAP) < 0)
1694 return -1;
1695 return 0;
1698 /* Check that computing the gist of "map" with respect to "context"
1699 * does not make any copy of "map" get marked empty.
1700 * Earlier versions of isl would end up doing that.
1702 static isl_stat test_gist_empty_pair(isl_ctx *ctx, const char *map,
1703 const char *context)
1705 isl_map *m1, *m2, *m3;
1706 isl_bool empty_before, empty_after;
1708 m1 = isl_map_read_from_str(ctx, map);
1709 m2 = isl_map_read_from_str(ctx, context);
1710 m3 = isl_map_copy(m1);
1711 empty_before = isl_map_is_empty(m3);
1712 m1 = isl_map_gist(m1, m2);
1713 empty_after = isl_map_is_empty(m3);
1714 isl_map_free(m1);
1715 isl_map_free(m3);
1717 if (empty_before < 0 || empty_after < 0)
1718 return isl_stat_error;
1719 if (empty_before)
1720 isl_die(ctx, isl_error_unknown, "map should not be empty",
1721 return isl_stat_error);
1722 if (empty_after)
1723 isl_die(ctx, isl_error_unknown, "map should still not be empty",
1724 return isl_stat_error);
1726 return isl_stat_ok;
1729 /* Check that computing a gist does not make any copy of the input
1730 * get marked empty.
1731 * Earlier versions of isl would end up doing that on some pairs of inputs.
1733 static isl_stat test_gist_empty(isl_ctx *ctx)
1735 const char *map, *context;
1737 map = "{ [] -> [a, b, c] : 2b = 1 + a }";
1738 context = "{ [] -> [a, b, c] : 2c = 2 + a }";
1739 if (test_gist_empty_pair(ctx, map, context) < 0)
1740 return isl_stat_error;
1741 map = "{ [] -> [0, 0] }";
1742 context = "{ [] -> [a, b] : a > b }";
1743 if (test_gist_empty_pair(ctx, map, context) < 0)
1744 return isl_stat_error;
1746 return isl_stat_ok;
1749 /* Inputs to isl_map_plain_gist_basic_map, along with the expected output.
1751 struct {
1752 const char *map;
1753 const char *context;
1754 const char *gist;
1755 } plain_gist_tests[] = {
1756 { "{ [i] -> [j] : i >= 1 and j >= 1 or i >= 2 and j <= 10 }",
1757 "{ [i] -> [j] : i >= 1 }",
1758 "{ [i] -> [j] : j >= 1 or i >= 2 and j <= 10 }" },
1759 { "{ [n] -> [i,j,k] : (i mod 3 = 2 and j mod 4 = 2) or "
1760 "(j mod 4 = 2 and k mod 6 = n) }",
1761 "{ [n] -> [i,j,k] : j mod 4 = 2 }",
1762 "{ [n] -> [i,j,k] : (i mod 3 = 2) or (k mod 6 = n) }" },
1763 { "{ [i] -> [j] : i > j and (exists a,b : i <= 2a + 5b <= 2) }",
1764 "{ [i] -> [j] : i > j }",
1765 "{ [i] -> [j] : exists a,b : i <= 2a + 5b <= 2 }" },
1768 /* Basic tests for isl_map_plain_gist_basic_map.
1770 static int test_plain_gist(isl_ctx *ctx)
1772 int i;
1774 for (i = 0; i < ARRAY_SIZE(plain_gist_tests); ++i) {
1775 const char *str;
1776 int equal;
1777 isl_map *map, *gist;
1778 isl_basic_map *context;
1780 map = isl_map_read_from_str(ctx, plain_gist_tests[i].map);
1781 str = plain_gist_tests[i].context;
1782 context = isl_basic_map_read_from_str(ctx, str);
1783 map = isl_map_plain_gist_basic_map(map, context);
1784 gist = isl_map_read_from_str(ctx, plain_gist_tests[i].gist);
1785 equal = isl_map_is_equal(map, gist);
1786 isl_map_free(map);
1787 isl_map_free(gist);
1788 if (equal < 0)
1789 return -1;
1790 if (!equal)
1791 isl_die(ctx, isl_error_unknown,
1792 "incorrect gist result", return -1);
1795 return 0;
1798 /* Inputs for isl_basic_set_gist tests that are expected to fail.
1800 struct {
1801 const char *set;
1802 const char *context;
1803 } gist_fail_tests[] = {
1804 { "{ [i] : exists (e0, e1: 3e1 >= 1 + 2e0 and "
1805 "8e1 <= -1 + 5i - 5e0 and 2e1 >= 1 + 2i - 5e0) }",
1806 "{ [i] : i >= 0 }" },
1809 /* Check that isl_basic_set_gist fails (gracefully) when expected.
1810 * In particular, the user should be able to recover from the failure.
1812 static isl_stat test_gist_fail(struct isl_ctx *ctx)
1814 int i, n;
1815 int on_error;
1817 on_error = isl_options_get_on_error(ctx);
1818 isl_options_set_on_error(ctx, ISL_ON_ERROR_CONTINUE);
1819 n = ARRAY_SIZE(gist_fail_tests);
1820 for (i = 0; i < n; ++i) {
1821 const char *str;
1822 isl_basic_set *bset, *context;
1824 bset = isl_basic_set_read_from_str(ctx, gist_fail_tests[i].set);
1825 str = gist_fail_tests[i].context;
1826 context = isl_basic_set_read_from_str(ctx, str);
1827 bset = isl_basic_set_gist(bset, context);
1828 isl_basic_set_free(bset);
1829 if (bset)
1830 break;
1832 isl_options_set_on_error(ctx, on_error);
1833 if (i < n)
1834 isl_die(ctx, isl_error_unknown,
1835 "operation not expected to succeed",
1836 return isl_stat_error);
1838 return isl_stat_ok;
1841 struct {
1842 const char *set;
1843 const char *context;
1844 const char *gist;
1845 } gist_tests[] = {
1846 { "{ [1, -1, 3] }",
1847 "{ [1, b, 2 - b] : -1 <= b <= 2 }",
1848 "{ [a, -1, c] }" },
1849 { "{ [a, b, c] : a <= 15 and a >= 1 }",
1850 "{ [a, b, c] : exists (e0 = floor((-1 + a)/16): a >= 1 and "
1851 "c <= 30 and 32e0 >= -62 + 2a + 2b - c and b >= 0) }",
1852 "{ [a, b, c] : a <= 15 }" },
1853 { "{ : }", "{ : 1 = 0 }", "{ : }" },
1854 { "{ : 1 = 0 }", "{ : 1 = 0 }", "{ : }" },
1855 { "[M] -> { [x] : exists (e0 = floor((-2 + x)/3): 3e0 = -2 + x) }",
1856 "[M] -> { [3M] }" , "[M] -> { [x] : 1 = 0 }" },
1857 { "{ [m, n, a, b] : a <= 2147 + n }",
1858 "{ [m, n, a, b] : (m >= 1 and n >= 1 and a <= 2148 - m and "
1859 "b <= 2148 - n and b >= 0 and b >= 2149 - n - a) or "
1860 "(n >= 1 and a >= 0 and b <= 2148 - n - a and "
1861 "b >= 0) }",
1862 "{ [m, n, ku, kl] }" },
1863 { "{ [a, a, b] : a >= 10 }",
1864 "{ [a, b, c] : c >= a and c <= b and c >= 2 }",
1865 "{ [a, a, b] : a >= 10 }" },
1866 { "{ [i, j] : i >= 0 and i + j >= 0 }", "{ [i, j] : i <= 0 }",
1867 "{ [0, j] : j >= 0 }" },
1868 /* Check that no constraints on i6 are introduced in the gist */
1869 { "[t1] -> { [i4, i6] : exists (e0 = floor((1530 - 4t1 - 5i4)/20): "
1870 "20e0 <= 1530 - 4t1 - 5i4 and 20e0 >= 1511 - 4t1 - 5i4 and "
1871 "5e0 <= 381 - t1 and i4 <= 1) }",
1872 "[t1] -> { [i4, i6] : exists (e0 = floor((-t1 + i6)/5): "
1873 "5e0 = -t1 + i6 and i6 <= 6 and i6 >= 3) }",
1874 "[t1] -> { [i4, i6] : exists (e0 = floor((1530 - 4t1 - 5i4)/20): "
1875 "i4 <= 1 and 5e0 <= 381 - t1 and 20e0 <= 1530 - 4t1 - 5i4 and "
1876 "20e0 >= 1511 - 4t1 - 5i4) }" },
1877 /* Check that no constraints on i6 are introduced in the gist */
1878 { "[t1, t2] -> { [i4, i5, i6] : exists (e0 = floor((1 + i4)/2), "
1879 "e1 = floor((1530 - 4t1 - 5i4)/20), "
1880 "e2 = floor((-4t1 - 5i4 + 10*floor((1 + i4)/2))/20), "
1881 "e3 = floor((-1 + i4)/2): t2 = 0 and 2e3 = -1 + i4 and "
1882 "20e2 >= -19 - 4t1 - 5i4 + 10e0 and 5e2 <= 1 - t1 and "
1883 "2e0 <= 1 + i4 and 2e0 >= i4 and "
1884 "20e1 <= 1530 - 4t1 - 5i4 and "
1885 "20e1 >= 1511 - 4t1 - 5i4 and i4 <= 1 and "
1886 "5e1 <= 381 - t1 and 20e2 <= -4t1 - 5i4 + 10e0) }",
1887 "[t1, t2] -> { [i4, i5, i6] : exists (e0 = floor((-17 + i4)/2), "
1888 "e1 = floor((-t1 + i6)/5): 5e1 = -t1 + i6 and "
1889 "2e0 <= -17 + i4 and 2e0 >= -18 + i4 and "
1890 "10e0 <= -91 + 5i4 + 4i6 and "
1891 "10e0 >= -105 + 5i4 + 4i6) }",
1892 "[t1, t2] -> { [i4, i5, i6] : exists (e0 = floor((381 - t1)/5), "
1893 "e1 = floor((-1 + i4)/2): t2 = 0 and 2e1 = -1 + i4 and "
1894 "i4 <= 1 and 5e0 <= 381 - t1 and 20e0 >= 1511 - 4t1 - 5i4) }" },
1895 { "{ [0, 0, q, p] : -5 <= q <= 5 and p >= 0 }",
1896 "{ [a, b, q, p] : b >= 1 + a }",
1897 "{ [a, b, q, p] : false }" },
1898 { "[n] -> { [x] : x = n && x mod 32 = 0 }",
1899 "[n] -> { [x] : x mod 32 = 0 }",
1900 "[n] -> { [x = n] }" },
1901 { "{ [x] : x mod 6 = 0 }", "{ [x] : x mod 3 = 0 }",
1902 "{ [x] : x mod 2 = 0 }" },
1903 { "{ [x] : x mod 3200 = 0 }", "{ [x] : x mod 10000 = 0 }",
1904 "{ [x] : x mod 128 = 0 }" },
1905 { "{ [x] : x mod 3200 = 0 }", "{ [x] : x mod 10 = 0 }",
1906 "{ [x] : x mod 3200 = 0 }" },
1907 { "{ [a, b, c] : a mod 2 = 0 and a = c }",
1908 "{ [a, b, c] : b mod 2 = 0 and b = c }",
1909 "{ [a, b, c = a] }" },
1910 { "{ [a, b, c] : a mod 6 = 0 and a = c }",
1911 "{ [a, b, c] : b mod 2 = 0 and b = c }",
1912 "{ [a, b, c = a] : a mod 3 = 0 }" },
1913 { "{ [x] : 0 <= x <= 4 or 6 <= x <= 9 }",
1914 "{ [x] : 1 <= x <= 3 or 7 <= x <= 8 }",
1915 "{ [x] }" },
1916 { "{ [x,y] : x < 0 and 0 <= y <= 4 or x >= -2 and -x <= y <= 10 + x }",
1917 "{ [x,y] : 1 <= y <= 3 }",
1918 "{ [x,y] }" },
1921 /* Check that isl_set_gist behaves as expected.
1923 * For the test cases in gist_tests, besides checking that the result
1924 * is as expected, also check that applying the gist operation does
1925 * not modify the input set (an earlier version of isl would do that) and
1926 * that the test case is consistent, i.e., that the gist has the same
1927 * intersection with the context as the input set.
1929 static int test_gist(struct isl_ctx *ctx)
1931 int i;
1932 const char *str;
1933 isl_basic_set *bset1, *bset2;
1934 isl_map *map1, *map2;
1935 isl_bool equal;
1936 isl_size n_div;
1938 for (i = 0; i < ARRAY_SIZE(gist_tests); ++i) {
1939 isl_bool equal_input, equal_intersection;
1940 isl_set *set1, *set2, *copy, *context;
1942 set1 = isl_set_read_from_str(ctx, gist_tests[i].set);
1943 context = isl_set_read_from_str(ctx, gist_tests[i].context);
1944 copy = isl_set_copy(set1);
1945 set1 = isl_set_gist(set1, isl_set_copy(context));
1946 set2 = isl_set_read_from_str(ctx, gist_tests[i].gist);
1947 equal = isl_set_is_equal(set1, set2);
1948 isl_set_free(set1);
1949 set1 = isl_set_read_from_str(ctx, gist_tests[i].set);
1950 equal_input = isl_set_is_equal(set1, copy);
1951 isl_set_free(copy);
1952 set1 = isl_set_intersect(set1, isl_set_copy(context));
1953 set2 = isl_set_intersect(set2, context);
1954 equal_intersection = isl_set_is_equal(set1, set2);
1955 isl_set_free(set2);
1956 isl_set_free(set1);
1957 if (equal < 0 || equal_input < 0 || equal_intersection < 0)
1958 return -1;
1959 if (!equal)
1960 isl_die(ctx, isl_error_unknown,
1961 "incorrect gist result", return -1);
1962 if (!equal_input)
1963 isl_die(ctx, isl_error_unknown,
1964 "gist modified input", return -1);
1965 if (!equal_input)
1966 isl_die(ctx, isl_error_unknown,
1967 "inconsistent gist test case", return -1);
1970 if (test_gist_fail(ctx) < 0)
1971 return -1;
1973 str = "[p0, p2, p3, p5, p6, p10] -> { [] : "
1974 "exists (e0 = [(15 + p0 + 15p6 + 15p10)/16], e1 = [(p5)/8], "
1975 "e2 = [(p6)/128], e3 = [(8p2 - p5)/128], "
1976 "e4 = [(128p3 - p6)/4096]: 8e1 = p5 and 128e2 = p6 and "
1977 "128e3 = 8p2 - p5 and 4096e4 = 128p3 - p6 and p2 >= 0 and "
1978 "16e0 >= 16 + 16p6 + 15p10 and p2 <= 15 and p3 >= 0 and "
1979 "p3 <= 31 and p6 >= 128p3 and p5 >= 8p2 and p10 >= 0 and "
1980 "16e0 <= 15 + p0 + 15p6 + 15p10 and 16e0 >= p0 + 15p6 + 15p10 and "
1981 "p10 <= 15 and p10 <= -1 + p0 - p6) }";
1982 bset1 = isl_basic_set_read_from_str(ctx, str);
1983 str = "[p0, p2, p3, p5, p6, p10] -> { [] : exists (e0 = [(p5)/8], "
1984 "e1 = [(p6)/128], e2 = [(8p2 - p5)/128], "
1985 "e3 = [(128p3 - p6)/4096]: 8e0 = p5 and 128e1 = p6 and "
1986 "128e2 = 8p2 - p5 and 4096e3 = 128p3 - p6 and p5 >= -7 and "
1987 "p2 >= 0 and 8p2 <= -1 + p0 and p2 <= 15 and p3 >= 0 and "
1988 "p3 <= 31 and 128p3 <= -1 + p0 and p6 >= -127 and "
1989 "p5 <= -1 + p0 and p6 <= -1 + p0 and p6 >= 128p3 and "
1990 "p0 >= 1 and p5 >= 8p2 and p10 >= 0 and p10 <= 15 ) }";
1991 bset2 = isl_basic_set_read_from_str(ctx, str);
1992 bset1 = isl_basic_set_gist(bset1, bset2);
1993 assert(bset1 && bset1->n_div == 0);
1994 isl_basic_set_free(bset1);
1996 /* Check that the integer divisions of the second disjunct
1997 * do not spread to the first disjunct.
1999 str = "[t1] -> { S_0[] -> A[o0] : (exists (e0 = [(-t1 + o0)/16]: "
2000 "16e0 = -t1 + o0 and o0 >= 0 and o0 <= 15 and t1 >= 0)) or "
2001 "(exists (e0 = [(-1 + t1)/16], "
2002 "e1 = [(-16 + t1 - 16e0)/4294967296]: "
2003 "4294967296e1 = -16 + t1 - o0 - 16e0 and "
2004 "16e0 <= -1 + t1 and 16e0 >= -16 + t1 and o0 >= 0 and "
2005 "o0 <= 4294967295 and t1 <= -1)) }";
2006 map1 = isl_map_read_from_str(ctx, str);
2007 str = "[t1] -> { S_0[] -> A[o0] : t1 >= 0 and t1 <= 4294967295 }";
2008 map2 = isl_map_read_from_str(ctx, str);
2009 map1 = isl_map_gist(map1, map2);
2010 if (!map1)
2011 return -1;
2012 if (map1->n != 1)
2013 isl_die(ctx, isl_error_unknown, "expecting single disjunct",
2014 isl_map_free(map1); return -1);
2015 n_div = isl_basic_map_dim(map1->p[0], isl_dim_div);
2016 isl_map_free(map1);
2017 if (n_div < 0)
2018 return -1;
2019 if (n_div != 1)
2020 isl_die(ctx, isl_error_unknown, "expecting single div",
2021 return -1);
2023 if (test_gist_empty(ctx) < 0)
2024 return -1;
2025 if (test_plain_gist(ctx) < 0)
2026 return -1;
2028 return 0;
2031 int test_coalesce_set(isl_ctx *ctx, const char *str, int check_one)
2033 isl_set *set, *set2;
2034 int equal;
2035 int one;
2037 set = isl_set_read_from_str(ctx, str);
2038 set = isl_set_coalesce(set);
2039 set2 = isl_set_read_from_str(ctx, str);
2040 equal = isl_set_is_equal(set, set2);
2041 one = set && set->n == 1;
2042 isl_set_free(set);
2043 isl_set_free(set2);
2045 if (equal < 0)
2046 return -1;
2047 if (!equal)
2048 isl_die(ctx, isl_error_unknown,
2049 "coalesced set not equal to input", return -1);
2050 if (check_one && !one)
2051 isl_die(ctx, isl_error_unknown,
2052 "coalesced set should not be a union", return -1);
2054 return 0;
2057 /* Inputs for coalescing tests with unbounded wrapping.
2058 * "str" is a string representation of the input set.
2059 * "single_disjunct" is set if we expect the result to consist of
2060 * a single disjunct.
2062 struct {
2063 int single_disjunct;
2064 const char *str;
2065 } coalesce_unbounded_tests[] = {
2066 { 1, "{ [x,y,z] : y + 2 >= 0 and x - y + 1 >= 0 and "
2067 "-x - y + 1 >= 0 and -3 <= z <= 3;"
2068 "[x,y,z] : -x+z + 20 >= 0 and -x-z + 20 >= 0 and "
2069 "x-z + 20 >= 0 and x+z + 20 >= 0 and "
2070 "-10 <= y <= 0}" },
2071 { 1, "{ [x,y] : 0 <= x,y <= 10; [5,y]: 4 <= y <= 11 }" },
2072 { 1, "{ [x,0,0] : -5 <= x <= 5; [0,y,1] : -5 <= y <= 5 }" },
2073 { 1, "{ [x,y] : 0 <= x <= 10 and 0 >= y >= -1 and x+y >= 0; [0,1] }" },
2074 { 1, "{ [x,y] : (0 <= x,y <= 4) or (2 <= x,y <= 5 and x + y <= 9) }" },
2075 { 0, "{ [x, y, z] : 0 <= x,y,z <= 100 and 0 < z <= 2 + 2x + 2y; "
2076 "[x, y, 0] : x,y <= 100 and y <= 9 + 11x and x <= 9 + 11y }" },
2077 { 1, "{ [0:1, 0:1]; [0, 2:3] }" },
2078 { 1, "{ [0:1, 0:1]; [0, 2:3]; [1, -2:-1] }" },
2079 { 1, "{ [0:3, 0:1]; [1:2, 2:5] }" },
2080 { 1, "{ [0:3, 0:1]; [0:2, 2:5] }" },
2081 { 1, "{ [0:3, 0:1]; [1:3, 2:5] }" },
2082 { 0, "{ [0:3, 0:1]; [1:4, 2:5] }" },
2083 { 0, "{ [0:3, 0:1]; [1:5, 2:5] }" },
2086 /* Test the functionality of isl_set_coalesce with the bounded wrapping
2087 * option turned off.
2089 int test_coalesce_unbounded_wrapping(isl_ctx *ctx)
2091 int i;
2092 int r = 0;
2093 int bounded;
2095 bounded = isl_options_get_coalesce_bounded_wrapping(ctx);
2096 isl_options_set_coalesce_bounded_wrapping(ctx, 0);
2098 for (i = 0; i < ARRAY_SIZE(coalesce_unbounded_tests); ++i) {
2099 const char *str = coalesce_unbounded_tests[i].str;
2100 int check_one = coalesce_unbounded_tests[i].single_disjunct;
2101 if (test_coalesce_set(ctx, str, check_one) >= 0)
2102 continue;
2103 r = -1;
2104 break;
2107 isl_options_set_coalesce_bounded_wrapping(ctx, bounded);
2109 return r;
2112 /* Inputs for coalescing tests.
2113 * "str" is a string representation of the input set.
2114 * "single_disjunct" is set if we expect the result to consist of
2115 * a single disjunct.
2117 struct {
2118 int single_disjunct;
2119 const char *str;
2120 } coalesce_tests[] = {
2121 { 1, "{[x,y]: x >= 0 & x <= 10 & y >= 0 & y <= 10 or "
2122 "y >= x & x >= 2 & 5 >= y }" },
2123 { 1, "{[x,y]: y >= 0 & 2x + y <= 30 & y <= 10 & x >= 0 or "
2124 "x + y >= 10 & y <= x & x + y <= 20 & y >= 0}" },
2125 { 0, "{[x,y]: y >= 0 & 2x + y <= 30 & y <= 10 & x >= 0 or "
2126 "x + y >= 10 & y <= x & x + y <= 19 & y >= 0}" },
2127 { 1, "{[x,y]: y >= 0 & x <= 5 & y <= x or "
2128 "y >= 0 & x >= 6 & x <= 10 & y <= x}" },
2129 { 0, "{[x,y]: y >= 0 & x <= 5 & y <= x or "
2130 "y >= 0 & x >= 7 & x <= 10 & y <= x}" },
2131 { 0, "{[x,y]: y >= 0 & x <= 5 & y <= x or "
2132 "y >= 0 & x >= 6 & x <= 10 & y + 1 <= x}" },
2133 { 1, "{[x,y]: y >= 0 & x <= 5 & y <= x or y >= 0 & x = 6 & y <= 6}" },
2134 { 0, "{[x,y]: y >= 0 & x <= 5 & y <= x or y >= 0 & x = 7 & y <= 6}" },
2135 { 1, "{[x,y]: y >= 0 & x <= 5 & y <= x or y >= 0 & x = 6 & y <= 5}" },
2136 { 0, "{[x,y]: y >= 0 & x <= 5 & y <= x or y >= 0 & x = 6 & y <= 7}" },
2137 { 1, "[n] -> { [i] : i = 1 and n >= 2 or 2 <= i and i <= n }" },
2138 { 0, "{[x,y] : x >= 0 and y >= 0 or 0 <= y and y <= 5 and x = -1}" },
2139 { 1, "[n] -> { [i] : 1 <= i and i <= n - 1 or 2 <= i and i <= n }" },
2140 { 0, "[n] -> { [[i0] -> [o0]] : exists (e0 = [(i0)/4], e1 = [(o0)/4], "
2141 "e2 = [(n)/2], e3 = [(-2 + i0)/4], e4 = [(-2 + o0)/4], "
2142 "e5 = [(-2n + i0)/4]: 2e2 = n and 4e3 = -2 + i0 and "
2143 "4e4 = -2 + o0 and i0 >= 8 + 2n and o0 >= 2 + i0 and "
2144 "o0 <= 56 + 2n and o0 <= -12 + 4n and i0 <= 57 + 2n and "
2145 "i0 <= -11 + 4n and o0 >= 6 + 2n and 4e0 <= i0 and "
2146 "4e0 >= -3 + i0 and 4e1 <= o0 and 4e1 >= -3 + o0 and "
2147 "4e5 <= -2n + i0 and 4e5 >= -3 - 2n + i0);"
2148 "[[i0] -> [o0]] : exists (e0 = [(i0)/4], e1 = [(o0)/4], "
2149 "e2 = [(n)/2], e3 = [(-2 + i0)/4], e4 = [(-2 + o0)/4], "
2150 "e5 = [(-2n + i0)/4]: 2e2 = n and 4e3 = -2 + i0 and "
2151 "4e4 = -2 + o0 and 2e0 >= 3 + n and e0 <= -4 + n and "
2152 "2e0 <= 27 + n and e1 <= -4 + n and 2e1 <= 27 + n and "
2153 "2e1 >= 2 + n and e1 >= 1 + e0 and i0 >= 7 + 2n and "
2154 "i0 <= -11 + 4n and i0 <= 57 + 2n and 4e0 <= -2 + i0 and "
2155 "4e0 >= -3 + i0 and o0 >= 6 + 2n and o0 <= -11 + 4n and "
2156 "o0 <= 57 + 2n and 4e1 <= -2 + o0 and 4e1 >= -3 + o0 and "
2157 "4e5 <= -2n + i0 and 4e5 >= -3 - 2n + i0 ) }" },
2158 { 0, "[n, m] -> { [o0, o2, o3] : (o3 = 1 and o0 >= 1 + m and "
2159 "o0 <= n + m and o2 <= m and o0 >= 2 + n and o2 >= 3) or "
2160 "(o0 >= 2 + n and o0 >= 1 + m and o0 <= n + m and n >= 1 and "
2161 "o3 <= -1 + o2 and o3 >= 1 - m + o2 and o3 >= 2 and o3 <= n) }" },
2162 { 0, "[M, N] -> { [[i0, i1, i2, i3, i4, i5, i6] -> "
2163 "[o0, o1, o2, o3, o4, o5, o6]] : "
2164 "(o6 <= -4 + 2M - 2N + i0 + i1 - i2 + i6 - o0 - o1 + o2 and "
2165 "o3 <= -2 + i3 and o6 >= 2 + i0 + i3 + i6 - o0 - o3 and "
2166 "o6 >= 2 - M + N + i3 + i4 + i6 - o3 - o4 and o0 <= -1 + i0 and "
2167 "o4 >= 4 - 3M + 3N - i0 - i1 + i2 + 2i3 + i4 + o0 + o1 - o2 - 2o3 "
2168 "and o6 <= -3 + 2M - 2N + i3 + i4 - i5 + i6 - o3 - o4 + o5 and "
2169 "2o6 <= -5 + 5M - 5N + 2i0 + i1 - i2 - i5 + 2i6 - 2o0 - o1 + o2 + o5 "
2170 "and o6 >= 2i0 + i1 + i6 - 2o0 - o1 and "
2171 "3o6 <= -5 + 4M - 4N + 2i0 + i1 - i2 + 2i3 + i4 - i5 + 3i6 "
2172 "- 2o0 - o1 + o2 - 2o3 - o4 + o5) or "
2173 "(N >= 2 and o3 <= -1 + i3 and o0 <= -1 + i0 and "
2174 "o6 >= i3 + i6 - o3 and M >= 0 and "
2175 "2o6 >= 1 + i0 + i3 + 2i6 - o0 - o3 and "
2176 "o6 >= 1 - M + i0 + i6 - o0 and N >= 2M and o6 >= i0 + i6 - o0) }" },
2177 { 0, "[M, N] -> { [o0] : (o0 = 0 and M >= 1 and N >= 2) or "
2178 "(o0 = 0 and M >= 1 and N >= 2M and N >= 2 + M) or "
2179 "(o0 = 0 and M >= 2 and N >= 3) or "
2180 "(M = 0 and o0 = 0 and N >= 3) }" },
2181 { 0, "{ [i0, i1, i2, i3] : (i1 = 10i0 and i0 >= 1 and 10i0 <= 100 and "
2182 "i3 <= 9 + 10 i2 and i3 >= 1 + 10i2 and i3 >= 0) or "
2183 "(i1 <= 9 + 10i0 and i1 >= 1 + 10i0 and i2 >= 0 and "
2184 "i0 >= 0 and i1 <= 100 and i3 <= 9 + 10i2 and i3 >= 1 + 10i2) }" },
2185 { 0, "[M] -> { [i1] : (i1 >= 2 and i1 <= M) or (i1 = M and M >= 1) }" },
2186 { 0, "{[x,y] : x,y >= 0; [x,y] : 10 <= x <= 20 and y >= -1 }" },
2187 { 1, "{ [x, y] : (x >= 1 and y >= 1 and x <= 2 and y <= 2) or "
2188 "(y = 3 and x = 1) }" },
2189 { 1, "[M] -> { [i0, i1, i2, i3, i4] : (i1 >= 3 and i4 >= 2 + i2 and "
2190 "i2 >= 2 and i0 >= 2 and i3 >= 1 + i2 and i0 <= M and "
2191 "i1 <= M and i3 <= M and i4 <= M) or "
2192 "(i1 >= 2 and i4 >= 1 + i2 and i2 >= 2 and i0 >= 2 and "
2193 "i3 >= 1 + i2 and i0 <= M and i1 <= -1 + M and i3 <= M and "
2194 "i4 <= -1 + M) }" },
2195 { 1, "{ [x, y] : (x >= 0 and y >= 0 and x <= 10 and y <= 10) or "
2196 "(x >= 1 and y >= 1 and x <= 11 and y <= 11) }" },
2197 { 0, "{[x,0] : x >= 0; [x,1] : x <= 20}" },
2198 { 1, "{ [x, 1 - x] : 0 <= x <= 1; [0,0] }" },
2199 { 1, "{ [0,0]; [i,i] : 1 <= i <= 10 }" },
2200 { 0, "{ [0,0]; [i,j] : 1 <= i,j <= 10 }" },
2201 { 1, "{ [0,0]; [i,2i] : 1 <= i <= 10 }" },
2202 { 0, "{ [0,0]; [i,2i] : 2 <= i <= 10 }" },
2203 { 0, "{ [1,0]; [i,2i] : 1 <= i <= 10 }" },
2204 { 0, "{ [0,1]; [i,2i] : 1 <= i <= 10 }" },
2205 { 0, "{ [a, b] : exists e : 2e = a and "
2206 "a >= 0 and (a <= 3 or (b <= 0 and b >= -4 + a)) }" },
2207 { 0, "{ [i, j, i', j'] : i <= 2 and j <= 2 and "
2208 "j' >= -1 + 2i + j - 2i' and i' <= -1 + i and "
2209 "j >= 1 and j' <= i + j - i' and i >= 1; "
2210 "[1, 1, 1, 1] }" },
2211 { 1, "{ [i,j] : exists a,b : i = 2a and j = 3b; "
2212 "[i,j] : exists a : j = 3a }" },
2213 { 1, "{ [a, b, c] : (c <= 7 - b and b <= 1 and b >= 0 and "
2214 "c >= 3 + b and b <= 3 + 8a and b >= -26 + 8a and "
2215 "a >= 3) or "
2216 "(b <= 1 and c <= 7 and b >= 0 and c >= 4 + b and "
2217 "b <= 3 + 8a and b >= -26 + 8a and a >= 3) }" },
2218 { 1, "{ [a, 0, c] : c >= 1 and c <= 29 and c >= -1 + 8a and "
2219 "c <= 6 + 8a and a >= 3; "
2220 "[a, -1, c] : c >= 1 and c <= 30 and c >= 8a and "
2221 "c <= 7 + 8a and a >= 3 and a <= 4 }" },
2222 { 1, "{ [x,y] : 0 <= x <= 2 and y >= 0 and x + 2y <= 4; "
2223 "[x,0] : 3 <= x <= 4 }" },
2224 { 1, "{ [x,y] : 0 <= x <= 3 and y >= 0 and x + 3y <= 6; "
2225 "[x,0] : 4 <= x <= 5 }" },
2226 { 0, "{ [x,y] : 0 <= x <= 2 and y >= 0 and x + 2y <= 4; "
2227 "[x,0] : 3 <= x <= 5 }" },
2228 { 0, "{ [x,y] : 0 <= x <= 2 and y >= 0 and x + y <= 4; "
2229 "[x,0] : 3 <= x <= 4 }" },
2230 { 1, "{ [i0, i1] : i0 <= 122 and i0 >= 1 and 128i1 >= -249 + i0 and "
2231 "i1 <= 0; "
2232 "[i0, 0] : i0 >= 123 and i0 <= 124 }" },
2233 { 1, "{ [0,0]; [1,1] }" },
2234 { 1, "[n] -> { [k] : 16k <= -1 + n and k >= 1; [0] : n >= 2 }" },
2235 { 1, "{ [k, ii, k - ii] : ii >= -6 + k and ii <= 6 and ii >= 1 and "
2236 "ii <= k;"
2237 "[k, 0, k] : k <= 6 and k >= 1 }" },
2238 { 1, "{ [i,j] : i = 4 j and 0 <= i <= 100;"
2239 "[i,j] : 1 <= i <= 100 and i >= 4j + 1 and i <= 4j + 2 }" },
2240 { 1, "{ [x,y] : x % 2 = 0 and y % 2 = 0; [x,x] : x % 2 = 0 }" },
2241 { 1, "[n] -> { [1] : n >= 0;"
2242 "[x] : exists (e0 = floor((x)/2): x >= 2 and "
2243 "2e0 >= -1 + x and 2e0 <= x and 2e0 <= n) }" },
2244 { 1, "[n] -> { [x, y] : exists (e0 = floor((x)/2), e1 = floor((y)/3): "
2245 "3e1 = y and x >= 2 and 2e0 >= -1 + x and "
2246 "2e0 <= x and 2e0 <= n);"
2247 "[1, y] : exists (e0 = floor((y)/3): 3e0 = y and "
2248 "n >= 0) }" },
2249 { 1, "[t1] -> { [i0] : (exists (e0 = floor((63t1)/64): "
2250 "128e0 >= -134 + 127t1 and t1 >= 2 and "
2251 "64e0 <= 63t1 and 64e0 >= -63 + 63t1)) or "
2252 "t1 = 1 }" },
2253 { 1, "{ [i, i] : exists (e0 = floor((1 + 2i)/3): 3e0 <= 2i and "
2254 "3e0 >= -1 + 2i and i <= 9 and i >= 1);"
2255 "[0, 0] }" },
2256 { 1, "{ [t1] : exists (e0 = floor((-11 + t1)/2): 2e0 = -11 + t1 and "
2257 "t1 >= 13 and t1 <= 16);"
2258 "[t1] : t1 <= 15 and t1 >= 12 }" },
2259 { 1, "{ [x,y] : x = 3y and 0 <= y <= 2; [-3,-1] }" },
2260 { 1, "{ [x,y] : 2x = 3y and 0 <= y <= 4; [-3,-2] }" },
2261 { 0, "{ [x,y] : 2x = 3y and 0 <= y <= 4; [-2,-2] }" },
2262 { 0, "{ [x,y] : 2x = 3y and 0 <= y <= 4; [-3,-1] }" },
2263 { 1, "{ [i] : exists j : i = 4 j and 0 <= i <= 100;"
2264 "[i] : exists j : 1 <= i <= 100 and i >= 4j + 1 and "
2265 "i <= 4j + 2 }" },
2266 { 1, "{ [c0] : (exists (e0 : c0 - 1 <= 3e0 <= c0)) or "
2267 "(exists (e0 : 3e0 = -2 + c0)) }" },
2268 { 0, "[n, b0, t0] -> "
2269 "{ [i0, i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11, i12] : "
2270 "(exists (e0 = floor((-32b0 + i4)/1048576), "
2271 "e1 = floor((i8)/32): 1048576e0 = -32b0 + i4 and 32e1 = i8 and "
2272 "n <= 2147483647 and b0 <= 32767 and b0 >= 0 and "
2273 "32b0 <= -2 + n and t0 <= 31 and t0 >= 0 and i0 >= 8 + n and "
2274 "3i4 <= -96 + 3t0 + i0 and 3i4 >= -95 - n + 3t0 + i0 and "
2275 "i8 >= -157 + i0 - 4i4 and i8 >= 0 and "
2276 "i8 <= -33 + i0 - 4i4 and 3i8 <= -91 + 4n - i0)) or "
2277 "(exists (e0 = floor((-32b0 + i4)/1048576), "
2278 "e1 = floor((i8)/32): 1048576e0 = -32b0 + i4 and 32e1 = i8 and "
2279 "n <= 2147483647 and b0 <= 32767 and b0 >= 0 and "
2280 "32b0 <= -2 + n and t0 <= 31 and t0 >= 0 and i0 <= 7 + n and "
2281 "4i4 <= -3 + i0 and 3i4 <= -96 + 3t0 + i0 and "
2282 "3i4 >= -95 - n + 3t0 + i0 and i8 >= -157 + i0 - 4i4 and "
2283 "i8 >= 0 and i8 <= -4 + i0 - 3i4 and i8 <= -41 + i0));"
2284 "[i0, i1, i2, i3, 0, i5, i6, i7, i8, i9, i10, i11, i12] : "
2285 "(exists (e0 = floor((i8)/32): b0 = 0 and 32e0 = i8 and "
2286 "n <= 2147483647 and t0 <= 31 and t0 >= 0 and i0 >= 11 and "
2287 "i0 >= 96 - 3t0 and i0 <= 95 + n - 3t0 and i0 <= 7 + n and "
2288 "i8 >= -40 + i0 and i8 <= -10 + i0)) }" },
2289 { 0, "{ [i0, i1, i2] : "
2290 "(exists (e0, e1 = floor((i0)/32), e2 = floor((i1)/32): "
2291 "32e1 = i0 and 32e2 = i1 and i1 >= -31 + i0 and "
2292 "i1 <= 31 + i0 and i2 >= -30 + i0 and i2 >= -30 + i1 and "
2293 "32e0 >= -30 + i0 and 32e0 >= -30 + i1 and "
2294 "32e0 >= -31 + i2 and 32e0 <= 30 + i2 and 32e0 <= 31 + i1 and "
2295 "32e0 <= 31 + i0)) or "
2296 "i0 >= 0 }" },
2297 { 1, "{ [a, b, c] : 2b = 1 + a and 2c = 2 + a; [0, 0, 0] }" },
2298 { 1, "{ [a, a, b, c] : 32*floor((a)/32) = a and 2*floor((b)/2) = b and "
2299 "2*floor((c)/2) = c and 0 <= a <= 192;"
2300 "[224, 224, b, c] : 2*floor((b)/2) = b and 2*floor((c)/2) = c }"
2302 { 1, "[n] -> { [a,b] : (exists e : 1 <= a <= 7e and 9e <= b <= n) or "
2303 "(0 <= a <= b <= n) }" },
2304 { 1, "{ [a, b] : 0 <= a <= 2 and b >= 0 and "
2305 "((0 < b <= 13) or (2*floor((a + b)/2) >= -5 + a + 2b)) }" },
2306 { 1, "{ [a] : (2 <= a <= 5) or (a mod 2 = 1 and 1 <= a <= 5) }" },
2307 { 1, "{ [a, b, c] : (b = -1 + a and 0 < a <= 3 and "
2308 "9*floor((-4a + 2c)/9) <= -3 - 4a + 2c) or "
2309 "(exists (e0 = floor((-16 + 2c)/9): a = 4 and "
2310 "b = 3 and 9e0 <= -19 + 2c)) }" },
2311 { 1, "{ [a, b, c] : (b = -1 + a and 0 < a <= 3 and "
2312 "9*floor((-4a + 2c)/9) <= -3 - 4a + 2c) or "
2313 "(a = 4 and b = 3 and "
2314 "9*floor((-16 + 2c)/9) <= -19 + 2c) }" },
2315 { 0, "{ [a, b, c] : (b <= 2 and b <= -2 + a) or "
2316 "(b = -1 + a and 0 < a <= 3 and "
2317 "9*floor((-4a + 2c)/9) <= -3 - 4a + 2c) or "
2318 "(exists (e0 = floor((-16 + 2c)/9): a = 4 and "
2319 "b = 3 and 9e0 <= -19 + 2c)) }" },
2320 { 1, "{ [y, x] : (x - y) mod 3 = 2 and 2 <= y <= 200 and 0 <= x <= 2;"
2321 "[1, 0] }" },
2322 { 1, "{ [x, y] : (x - y) mod 3 = 2 and 2 <= y <= 200 and 0 <= x <= 2;"
2323 "[0, 1] }" },
2324 { 1, "{ [1, y] : -1 <= y <= 1; [x, -x] : 0 <= x <= 1 }" },
2325 { 1, "{ [1, y] : 0 <= y <= 1; [x, -x] : 0 <= x <= 1 }" },
2326 { 1, "{ [x, y] : 0 <= x <= 10 and x - 4*floor(x/4) <= 1 and y <= 0; "
2327 "[x, y] : 0 <= x <= 10 and x - 4*floor(x/4) > 1 and y <= 0; "
2328 "[x, y] : 0 <= x <= 10 and x - 5*floor(x/5) <= 1 and 0 < y; "
2329 "[x, y] : 0 <= x <= 10 and x - 5*floor(x/5) > 1 and 0 < y }" },
2330 { 1, "{ [x, 0] : 0 <= x <= 10 and x mod 2 = 0; "
2331 "[x, 0] : 0 <= x <= 10 and x mod 2 = 1; "
2332 "[x, y] : 0 <= x <= 10 and 1 <= y <= 10 }" },
2333 { 1, "{ [a] : a <= 8 and "
2334 "(a mod 10 = 7 or a mod 10 = 8 or a mod 10 = 9) }" },
2335 { 1, "{ [x, y] : 2y = -x and x <= 0 or "
2336 "x <= -1 and 2y <= -x - 1 and 2y >= x - 1 }" },
2337 { 0, "{ [x, y] : 2y = -x and x <= 0 or "
2338 "x <= -2 and 2y <= -x - 1 and 2y >= x - 1 }" },
2339 { 1, "{ [a] : (a <= 0 and 3*floor((a)/3) = a) or "
2340 "(a < 0 and 3*floor((a)/3) < a) }" },
2341 { 1, "{ [a] : (a <= 0 and 3*floor((a)/3) = a) or "
2342 "(a < -1 and 3*floor((a)/3) < a) }" },
2343 { 1, "{ [a, b] : a <= 1024 and b >= 0 and "
2344 "((-31 - a + b <= 32*floor((-1 - a)/32) <= -33 + b and "
2345 "32*floor((-1 - a)/32) <= -16 + b + 16*floor((-1 - a)/16))"
2346 "or (2 <= a <= 15 and b < a)) }" },
2347 { 1, "{ [a] : a > 0 and ((16*floor((a)/16) < a and "
2348 "32*floor((a)/32) < a) or a <= 15) }" },
2349 { 1, "{ [a, b, c, d] : (-a + d) mod 64 = 0 and a <= 8 and b <= 1 and "
2350 "10 - a <= c <= 3 and d >= 5 and 9 - 64b <= d <= 70;"
2351 "[a, b = 1, c, d] : (-a + d) mod 64 = 0 and a <= 8 and c >= 4 and "
2352 "10 - a <= c <= 5 and 5 <= d <= 73 - c }" },
2353 { 1, "[n, m] -> { S_0[i] : (-n + i) mod 3 = 0 and m >= 3 + n and "
2354 "i >= n and 3*floor((2 + n + 2m)/3) <= n + 3m - i; "
2355 "S_0[n] : n <= m <= 2 + n }" },
2356 { 1, "{ [a, b] : exists (e0: 0 <= a <= 1 and b >= 0 and "
2357 "2e0 >= -5 + a + 2b and 2e0 >= -1 + a + b and "
2358 "2e0 <= a + b); "
2359 "[a, b] : exists (e0: 0 <= a <= 1 and 2e0 >= -5 + a + 2b and "
2360 "2e0 >= -1 - a + b and 2e0 <= -a + b and "
2361 "2e0 < -a + 2b) }" },
2362 { 1, "{ [i, j, i - 8j] : 8 <= i <= 63 and -7 + i <= 8j <= i; "
2363 "[i, 0, i] : 0 <= i <= 7 }" },
2364 { 1, "{ [a, b] : a >= 0 and 0 <= b <= 1 - a; [1, 1] }" },
2365 { 0, "{ [a, b] : a >= 0 and 0 <= b <= 1 - a; [0, 2] }" },
2366 { 0, "{ [a, b] : a >= 0 and 0 <= b <= 1 - a; [-1, 3] }" },
2367 { 1, "{ [a, b] : a, b >= 0 and a + 2b <= 2; [1, 1] }" },
2368 { 0, "{ [a, b] : a, b >= 0 and a + 2b <= 2; [2, 1] }" },
2369 { 0, "{ [a, c] : (2 + a) mod 4 = 0 or "
2370 "(c = 4 + a and 4 * floor((a)/4) = a and a >= 0 and a <= 4) or "
2371 "(c = 3 + a and 4 * floor((-1 + a)/4) = -1 + a and "
2372 "a > 0 and a <= 5) }" },
2373 { 1, "{ [1, 0, 0]; [a, b, c] : -1 <= -a < b <= 0 and 2c > b }" },
2374 { 0, "{ [j, a, l] : a mod 2 = 0 and j <= 29 and a >= 2 and "
2375 "2a <= -5 + j and 32j + 2a + 2 <= 4l < 33j; "
2376 "[j, 0, l] : 4 <= j <= 29 and -3 + 33j <= 4l <= 33j }" },
2377 { 0, "{ [0:1, 0:1]; [0, 2:3] }" },
2378 { 1, "{ [a] : (a = 0 or ((1 + a) mod 2 = 0 and 0 < a <= 15) or "
2379 "((a) mod 2 = 0 and 0 < a <= 15)) }" },
2382 /* A specialized coalescing test case that would result
2383 * in a segmentation fault or a failed assertion in earlier versions of isl.
2385 static int test_coalesce_special(struct isl_ctx *ctx)
2387 const char *str;
2388 isl_map *map1, *map2;
2390 str = "[y] -> { [S_L220_OUT[] -> T7[]] -> "
2391 "[[S_L309_IN[] -> T11[]] -> ce_imag2[1, o1]] : "
2392 "(y = 201 and o1 <= 239 and o1 >= 212) or "
2393 "(exists (e0 = [(y)/3]: 3e0 = y and y <= 198 and y >= 3 and "
2394 "o1 <= 239 and o1 >= 212)) or "
2395 "(exists (e0 = [(y)/3]: 3e0 = y and y <= 201 and y >= 3 and "
2396 "o1 <= 241 and o1 >= 240));"
2397 "[S_L220_OUT[] -> T7[]] -> "
2398 "[[S_L309_IN[] -> T11[]] -> ce_imag2[0, o1]] : "
2399 "(y = 2 and o1 <= 241 and o1 >= 212) or "
2400 "(exists (e0 = [(-2 + y)/3]: 3e0 = -2 + y and y <= 200 and "
2401 "y >= 5 and o1 <= 241 and o1 >= 212)) }";
2402 map1 = isl_map_read_from_str(ctx, str);
2403 map1 = isl_map_align_divs_internal(map1);
2404 map1 = isl_map_coalesce(map1);
2405 str = "[y] -> { [S_L220_OUT[] -> T7[]] -> "
2406 "[[S_L309_IN[] -> T11[]] -> ce_imag2[o0, o1]] : "
2407 "exists (e0 = [(-1 - y + o0)/3]: 3e0 = -1 - y + o0 and "
2408 "y <= 201 and o0 <= 2 and o1 >= 212 and o1 <= 241 and "
2409 "o0 >= 3 - y and o0 <= -2 + y and o0 >= 0) }";
2410 map2 = isl_map_read_from_str(ctx, str);
2411 map2 = isl_map_union(map2, map1);
2412 map2 = isl_map_align_divs_internal(map2);
2413 map2 = isl_map_coalesce(map2);
2414 isl_map_free(map2);
2415 if (!map2)
2416 return -1;
2418 return 0;
2421 /* Check that the union of the basic sets described by "str1" and "str2"
2422 * can be coalesced.
2423 * The explicit call to isl_basic_set_union prevents the implicit
2424 * equality constraints in the basic maps from being detected prior
2425 * to the call to isl_set_coalesce, at least at the point
2426 * where this function was introduced.
2428 static isl_stat test_coalesce_union(isl_ctx *ctx, const char *str1,
2429 const char *str2)
2431 isl_basic_set *bset1, *bset2;
2432 isl_set *set;
2434 bset1 = isl_basic_set_read_from_str(ctx, str1);
2435 bset2 = isl_basic_set_read_from_str(ctx, str2);
2436 set = isl_basic_set_union(bset1, bset2);
2437 set = isl_set_coalesce(set);
2438 isl_set_free(set);
2440 return isl_stat_non_null(set);
2443 /* A specialized coalescing test case that would result in an assertion
2444 * in an earlier version of isl. Use test_coalesce_union with
2445 * an explicit call to isl_basic_set_union to prevent the implicit
2446 * equality constraints in the first basic map from being detected prior
2447 * to the call to isl_set_coalesce, at least at the point
2448 * where this test case was introduced.
2450 static isl_stat test_coalesce_special2(struct isl_ctx *ctx)
2452 const char *str1;
2453 const char *str2;
2455 str1 = "{ [x, y] : x, y >= 0 and x + 2y <= 1 and 2x + y <= 1 }";
2456 str2 = "{ [x,0] : -1 <= x <= 1 and x mod 2 = 1 }";
2457 return test_coalesce_union(ctx, str1, str2);
2460 /* Check that calling isl_set_coalesce does not leave other sets
2461 * that may share some information with the input to isl_set_coalesce
2462 * in an inconsistent state.
2463 * In particular, older versions of isl would modify all copies
2464 * of the basic sets in the isl_set_coalesce input in a way
2465 * that could leave them in an inconsistent state.
2466 * The result of printing any other set containing one of these
2467 * basic sets would then result in an invalid set description.
2469 static int test_coalesce_special3(isl_ctx *ctx)
2471 const char *str;
2472 char *s;
2473 isl_set *set1, *set2;
2474 isl_printer *p;
2476 set1 = isl_set_read_from_str(ctx, "{ [0, 0, 0] }");
2477 str = "{ [a, b, a + b] : a >= 0 and b >= 0 and 0 < a + b }";
2478 set2 = isl_set_read_from_str(ctx, str);
2479 set1 = isl_set_union(set1, isl_set_copy(set2));
2480 set1 = isl_set_coalesce(set1);
2481 isl_set_free(set1);
2483 p = isl_printer_to_str(ctx);
2484 p = isl_printer_print_set(p, set2);
2485 isl_set_free(set2);
2486 s = isl_printer_get_str(p);
2487 isl_printer_free(p);
2488 set1 = isl_set_read_from_str(ctx, s);
2489 free(s);
2490 isl_set_free(set1);
2492 if (!set1)
2493 return -1;
2495 return 0;
2498 /* Check that calling isl_set_coalesce on the intersection of
2499 * the sets described by "s1" and "s2" does not leave other sets
2500 * that may share some information with the input to isl_set_coalesce
2501 * in an inconsistent state.
2502 * In particular, when isl_set_coalesce detects equality constraints,
2503 * it does not immediately perform Gaussian elimination on them,
2504 * but then it needs to ensure that it is performed at some point.
2505 * The input set has implicit equality constraints in the first disjunct.
2506 * It is constructed as an intersection, because otherwise
2507 * those equality constraints would already be detected during parsing.
2509 static isl_stat test_coalesce_intersection(isl_ctx *ctx,
2510 const char *s1, const char *s2)
2512 isl_set *set1, *set2;
2514 set1 = isl_set_read_from_str(ctx, s1);
2515 set2 = isl_set_read_from_str(ctx, s2);
2516 set1 = isl_set_intersect(set1, set2);
2517 isl_set_free(isl_set_coalesce(isl_set_copy(set1)));
2518 set1 = isl_set_coalesce(set1);
2519 isl_set_free(set1);
2521 if (!set1)
2522 return isl_stat_error;
2524 return isl_stat_ok;
2527 /* Check that calling isl_set_coalesce does not leave other sets
2528 * that may share some information with the input to isl_set_coalesce
2529 * in an inconsistent state, for the case where one disjunct
2530 * is a subset of the other.
2532 static isl_stat test_coalesce_special4(isl_ctx *ctx)
2534 const char *s1, *s2;
2536 s1 = "{ [a, b] : b <= 0 or a <= 1 }";
2537 s2 = "{ [a, b] : -1 <= -a < b }";
2538 return test_coalesce_intersection(ctx, s1, s2);
2541 /* Check that calling isl_set_coalesce does not leave other sets
2542 * that may share some information with the input to isl_set_coalesce
2543 * in an inconsistent state, for the case where two disjuncts
2544 * can be fused.
2546 static isl_stat test_coalesce_special5(isl_ctx *ctx)
2548 const char *s1, *s2;
2550 s1 = "{ [a, b, c] : b <= 0 }";
2551 s2 = "{ [a, b, c] : -1 <= -a < b and (c >= 0 or c < 0) }";
2552 return test_coalesce_intersection(ctx, s1, s2);
2555 /* Check that calling isl_set_coalesce does not leave other sets
2556 * that may share some information with the input to isl_set_coalesce
2557 * in an inconsistent state, for the case where two disjuncts
2558 * can be fused and where both disjuncts have implicit equality constraints.
2560 static isl_stat test_coalesce_special6(isl_ctx *ctx)
2562 const char *s1, *s2;
2564 s1 = "{ [a, b, c] : c <= 0 }";
2565 s2 = "{ [a, b, c] : 0 <= a <= b <= c or (0 <= b <= c and a > 0) }";
2566 return test_coalesce_intersection(ctx, s1, s2);
2569 /* A specialized coalescing test case that would result in an assertion failure
2570 * in an earlier version of isl. Use test_coalesce_union with
2571 * an explicit call to isl_basic_set_union to prevent the implicit
2572 * equality constraints in the basic maps from being detected prior
2573 * to the call to isl_set_coalesce, at least at the point
2574 * where this test case was introduced.
2576 static isl_stat test_coalesce_special7(isl_ctx *ctx)
2578 const char *str1;
2579 const char *str2;
2581 str1 = "{ [a, b, c=0:17] : a <= 7 and 2b <= 11 - a and "
2582 "c <= -7 + 2a and 2c >= - 3 + 3a - 2b }";
2583 str2 = "{ [a, b, c] : c > -15a and c >= -7 + 2a and c < 0 and "
2584 "3c <= -5 + 5a - 3b and 2b >= 11 - a }";
2585 return test_coalesce_union(ctx, str1, str2);
2588 /* Test the functionality of isl_set_coalesce.
2589 * That is, check that the output is always equal to the input
2590 * and in some cases that the result consists of a single disjunct.
2592 static int test_coalesce(struct isl_ctx *ctx)
2594 int i;
2596 for (i = 0; i < ARRAY_SIZE(coalesce_tests); ++i) {
2597 const char *str = coalesce_tests[i].str;
2598 int check_one = coalesce_tests[i].single_disjunct;
2599 if (test_coalesce_set(ctx, str, check_one) < 0)
2600 return -1;
2603 if (test_coalesce_unbounded_wrapping(ctx) < 0)
2604 return -1;
2605 if (test_coalesce_special(ctx) < 0)
2606 return -1;
2607 if (test_coalesce_special2(ctx) < 0)
2608 return -1;
2609 if (test_coalesce_special3(ctx) < 0)
2610 return -1;
2611 if (test_coalesce_special4(ctx) < 0)
2612 return -1;
2613 if (test_coalesce_special5(ctx) < 0)
2614 return -1;
2615 if (test_coalesce_special6(ctx) < 0)
2616 return -1;
2617 if (test_coalesce_special7(ctx) < 0)
2618 return -1;
2621 return 0;
2624 /* Construct a representation of the graph on the right of Figure 1
2625 * in "Computing the Transitive Closure of a Union of
2626 * Affine Integer Tuple Relations".
2628 static __isl_give isl_map *cocoa_fig_1_right_graph(isl_ctx *ctx)
2630 isl_set *dom;
2631 isl_map *up, *right;
2633 dom = isl_set_read_from_str(ctx,
2634 "{ [x,y] : x >= 0 and -2 x + 3 y >= 0 and x <= 3 and "
2635 "2 x - 3 y + 3 >= 0 }");
2636 right = isl_map_read_from_str(ctx,
2637 "{ [x,y] -> [x2,y2] : x2 = x + 1 and y2 = y }");
2638 up = isl_map_read_from_str(ctx,
2639 "{ [x,y] -> [x2,y2] : x2 = x and y2 = y + 1 }");
2640 right = isl_map_intersect_domain(right, isl_set_copy(dom));
2641 right = isl_map_intersect_range(right, isl_set_copy(dom));
2642 up = isl_map_intersect_domain(up, isl_set_copy(dom));
2643 up = isl_map_intersect_range(up, dom);
2644 return isl_map_union(up, right);
2647 /* Construct a representation of the power of the graph
2648 * on the right of Figure 1 in "Computing the Transitive Closure of
2649 * a Union of Affine Integer Tuple Relations".
2651 static __isl_give isl_map *cocoa_fig_1_right_power(isl_ctx *ctx)
2653 return isl_map_read_from_str(ctx,
2654 "{ [1] -> [[0,0] -> [0,1]]; [2] -> [[0,0] -> [1,1]]; "
2655 " [1] -> [[0,1] -> [1,1]]; [1] -> [[2,2] -> [3,2]]; "
2656 " [2] -> [[2,2] -> [3,3]]; [1] -> [[3,2] -> [3,3]] }");
2659 /* Construct a representation of the transitive closure of the graph
2660 * on the right of Figure 1 in "Computing the Transitive Closure of
2661 * a Union of Affine Integer Tuple Relations".
2663 static __isl_give isl_map *cocoa_fig_1_right_tc(isl_ctx *ctx)
2665 return isl_set_unwrap(isl_map_range(cocoa_fig_1_right_power(ctx)));
2668 static int test_closure(isl_ctx *ctx)
2670 const char *str;
2671 isl_map *map, *map2;
2672 isl_bool exact, equal;
2674 /* COCOA example 1 */
2675 map = isl_map_read_from_str(ctx,
2676 "[n] -> { [i,j] -> [i2,j2] : i2 = i + 1 and j2 = j + 1 and "
2677 "1 <= i and i < n and 1 <= j and j < n or "
2678 "i2 = i + 1 and j2 = j - 1 and "
2679 "1 <= i and i < n and 2 <= j and j <= n }");
2680 map = isl_map_power(map, &exact);
2681 assert(exact);
2682 isl_map_free(map);
2684 /* COCOA example 1 */
2685 map = isl_map_read_from_str(ctx,
2686 "[n] -> { [i,j] -> [i2,j2] : i2 = i + 1 and j2 = j + 1 and "
2687 "1 <= i and i < n and 1 <= j and j < n or "
2688 "i2 = i + 1 and j2 = j - 1 and "
2689 "1 <= i and i < n and 2 <= j and j <= n }");
2690 map = isl_map_transitive_closure(map, &exact);
2691 assert(exact);
2692 map2 = isl_map_read_from_str(ctx,
2693 "[n] -> { [i,j] -> [i2,j2] : exists (k1,k2,k : "
2694 "1 <= i and i < n and 1 <= j and j <= n and "
2695 "2 <= i2 and i2 <= n and 1 <= j2 and j2 <= n and "
2696 "i2 = i + k1 + k2 and j2 = j + k1 - k2 and "
2697 "k1 >= 0 and k2 >= 0 and k1 + k2 = k and k >= 1 )}");
2698 assert(isl_map_is_equal(map, map2));
2699 isl_map_free(map2);
2700 isl_map_free(map);
2702 map = isl_map_read_from_str(ctx,
2703 "[n] -> { [x] -> [y] : y = x + 1 and 0 <= x and x <= n and "
2704 " 0 <= y and y <= n }");
2705 map = isl_map_transitive_closure(map, &exact);
2706 map2 = isl_map_read_from_str(ctx,
2707 "[n] -> { [x] -> [y] : y > x and 0 <= x and x <= n and "
2708 " 0 <= y and y <= n }");
2709 assert(isl_map_is_equal(map, map2));
2710 isl_map_free(map2);
2711 isl_map_free(map);
2713 /* COCOA example 2 */
2714 map = isl_map_read_from_str(ctx,
2715 "[n] -> { [i,j] -> [i2,j2] : i2 = i + 2 and j2 = j + 2 and "
2716 "1 <= i and i < n - 1 and 1 <= j and j < n - 1 or "
2717 "i2 = i + 2 and j2 = j - 2 and "
2718 "1 <= i and i < n - 1 and 3 <= j and j <= n }");
2719 map = isl_map_transitive_closure(map, &exact);
2720 assert(exact);
2721 map2 = isl_map_read_from_str(ctx,
2722 "[n] -> { [i,j] -> [i2,j2] : exists (k1,k2,k : "
2723 "1 <= i and i < n - 1 and 1 <= j and j <= n and "
2724 "3 <= i2 and i2 <= n and 1 <= j2 and j2 <= n and "
2725 "i2 = i + 2 k1 + 2 k2 and j2 = j + 2 k1 - 2 k2 and "
2726 "k1 >= 0 and k2 >= 0 and k1 + k2 = k and k >= 1) }");
2727 assert(isl_map_is_equal(map, map2));
2728 isl_map_free(map);
2729 isl_map_free(map2);
2731 /* COCOA Fig.2 left */
2732 map = isl_map_read_from_str(ctx,
2733 "[n] -> { [i,j] -> [i2,j2] : i2 = i + 2 and j2 = j and "
2734 "i <= 2 j - 3 and i <= n - 2 and j <= 2 i - 1 and "
2735 "j <= n or "
2736 "i2 = i and j2 = j + 2 and i <= 2 j - 1 and i <= n and "
2737 "j <= 2 i - 3 and j <= n - 2 or "
2738 "i2 = i + 1 and j2 = j + 1 and i <= 2 j - 1 and "
2739 "i <= n - 1 and j <= 2 i - 1 and j <= n - 1 }");
2740 map = isl_map_transitive_closure(map, &exact);
2741 assert(exact);
2742 isl_map_free(map);
2744 /* COCOA Fig.2 right */
2745 map = isl_map_read_from_str(ctx,
2746 "[n] -> { [i,j] -> [i2,j2] : i2 = i + 3 and j2 = j and "
2747 "i <= 2 j - 4 and i <= n - 3 and j <= 2 i - 1 and "
2748 "j <= n or "
2749 "i2 = i and j2 = j + 3 and i <= 2 j - 1 and i <= n and "
2750 "j <= 2 i - 4 and j <= n - 3 or "
2751 "i2 = i + 1 and j2 = j + 1 and i <= 2 j - 1 and "
2752 "i <= n - 1 and j <= 2 i - 1 and j <= n - 1 }");
2753 map = isl_map_power(map, &exact);
2754 assert(exact);
2755 isl_map_free(map);
2757 /* COCOA Fig.2 right */
2758 map = isl_map_read_from_str(ctx,
2759 "[n] -> { [i,j] -> [i2,j2] : i2 = i + 3 and j2 = j and "
2760 "i <= 2 j - 4 and i <= n - 3 and j <= 2 i - 1 and "
2761 "j <= n or "
2762 "i2 = i and j2 = j + 3 and i <= 2 j - 1 and i <= n and "
2763 "j <= 2 i - 4 and j <= n - 3 or "
2764 "i2 = i + 1 and j2 = j + 1 and i <= 2 j - 1 and "
2765 "i <= n - 1 and j <= 2 i - 1 and j <= n - 1 }");
2766 map = isl_map_transitive_closure(map, &exact);
2767 assert(exact);
2768 map2 = isl_map_read_from_str(ctx,
2769 "[n] -> { [i,j] -> [i2,j2] : exists (k1,k2,k3,k : "
2770 "i <= 2 j - 1 and i <= n and j <= 2 i - 1 and "
2771 "j <= n and 3 + i + 2 j <= 3 n and "
2772 "3 + 2 i + j <= 3n and i2 <= 2 j2 -1 and i2 <= n and "
2773 "i2 <= 3 j2 - 4 and j2 <= 2 i2 -1 and j2 <= n and "
2774 "13 + 4 j2 <= 11 i2 and i2 = i + 3 k1 + k3 and "
2775 "j2 = j + 3 k2 + k3 and k1 >= 0 and k2 >= 0 and "
2776 "k3 >= 0 and k1 + k2 + k3 = k and k > 0) }");
2777 assert(isl_map_is_equal(map, map2));
2778 isl_map_free(map2);
2779 isl_map_free(map);
2781 map = cocoa_fig_1_right_graph(ctx);
2782 map = isl_map_transitive_closure(map, &exact);
2783 assert(exact);
2784 map2 = cocoa_fig_1_right_tc(ctx);
2785 assert(isl_map_is_equal(map, map2));
2786 isl_map_free(map2);
2787 isl_map_free(map);
2789 map = cocoa_fig_1_right_graph(ctx);
2790 map = isl_map_power(map, &exact);
2791 map2 = cocoa_fig_1_right_power(ctx);
2792 equal = isl_map_is_equal(map, map2);
2793 isl_map_free(map2);
2794 isl_map_free(map);
2795 if (equal < 0)
2796 return -1;
2797 if (!exact)
2798 isl_die(ctx, isl_error_unknown, "power not exact", return -1);
2799 if (!equal)
2800 isl_die(ctx, isl_error_unknown, "unexpected power", return -1);
2802 /* COCOA Theorem 1 counter example */
2803 map = isl_map_read_from_str(ctx,
2804 "{ [i,j] -> [i2,j2] : i = 0 and 0 <= j and j <= 1 and "
2805 "i2 = 1 and j2 = j or "
2806 "i = 0 and j = 0 and i2 = 0 and j2 = 1 }");
2807 map = isl_map_transitive_closure(map, &exact);
2808 assert(exact);
2809 isl_map_free(map);
2811 map = isl_map_read_from_str(ctx,
2812 "[m,n] -> { [i,j] -> [i2,j2] : i2 = i and j2 = j + 2 and "
2813 "1 <= i,i2 <= n and 1 <= j,j2 <= m or "
2814 "i2 = i + 1 and 3 <= j2 - j <= 4 and "
2815 "1 <= i,i2 <= n and 1 <= j,j2 <= m }");
2816 map = isl_map_transitive_closure(map, &exact);
2817 assert(exact);
2818 isl_map_free(map);
2820 /* Kelly et al 1996, fig 12 */
2821 map = isl_map_read_from_str(ctx,
2822 "[n] -> { [i,j] -> [i2,j2] : i2 = i and j2 = j + 1 and "
2823 "1 <= i,j,j+1 <= n or "
2824 "j = n and j2 = 1 and i2 = i + 1 and "
2825 "1 <= i,i+1 <= n }");
2826 map = isl_map_transitive_closure(map, &exact);
2827 assert(exact);
2828 map2 = isl_map_read_from_str(ctx,
2829 "[n] -> { [i,j] -> [i2,j2] : 1 <= j < j2 <= n and "
2830 "1 <= i <= n and i = i2 or "
2831 "1 <= i < i2 <= n and 1 <= j <= n and "
2832 "1 <= j2 <= n }");
2833 assert(isl_map_is_equal(map, map2));
2834 isl_map_free(map2);
2835 isl_map_free(map);
2837 /* Omega's closure4 */
2838 map = isl_map_read_from_str(ctx,
2839 "[m,n] -> { [x,y] -> [x2,y2] : x2 = x and y2 = y + 1 and "
2840 "1 <= x,y <= 10 or "
2841 "x2 = x + 1 and y2 = y and "
2842 "1 <= x <= 20 && 5 <= y <= 15 }");
2843 map = isl_map_transitive_closure(map, &exact);
2844 assert(exact);
2845 isl_map_free(map);
2847 map = isl_map_read_from_str(ctx,
2848 "[n] -> { [x] -> [y]: 1 <= n <= y - x <= 10 }");
2849 map = isl_map_transitive_closure(map, &exact);
2850 assert(!exact);
2851 map2 = isl_map_read_from_str(ctx,
2852 "[n] -> { [x] -> [y] : 1 <= n <= 10 and y >= n + x }");
2853 assert(isl_map_is_equal(map, map2));
2854 isl_map_free(map);
2855 isl_map_free(map2);
2857 str = "[n, m] -> { [i0, i1, i2, i3] -> [o0, o1, o2, o3] : "
2858 "i3 = 1 and o0 = i0 and o1 = -1 + i1 and o2 = -1 + i2 and "
2859 "o3 = -2 + i2 and i1 <= -1 + i0 and i1 >= 1 - m + i0 and "
2860 "i1 >= 2 and i1 <= n and i2 >= 3 and i2 <= 1 + n and i2 <= m }";
2861 map = isl_map_read_from_str(ctx, str);
2862 map = isl_map_transitive_closure(map, &exact);
2863 assert(exact);
2864 map2 = isl_map_read_from_str(ctx, str);
2865 assert(isl_map_is_equal(map, map2));
2866 isl_map_free(map);
2867 isl_map_free(map2);
2869 str = "{[0] -> [1]; [2] -> [3]}";
2870 map = isl_map_read_from_str(ctx, str);
2871 map = isl_map_transitive_closure(map, &exact);
2872 assert(exact);
2873 map2 = isl_map_read_from_str(ctx, str);
2874 assert(isl_map_is_equal(map, map2));
2875 isl_map_free(map);
2876 isl_map_free(map2);
2878 str = "[n] -> { [[i0, i1, 1, 0, i0] -> [i5, 1]] -> "
2879 "[[i0, -1 + i1, 2, 0, i0] -> [-1 + i5, 2]] : "
2880 "exists (e0 = [(3 - n)/3]: i5 >= 2 and i1 >= 2 and "
2881 "3i0 <= -1 + n and i1 <= -1 + n and i5 <= -1 + n and "
2882 "3e0 >= 1 - n and 3e0 <= 2 - n and 3i0 >= -2 + n); "
2883 "[[i0, i1, 2, 0, i0] -> [i5, 1]] -> "
2884 "[[i0, i1, 1, 0, i0] -> [-1 + i5, 2]] : "
2885 "exists (e0 = [(3 - n)/3]: i5 >= 2 and i1 >= 1 and "
2886 "3i0 <= -1 + n and i1 <= -1 + n and i5 <= -1 + n and "
2887 "3e0 >= 1 - n and 3e0 <= 2 - n and 3i0 >= -2 + n); "
2888 "[[i0, i1, 1, 0, i0] -> [i5, 2]] -> "
2889 "[[i0, -1 + i1, 2, 0, i0] -> [i5, 1]] : "
2890 "exists (e0 = [(3 - n)/3]: i1 >= 2 and i5 >= 1 and "
2891 "3i0 <= -1 + n and i1 <= -1 + n and i5 <= -1 + n and "
2892 "3e0 >= 1 - n and 3e0 <= 2 - n and 3i0 >= -2 + n); "
2893 "[[i0, i1, 2, 0, i0] -> [i5, 2]] -> "
2894 "[[i0, i1, 1, 0, i0] -> [i5, 1]] : "
2895 "exists (e0 = [(3 - n)/3]: i5 >= 1 and i1 >= 1 and "
2896 "3i0 <= -1 + n and i1 <= -1 + n and i5 <= -1 + n and "
2897 "3e0 >= 1 - n and 3e0 <= 2 - n and 3i0 >= -2 + n) }";
2898 map = isl_map_read_from_str(ctx, str);
2899 map = isl_map_transitive_closure(map, NULL);
2900 assert(map);
2901 isl_map_free(map);
2903 return 0;
2906 /* Check that the actual result of a boolean operation is equal
2907 * to the expected result.
2909 static isl_stat check_bool(isl_ctx *ctx, isl_bool actual, isl_bool expected)
2911 if (actual != expected)
2912 isl_die(ctx, isl_error_unknown,
2913 "incorrect boolean operation", return isl_stat_error);
2914 return isl_stat_ok;
2917 /* Test operations on isl_bool values.
2919 * This tests:
2921 * isl_bool_not
2922 * isl_bool_ok
2924 static int test_isl_bool(isl_ctx *ctx)
2926 if (check_bool(ctx, isl_bool_not(isl_bool_true), isl_bool_false) < 0)
2927 return -1;
2928 if (check_bool(ctx, isl_bool_not(isl_bool_false), isl_bool_true) < 0)
2929 return -1;
2930 if (check_bool(ctx, isl_bool_not(isl_bool_error), isl_bool_error) < 0)
2931 return -1;
2932 if (check_bool(ctx, isl_bool_ok(0), isl_bool_false) < 0)
2933 return -1;
2934 if (check_bool(ctx, isl_bool_ok(1), isl_bool_true) < 0)
2935 return -1;
2936 if (check_bool(ctx, isl_bool_ok(-1), isl_bool_true) < 0)
2937 return -1;
2938 if (check_bool(ctx, isl_bool_ok(2), isl_bool_true) < 0)
2939 return -1;
2940 if (check_bool(ctx, isl_bool_ok(-2), isl_bool_true) < 0)
2941 return -1;
2943 return 0;
2946 static int test_lex(struct isl_ctx *ctx)
2948 isl_space *space;
2949 isl_map *map;
2950 int empty;
2952 space = isl_space_set_alloc(ctx, 0, 0);
2953 map = isl_map_lex_le(space);
2954 empty = isl_map_is_empty(map);
2955 isl_map_free(map);
2957 if (empty < 0)
2958 return -1;
2959 if (empty)
2960 isl_die(ctx, isl_error_unknown,
2961 "expecting non-empty result", return -1);
2963 return 0;
2966 /* Inputs for isl_map_lexmin tests.
2967 * "map" is the input and "lexmin" is the expected result.
2969 struct {
2970 const char *map;
2971 const char *lexmin;
2972 } lexmin_tests [] = {
2973 { "{ [x] -> [y] : x <= y <= 10; [x] -> [5] : -8 <= x <= 8 }",
2974 "{ [x] -> [5] : 6 <= x <= 8; "
2975 "[x] -> [x] : x <= 5 or (9 <= x <= 10) }" },
2976 { "{ [x] -> [y] : 4y = x or 4y = -1 + x or 4y = -2 + x }",
2977 "{ [x] -> [y] : 4y = x or 4y = -1 + x or 4y = -2 + x }" },
2978 { "{ [x] -> [y] : x = 4y; [x] -> [y] : x = 2y }",
2979 "{ [x] -> [y] : (4y = x and x >= 0) or "
2980 "(exists (e0 = [(x)/4], e1 = [(-2 + x)/4]: 2y = x and "
2981 "4e1 = -2 + x and 4e0 <= -1 + x and 4e0 >= -3 + x)) or "
2982 "(exists (e0 = [(x)/4]: 2y = x and 4e0 = x and x <= -4)) }" },
2983 { "{ T[a] -> S[b, c] : a = 4b-2c and c >= b }",
2984 "{ T[a] -> S[b, c] : 2b = a and 2c = a }" },
2985 /* Check that empty pieces are properly combined. */
2986 { "[K, N] -> { [x, y] -> [a, b] : K+2<=N<=K+4 and x>=4 and "
2987 "2N-6<=x<K+N and N-1<=a<=K+N-1 and N+b-6<=a<=2N-4 and "
2988 "b<=2N-3K+a and 3b<=4N-K+1 and b>=N and a>=x+1 }",
2989 "[K, N] -> { [x, y] -> [1 + x, N] : x >= -6 + 2N and "
2990 "x <= -5 + 2N and x >= -1 + 3K - N and x <= -2 + K + N and "
2991 "x >= 4 }" },
2992 { "{ [i, k, j] -> [a, b, c, d] : 8*floor((b)/8) = b and k <= 255 and "
2993 "a <= 255 and c <= 255 and d <= 255 - j and "
2994 "255 - j <= 7d <= 7 - i and 240d <= 239 + a and "
2995 "247d <= 247 + k - j and 247d <= 247 + k - b and "
2996 "247d <= 247 + i and 248 - b <= 248d <= c and "
2997 "254d >= i - a + b and 254d >= -a + b and "
2998 "255d >= -i + a - b and 1792d >= -63736 + 257b }",
2999 "{ [i, k, j] -> "
3000 "[-127762 + i + 502j, -62992 + 248j, 63240 - 248j, 255 - j] : "
3001 "k <= 255 and 7j >= 1778 + i and 246j >= 62738 - k and "
3002 "247j >= 62738 - i and 509j <= 129795 + i and "
3003 "742j >= 188724 - i; "
3004 "[0, k, j] -> [1, 0, 248, 1] : k <= 255 and 248 <= j <= 254, k }" },
3005 { "{ [a] -> [b] : 0 <= b <= 255 and -509 + a <= 512b < a and "
3006 "16*floor((8 + b)/16) <= 7 + b; "
3007 "[a] -> [1] }",
3008 "{ [a] -> [b = 1] : a >= 510 or a <= 0; "
3009 "[a] -> [b = 0] : 0 < a <= 509 }" },
3010 { "{ rat: [i] : 1 <= 2i <= 9 }", "{ rat: [i] : 2i = 1 }" },
3011 { "{ rat: [i] : 1 <= 2i <= 9 or i >= 10 }", "{ rat: [i] : 2i = 1 }" },
3012 { "{ rat: [i] : 21 <= 2i <= 29 or i = 5 }", "{ rat: [5] }" },
3015 static int test_lexmin(struct isl_ctx *ctx)
3017 int i;
3018 int equal;
3019 const char *str;
3020 isl_basic_map *bmap;
3021 isl_map *map, *map2;
3022 isl_set *set;
3023 isl_set *set2;
3024 isl_pw_multi_aff *pma;
3026 str = "[p0, p1] -> { [] -> [] : "
3027 "exists (e0 = [(2p1)/3], e1, e2, e3 = [(3 - p1 + 3e0)/3], "
3028 "e4 = [(p1)/3], e5 = [(p1 + 3e4)/3]: "
3029 "3e0 >= -2 + 2p1 and 3e0 >= p1 and 3e3 >= 1 - p1 + 3e0 and "
3030 "3e0 <= 2p1 and 3e3 >= -2 + p1 and 3e3 <= -1 + p1 and p1 >= 3 and "
3031 "3e5 >= -2 + 2p1 and 3e5 >= p1 and 3e5 <= -1 + p1 + 3e4 and "
3032 "3e4 <= p1 and 3e4 >= -2 + p1 and e3 <= -1 + e0 and "
3033 "3e4 >= 6 - p1 + 3e1 and 3e1 >= p1 and 3e5 >= -2 + p1 + 3e4 and "
3034 "2e4 >= 3 - p1 + 2e1 and e4 <= e1 and 3e3 <= 2 - p1 + 3e0 and "
3035 "e5 >= 1 + e1 and 3e4 >= 6 - 2p1 + 3e1 and "
3036 "p0 >= 2 and p1 >= p0 and 3e2 >= p1 and 3e4 >= 6 - p1 + 3e2 and "
3037 "e2 <= e1 and e3 >= 1 and e4 <= e2) }";
3038 map = isl_map_read_from_str(ctx, str);
3039 map = isl_map_lexmin(map);
3040 isl_map_free(map);
3041 if (!map)
3042 return -1;
3044 str = "[C] -> { [obj,a,b,c] : obj <= 38 a + 7 b + 10 c and "
3045 "a + b <= 1 and c <= 10 b and c <= C and a,b,c,C >= 0 }";
3046 set = isl_set_read_from_str(ctx, str);
3047 set = isl_set_lexmax(set);
3048 str = "[C] -> { [obj,a,b,c] : C = 8 }";
3049 set2 = isl_set_read_from_str(ctx, str);
3050 set = isl_set_intersect(set, set2);
3051 assert(!isl_set_is_empty(set));
3052 isl_set_free(set);
3054 for (i = 0; i < ARRAY_SIZE(lexmin_tests); ++i) {
3055 map = isl_map_read_from_str(ctx, lexmin_tests[i].map);
3056 map = isl_map_lexmin(map);
3057 map2 = isl_map_read_from_str(ctx, lexmin_tests[i].lexmin);
3058 equal = isl_map_is_equal(map, map2);
3059 isl_map_free(map);
3060 isl_map_free(map2);
3062 if (equal < 0)
3063 return -1;
3064 if (!equal)
3065 isl_die(ctx, isl_error_unknown,
3066 "unexpected result", return -1);
3069 str = "{ [i] -> [i', j] : j = i - 8i' and i' >= 0 and i' <= 7 and "
3070 " 8i' <= i and 8i' >= -7 + i }";
3071 bmap = isl_basic_map_read_from_str(ctx, str);
3072 pma = isl_basic_map_lexmin_pw_multi_aff(isl_basic_map_copy(bmap));
3073 map2 = isl_map_from_pw_multi_aff(pma);
3074 map = isl_map_from_basic_map(bmap);
3075 assert(isl_map_is_equal(map, map2));
3076 isl_map_free(map);
3077 isl_map_free(map2);
3079 str = "[i] -> { [i', j] : j = i - 8i' and i' >= 0 and i' <= 7 and "
3080 " 8i' <= i and 8i' >= -7 + i }";
3081 set = isl_set_read_from_str(ctx, str);
3082 pma = isl_set_lexmin_pw_multi_aff(isl_set_copy(set));
3083 set2 = isl_set_from_pw_multi_aff(pma);
3084 equal = isl_set_is_equal(set, set2);
3085 isl_set_free(set);
3086 isl_set_free(set2);
3087 if (equal < 0)
3088 return -1;
3089 if (!equal)
3090 isl_die(ctx, isl_error_unknown,
3091 "unexpected difference between set and "
3092 "piecewise affine expression", return -1);
3094 return 0;
3097 /* Inputs for isl_pw_multi_aff_max_multi_val tests.
3098 * "pma" is the input.
3099 * "res" is the expected result.
3101 static struct {
3102 const char *pma;
3103 const char *res;
3104 } opt_pw_tests[] = {
3105 { "{ [-1] -> [-1]; [1] -> [1] }", "{ [1] }" },
3106 { "{ [a, b] -> [floor((b - 2*floor((-a)/4))/5)] : "
3107 "0 <= a, b <= 100 and b mod 2 = 0}", "{ [30] }" },
3108 { "[N] -> { [i,j] -> A[i, -i, i + j] : 0 <= i,j <= N <= 10 }",
3109 "{ A[10, 0, 20] }" },
3110 { "[N] -> {A[N, -N, 2N] : 0 <= N }", "{ A[infty, 0, infty] }" },
3113 /* Perform basic isl_pw_multi_aff_max_multi_val tests.
3115 static isl_stat test_pw_max(struct isl_ctx *ctx)
3117 int i;
3118 isl_pw_multi_aff *pma;
3119 isl_multi_val *mv;
3120 isl_stat r;
3122 for (i = 0; i < ARRAY_SIZE(opt_pw_tests); ++i) {
3123 pma = isl_pw_multi_aff_read_from_str(ctx, opt_pw_tests[i].pma);
3124 mv = isl_pw_multi_aff_max_multi_val(pma);
3125 r = multi_val_check_plain_equal(mv, opt_pw_tests[i].res);
3126 isl_multi_val_free(mv);
3128 if (r < 0)
3129 return isl_stat_error;
3132 return isl_stat_ok;
3135 /* A specialized isl_set_min_val test case that would return the wrong result
3136 * in earlier versions of isl.
3137 * The explicit call to isl_basic_set_union prevents the second basic set
3138 * from being determined to be empty prior to the call to isl_set_min_val,
3139 * at least at the point where this test case was introduced.
3141 static int test_min_special(isl_ctx *ctx)
3143 const char *str;
3144 isl_basic_set *bset1, *bset2;
3145 isl_set *set;
3146 isl_aff *obj;
3147 isl_val *res;
3148 int ok;
3150 str = "{ [a, b] : a >= 2 and b >= 0 and 14 - a <= b <= 9 }";
3151 bset1 = isl_basic_set_read_from_str(ctx, str);
3152 str = "{ [a, b] : 1 <= a, b and a + b <= 1 }";
3153 bset2 = isl_basic_set_read_from_str(ctx, str);
3154 set = isl_basic_set_union(bset1, bset2);
3155 obj = isl_aff_read_from_str(ctx, "{ [a, b] -> [a] }");
3157 res = isl_set_min_val(set, obj);
3158 ok = isl_val_cmp_si(res, 5) == 0;
3160 isl_aff_free(obj);
3161 isl_set_free(set);
3162 isl_val_free(res);
3164 if (!res)
3165 return -1;
3166 if (!ok)
3167 isl_die(ctx, isl_error_unknown, "unexpected minimum",
3168 return -1);
3170 return 0;
3173 /* A specialized isl_set_min_val test case that would return an error
3174 * in earlier versions of isl.
3176 static int test_min_special2(isl_ctx *ctx)
3178 const char *str;
3179 isl_basic_set *bset;
3180 isl_aff *obj;
3181 isl_val *res;
3183 str = "{ [i, j, k] : 2j = i and 2k = i + 1 and i >= 2 }";
3184 bset = isl_basic_set_read_from_str(ctx, str);
3186 obj = isl_aff_read_from_str(ctx, "{ [i, j, k] -> [i] }");
3188 res = isl_basic_set_max_val(bset, obj);
3190 isl_basic_set_free(bset);
3191 isl_aff_free(obj);
3192 isl_val_free(res);
3194 if (!res)
3195 return -1;
3197 return 0;
3200 /* Check that the result of isl_set_min_multi_pw_aff
3201 * on the union of the sets with string descriptions "s1" and "s2"
3202 * consists of a single expression (on a single cell).
3204 static isl_stat check_single_expr_min(isl_ctx *ctx, const char *s1,
3205 const char *s2)
3207 isl_size n;
3208 isl_set *set1, *set2;
3209 isl_multi_pw_aff *mpa;
3210 isl_pw_multi_aff *pma;
3212 set1 = isl_set_read_from_str(ctx, s1);
3213 set2 = isl_set_read_from_str(ctx, s2);
3214 set1 = isl_set_union(set1, set2);
3215 mpa = isl_set_min_multi_pw_aff(set1);
3216 pma = isl_pw_multi_aff_from_multi_pw_aff(mpa);
3217 n = isl_pw_multi_aff_n_piece(pma);
3218 isl_pw_multi_aff_free(pma);
3220 if (n < 0)
3221 return isl_stat_error;
3222 if (n != 1)
3223 isl_die(ctx, isl_error_unknown, "expecting single expression",
3224 return isl_stat_error);
3225 return isl_stat_ok;
3228 /* A specialized isl_set_min_multi_pw_aff test that checks
3229 * that the minimum of 2N and 3N for N >= 0 is represented
3230 * by a single expression, without splitting off the special case N = 0.
3231 * Do this for both orderings.
3233 static int test_min_mpa(isl_ctx *ctx)
3235 const char *s1, *s2;
3237 s1 = "[N=0:] -> { [1, 3N:] }";
3238 s2 = "[N=0:] -> { [10, 2N:] }";
3239 if (check_single_expr_min(ctx, s1, s2) < 0)
3240 return -1;
3241 if (check_single_expr_min(ctx, s2, s1) < 0)
3242 return -1;
3244 return 0;
3247 struct {
3248 const char *set;
3249 const char *obj;
3250 __isl_give isl_val *(*fn)(__isl_keep isl_set *set,
3251 __isl_keep isl_aff *obj);
3252 const char *res;
3253 } opt_tests[] = {
3254 { "{ [-1]; [1] }", "{ [x] -> [x] }", &isl_set_min_val, "-1" },
3255 { "{ [-1]; [1] }", "{ [x] -> [x] }", &isl_set_max_val, "1" },
3256 { "{ [a, b] : 0 <= a, b <= 100 and b mod 2 = 0}",
3257 "{ [a, b] -> [floor((b - 2*floor((-a)/4))/5)] }",
3258 &isl_set_max_val, "30" },
3262 /* Perform basic isl_set_min_val and isl_set_max_val tests.
3263 * In particular, check the results on non-convex inputs.
3265 static int test_min(struct isl_ctx *ctx)
3267 int i;
3268 isl_set *set;
3269 isl_aff *obj;
3270 isl_val *val, *res;
3271 isl_bool ok;
3273 for (i = 0; i < ARRAY_SIZE(opt_tests); ++i) {
3274 set = isl_set_read_from_str(ctx, opt_tests[i].set);
3275 obj = isl_aff_read_from_str(ctx, opt_tests[i].obj);
3276 res = isl_val_read_from_str(ctx, opt_tests[i].res);
3277 val = opt_tests[i].fn(set, obj);
3278 ok = isl_val_eq(res, val);
3279 isl_val_free(res);
3280 isl_val_free(val);
3281 isl_aff_free(obj);
3282 isl_set_free(set);
3284 if (ok < 0)
3285 return -1;
3286 if (!ok)
3287 isl_die(ctx, isl_error_unknown,
3288 "unexpected optimum", return -1);
3291 if (test_pw_max(ctx) < 0)
3292 return -1;
3293 if (test_min_special(ctx) < 0)
3294 return -1;
3295 if (test_min_special2(ctx) < 0)
3296 return -1;
3298 return 0;
3301 struct must_may {
3302 isl_map *must;
3303 isl_map *may;
3306 static isl_stat collect_must_may(__isl_take isl_map *dep, int must,
3307 void *dep_user, void *user)
3309 struct must_may *mm = (struct must_may *)user;
3311 if (must)
3312 mm->must = isl_map_union(mm->must, dep);
3313 else
3314 mm->may = isl_map_union(mm->may, dep);
3316 return isl_stat_ok;
3319 static int common_space(void *first, void *second)
3321 int depth = *(int *)first;
3322 return 2 * depth;
3325 static int map_is_equal(__isl_keep isl_map *map, const char *str)
3327 isl_map *map2;
3328 int equal;
3330 if (!map)
3331 return -1;
3333 map2 = isl_map_read_from_str(map->ctx, str);
3334 equal = isl_map_is_equal(map, map2);
3335 isl_map_free(map2);
3337 return equal;
3340 static int map_check_equal(__isl_keep isl_map *map, const char *str)
3342 int equal;
3344 equal = map_is_equal(map, str);
3345 if (equal < 0)
3346 return -1;
3347 if (!equal)
3348 isl_die(isl_map_get_ctx(map), isl_error_unknown,
3349 "result not as expected", return -1);
3350 return 0;
3353 /* Is "set" equal to the set described by "str"?
3355 static isl_bool set_is_equal(__isl_keep isl_set *set, const char *str)
3357 isl_set *set2;
3358 isl_bool equal;
3360 if (!set)
3361 return isl_bool_error;
3363 set2 = isl_set_read_from_str(isl_set_get_ctx(set), str);
3364 equal = isl_set_is_equal(set, set2);
3365 isl_set_free(set2);
3367 return equal;
3370 /* Check that "set" is equal to the set described by "str".
3372 static isl_stat set_check_equal(__isl_keep isl_set *set, const char *str)
3374 isl_bool equal;
3376 equal = set_is_equal(set, str);
3377 if (equal < 0)
3378 return isl_stat_error;
3379 if (!equal)
3380 isl_die(isl_set_get_ctx(set), isl_error_unknown,
3381 "result not as expected", return isl_stat_error);
3382 return isl_stat_ok;
3385 /* Is "uset" equal to the union set described by "str"?
3387 static isl_bool uset_is_equal(__isl_keep isl_union_set *uset, const char *str)
3389 isl_union_set *uset2;
3390 isl_bool equal;
3392 if (!uset)
3393 return isl_bool_error;
3395 uset2 = isl_union_set_read_from_str(isl_union_set_get_ctx(uset), str);
3396 equal = isl_union_set_is_equal(uset, uset2);
3397 isl_union_set_free(uset2);
3399 return equal;
3402 /* Check that "uset" is equal to the union set described by "str".
3404 static isl_stat uset_check_equal(__isl_keep isl_union_set *uset,
3405 const char *str)
3407 isl_bool equal;
3409 equal = uset_is_equal(uset, str);
3410 if (equal < 0)
3411 return isl_stat_error;
3412 if (!equal)
3413 isl_die(isl_union_set_get_ctx(uset), isl_error_unknown,
3414 "result not as expected", return isl_stat_error);
3415 return isl_stat_ok;
3418 static int test_dep(struct isl_ctx *ctx)
3420 const char *str;
3421 isl_space *space;
3422 isl_map *map;
3423 isl_access_info *ai;
3424 isl_flow *flow;
3425 int depth;
3426 struct must_may mm;
3428 depth = 3;
3430 str = "{ [2,i,0] -> [i] : 0 <= i <= 10 }";
3431 map = isl_map_read_from_str(ctx, str);
3432 ai = isl_access_info_alloc(map, &depth, &common_space, 2);
3434 str = "{ [0,i,0] -> [i] : 0 <= i <= 10 }";
3435 map = isl_map_read_from_str(ctx, str);
3436 ai = isl_access_info_add_source(ai, map, 1, &depth);
3438 str = "{ [1,i,0] -> [5] : 0 <= i <= 10 }";
3439 map = isl_map_read_from_str(ctx, str);
3440 ai = isl_access_info_add_source(ai, map, 1, &depth);
3442 flow = isl_access_info_compute_flow(ai);
3443 space = isl_space_alloc(ctx, 0, 3, 3);
3444 mm.must = isl_map_empty(isl_space_copy(space));
3445 mm.may = isl_map_empty(space);
3447 isl_flow_foreach(flow, collect_must_may, &mm);
3449 str = "{ [0,i,0] -> [2,i,0] : (0 <= i <= 4) or (6 <= i <= 10); "
3450 " [1,10,0] -> [2,5,0] }";
3451 assert(map_is_equal(mm.must, str));
3452 str = "{ [i,j,k] -> [l,m,n] : 1 = 0 }";
3453 assert(map_is_equal(mm.may, str));
3455 isl_map_free(mm.must);
3456 isl_map_free(mm.may);
3457 isl_flow_free(flow);
3460 str = "{ [2,i,0] -> [i] : 0 <= i <= 10 }";
3461 map = isl_map_read_from_str(ctx, str);
3462 ai = isl_access_info_alloc(map, &depth, &common_space, 2);
3464 str = "{ [0,i,0] -> [i] : 0 <= i <= 10 }";
3465 map = isl_map_read_from_str(ctx, str);
3466 ai = isl_access_info_add_source(ai, map, 1, &depth);
3468 str = "{ [1,i,0] -> [5] : 0 <= i <= 10 }";
3469 map = isl_map_read_from_str(ctx, str);
3470 ai = isl_access_info_add_source(ai, map, 0, &depth);
3472 flow = isl_access_info_compute_flow(ai);
3473 space = isl_space_alloc(ctx, 0, 3, 3);
3474 mm.must = isl_map_empty(isl_space_copy(space));
3475 mm.may = isl_map_empty(space);
3477 isl_flow_foreach(flow, collect_must_may, &mm);
3479 str = "{ [0,i,0] -> [2,i,0] : (0 <= i <= 4) or (6 <= i <= 10) }";
3480 assert(map_is_equal(mm.must, str));
3481 str = "{ [0,5,0] -> [2,5,0]; [1,i,0] -> [2,5,0] : 0 <= i <= 10 }";
3482 assert(map_is_equal(mm.may, str));
3484 isl_map_free(mm.must);
3485 isl_map_free(mm.may);
3486 isl_flow_free(flow);
3489 str = "{ [2,i,0] -> [i] : 0 <= i <= 10 }";
3490 map = isl_map_read_from_str(ctx, str);
3491 ai = isl_access_info_alloc(map, &depth, &common_space, 2);
3493 str = "{ [0,i,0] -> [i] : 0 <= i <= 10 }";
3494 map = isl_map_read_from_str(ctx, str);
3495 ai = isl_access_info_add_source(ai, map, 0, &depth);
3497 str = "{ [1,i,0] -> [5] : 0 <= i <= 10 }";
3498 map = isl_map_read_from_str(ctx, str);
3499 ai = isl_access_info_add_source(ai, map, 0, &depth);
3501 flow = isl_access_info_compute_flow(ai);
3502 space = isl_space_alloc(ctx, 0, 3, 3);
3503 mm.must = isl_map_empty(isl_space_copy(space));
3504 mm.may = isl_map_empty(space);
3506 isl_flow_foreach(flow, collect_must_may, &mm);
3508 str = "{ [0,i,0] -> [2,i,0] : 0 <= i <= 10; "
3509 " [1,i,0] -> [2,5,0] : 0 <= i <= 10 }";
3510 assert(map_is_equal(mm.may, str));
3511 str = "{ [i,j,k] -> [l,m,n] : 1 = 0 }";
3512 assert(map_is_equal(mm.must, str));
3514 isl_map_free(mm.must);
3515 isl_map_free(mm.may);
3516 isl_flow_free(flow);
3519 str = "{ [0,i,2] -> [i] : 0 <= i <= 10 }";
3520 map = isl_map_read_from_str(ctx, str);
3521 ai = isl_access_info_alloc(map, &depth, &common_space, 2);
3523 str = "{ [0,i,0] -> [i] : 0 <= i <= 10 }";
3524 map = isl_map_read_from_str(ctx, str);
3525 ai = isl_access_info_add_source(ai, map, 0, &depth);
3527 str = "{ [0,i,1] -> [5] : 0 <= i <= 10 }";
3528 map = isl_map_read_from_str(ctx, str);
3529 ai = isl_access_info_add_source(ai, map, 0, &depth);
3531 flow = isl_access_info_compute_flow(ai);
3532 space = isl_space_alloc(ctx, 0, 3, 3);
3533 mm.must = isl_map_empty(isl_space_copy(space));
3534 mm.may = isl_map_empty(space);
3536 isl_flow_foreach(flow, collect_must_may, &mm);
3538 str = "{ [0,i,0] -> [0,i,2] : 0 <= i <= 10; "
3539 " [0,i,1] -> [0,5,2] : 0 <= i <= 5 }";
3540 assert(map_is_equal(mm.may, str));
3541 str = "{ [i,j,k] -> [l,m,n] : 1 = 0 }";
3542 assert(map_is_equal(mm.must, str));
3544 isl_map_free(mm.must);
3545 isl_map_free(mm.may);
3546 isl_flow_free(flow);
3549 str = "{ [0,i,1] -> [i] : 0 <= i <= 10 }";
3550 map = isl_map_read_from_str(ctx, str);
3551 ai = isl_access_info_alloc(map, &depth, &common_space, 2);
3553 str = "{ [0,i,0] -> [i] : 0 <= i <= 10 }";
3554 map = isl_map_read_from_str(ctx, str);
3555 ai = isl_access_info_add_source(ai, map, 0, &depth);
3557 str = "{ [0,i,2] -> [5] : 0 <= i <= 10 }";
3558 map = isl_map_read_from_str(ctx, str);
3559 ai = isl_access_info_add_source(ai, map, 0, &depth);
3561 flow = isl_access_info_compute_flow(ai);
3562 space = isl_space_alloc(ctx, 0, 3, 3);
3563 mm.must = isl_map_empty(isl_space_copy(space));
3564 mm.may = isl_map_empty(space);
3566 isl_flow_foreach(flow, collect_must_may, &mm);
3568 str = "{ [0,i,0] -> [0,i,1] : 0 <= i <= 10; "
3569 " [0,i,2] -> [0,5,1] : 0 <= i <= 4 }";
3570 assert(map_is_equal(mm.may, str));
3571 str = "{ [i,j,k] -> [l,m,n] : 1 = 0 }";
3572 assert(map_is_equal(mm.must, str));
3574 isl_map_free(mm.must);
3575 isl_map_free(mm.may);
3576 isl_flow_free(flow);
3579 depth = 5;
3581 str = "{ [1,i,0,0,0] -> [i,j] : 0 <= i <= 10 and 0 <= j <= 10 }";
3582 map = isl_map_read_from_str(ctx, str);
3583 ai = isl_access_info_alloc(map, &depth, &common_space, 1);
3585 str = "{ [0,i,0,j,0] -> [i,j] : 0 <= i <= 10 and 0 <= j <= 10 }";
3586 map = isl_map_read_from_str(ctx, str);
3587 ai = isl_access_info_add_source(ai, map, 1, &depth);
3589 flow = isl_access_info_compute_flow(ai);
3590 space = isl_space_alloc(ctx, 0, 5, 5);
3591 mm.must = isl_map_empty(isl_space_copy(space));
3592 mm.may = isl_map_empty(space);
3594 isl_flow_foreach(flow, collect_must_may, &mm);
3596 str = "{ [0,i,0,j,0] -> [1,i,0,0,0] : 0 <= i,j <= 10 }";
3597 assert(map_is_equal(mm.must, str));
3598 str = "{ [0,0,0,0,0] -> [0,0,0,0,0] : 1 = 0 }";
3599 assert(map_is_equal(mm.may, str));
3601 isl_map_free(mm.must);
3602 isl_map_free(mm.may);
3603 isl_flow_free(flow);
3605 return 0;
3608 /* Check that the dependence analysis proceeds without errors.
3609 * Earlier versions of isl would break down during the analysis
3610 * due to the use of the wrong spaces.
3612 static int test_flow(isl_ctx *ctx)
3614 const char *str;
3615 isl_union_map *access, *schedule;
3616 isl_union_map *must_dep, *may_dep;
3617 int r;
3619 str = "{ S0[j] -> i[]; S1[j,i] -> i[]; S2[] -> i[]; S3[] -> i[] }";
3620 access = isl_union_map_read_from_str(ctx, str);
3621 str = "{ S0[j] -> [0,j,0,0] : 0 <= j < 10; "
3622 "S1[j,i] -> [0,j,1,i] : 0 <= j < i < 10; "
3623 "S2[] -> [1,0,0,0]; "
3624 "S3[] -> [-1,0,0,0] }";
3625 schedule = isl_union_map_read_from_str(ctx, str);
3626 r = isl_union_map_compute_flow(access, isl_union_map_copy(access),
3627 isl_union_map_copy(access), schedule,
3628 &must_dep, &may_dep, NULL, NULL);
3629 isl_union_map_free(may_dep);
3630 isl_union_map_free(must_dep);
3632 return r;
3635 struct {
3636 const char *map;
3637 int sv;
3638 } sv_tests[] = {
3639 { "[N] -> { [i] -> [f] : 0 <= i <= N and 0 <= i - 10 f <= 9 }", 1 },
3640 { "[N] -> { [i] -> [f] : 0 <= i <= N and 0 <= i - 10 f <= 10 }", 0 },
3641 { "{ [i] -> [3*floor(i/2) + 5*floor(i/3)] }", 1 },
3642 { "{ S1[i] -> [i] : 0 <= i <= 9; S2[i] -> [i] : 0 <= i <= 9 }", 1 },
3643 { "{ [i] -> S1[i] : 0 <= i <= 9; [i] -> S2[i] : 0 <= i <= 9 }", 0 },
3644 { "{ A[i] -> [i]; B[i] -> [i]; B[i] -> [i + 1] }", 0 },
3645 { "{ A[i] -> [i]; B[i] -> [i] : i < 0; B[i] -> [i + 1] : i > 0 }", 1 },
3646 { "{ A[i] -> [i]; B[i] -> A[i] : i < 0; B[i] -> [i + 1] : i > 0 }", 1 },
3647 { "{ A[i] -> [i]; B[i] -> [j] : i - 1 <= j <= i }", 0 },
3650 int test_sv(isl_ctx *ctx)
3652 isl_union_map *umap;
3653 int i;
3654 int sv;
3656 for (i = 0; i < ARRAY_SIZE(sv_tests); ++i) {
3657 umap = isl_union_map_read_from_str(ctx, sv_tests[i].map);
3658 sv = isl_union_map_is_single_valued(umap);
3659 isl_union_map_free(umap);
3660 if (sv < 0)
3661 return -1;
3662 if (sv_tests[i].sv && !sv)
3663 isl_die(ctx, isl_error_internal,
3664 "map not detected as single valued", return -1);
3665 if (!sv_tests[i].sv && sv)
3666 isl_die(ctx, isl_error_internal,
3667 "map detected as single valued", return -1);
3670 return 0;
3673 struct {
3674 const char *str;
3675 int bijective;
3676 } bijective_tests[] = {
3677 { "[N,M]->{[i,j] -> [i]}", 0 },
3678 { "[N,M]->{[i,j] -> [i] : j=i}", 1 },
3679 { "[N,M]->{[i,j] -> [i] : j=0}", 1 },
3680 { "[N,M]->{[i,j] -> [i] : j=N}", 1 },
3681 { "[N,M]->{[i,j] -> [j,i]}", 1 },
3682 { "[N,M]->{[i,j] -> [i+j]}", 0 },
3683 { "[N,M]->{[i,j] -> []}", 0 },
3684 { "[N,M]->{[i,j] -> [i,j,N]}", 1 },
3685 { "[N,M]->{[i,j] -> [2i]}", 0 },
3686 { "[N,M]->{[i,j] -> [i,i]}", 0 },
3687 { "[N,M]->{[i,j] -> [2i,i]}", 0 },
3688 { "[N,M]->{[i,j] -> [2i,j]}", 1 },
3689 { "[N,M]->{[i,j] -> [x,y] : 2x=i & y =j}", 1 },
3692 static int test_bijective(struct isl_ctx *ctx)
3694 isl_map *map;
3695 int i;
3696 int bijective;
3698 for (i = 0; i < ARRAY_SIZE(bijective_tests); ++i) {
3699 map = isl_map_read_from_str(ctx, bijective_tests[i].str);
3700 bijective = isl_map_is_bijective(map);
3701 isl_map_free(map);
3702 if (bijective < 0)
3703 return -1;
3704 if (bijective_tests[i].bijective && !bijective)
3705 isl_die(ctx, isl_error_internal,
3706 "map not detected as bijective", return -1);
3707 if (!bijective_tests[i].bijective && bijective)
3708 isl_die(ctx, isl_error_internal,
3709 "map detected as bijective", return -1);
3712 return 0;
3715 /* Inputs for isl_pw_qpolynomial_gist tests.
3716 * "pwqp" is the input, "set" is the context and "gist" is the expected result.
3718 struct {
3719 const char *pwqp;
3720 const char *set;
3721 const char *gist;
3722 } pwqp_gist_tests[] = {
3723 { "{ [i] -> i }", "{ [k] : exists a : k = 2a }", "{ [i] -> i }" },
3724 { "{ [i] -> i + [ (i + [i/3])/2 ] }", "{ [10] }", "{ [i] -> 16 }" },
3725 { "{ [i] -> ([(i)/2]) }", "{ [k] : exists a : k = 2a+1 }",
3726 "{ [i] -> -1/2 + 1/2 * i }" },
3727 { "{ [i] -> i^2 : i != 0 }", "{ [i] : i != 0 }", "{ [i] -> i^2 }" },
3730 /* Perform some basic isl_pw_qpolynomial_gist tests.
3732 static isl_stat test_pwqp_gist(isl_ctx *ctx)
3734 int i;
3735 const char *str;
3736 isl_set *set;
3737 isl_pw_qpolynomial *pwqp1, *pwqp2;
3738 isl_bool equal;
3740 for (i = 0; i < ARRAY_SIZE(pwqp_gist_tests); ++i) {
3741 str = pwqp_gist_tests[i].pwqp;
3742 pwqp1 = isl_pw_qpolynomial_read_from_str(ctx, str);
3743 str = pwqp_gist_tests[i].set;
3744 set = isl_set_read_from_str(ctx, str);
3745 pwqp1 = isl_pw_qpolynomial_gist(pwqp1, set);
3746 str = pwqp_gist_tests[i].gist;
3747 pwqp2 = isl_pw_qpolynomial_read_from_str(ctx, str);
3748 pwqp1 = isl_pw_qpolynomial_sub(pwqp1, pwqp2);
3749 equal = isl_pw_qpolynomial_is_zero(pwqp1);
3750 isl_pw_qpolynomial_free(pwqp1);
3752 if (equal < 0)
3753 return isl_stat_error;
3754 if (!equal)
3755 isl_die(ctx, isl_error_unknown,
3756 "unexpected result", return isl_stat_error);
3759 return isl_stat_ok;
3762 /* Perform a basic isl_pw_qpolynomial_max test.
3764 static isl_stat test_pwqp_max(isl_ctx *ctx)
3766 const char *str;
3767 isl_pw_qpolynomial *pwqp;
3768 isl_val *v;
3769 int ok;
3771 str = "{ [x=2:9, y] -> floor((x + 1)/4)^3 - floor((2x)/3)^2 }";
3772 pwqp = isl_pw_qpolynomial_read_from_str(ctx, str);
3773 v = isl_pw_qpolynomial_max(pwqp);
3774 ok = isl_val_cmp_si(v, -1) == 0;
3775 isl_val_free(v);
3777 if (!v)
3778 return isl_stat_error;
3779 if (!ok)
3780 isl_die(ctx, isl_error_unknown, "unexpected maximum",
3781 return isl_stat_error);
3783 return isl_stat_ok;
3786 static int test_pwqp(struct isl_ctx *ctx)
3788 const char *str;
3789 isl_set *set;
3790 isl_pw_qpolynomial *pwqp1, *pwqp2;
3791 int equal;
3793 str = "{ [i,j,k] -> 1 + 9 * [i/5] + 7 * [j/11] + 4 * [k/13] }";
3794 pwqp1 = isl_pw_qpolynomial_read_from_str(ctx, str);
3796 pwqp1 = isl_pw_qpolynomial_move_dims(pwqp1, isl_dim_param, 0,
3797 isl_dim_in, 1, 1);
3799 str = "[j] -> { [i,k] -> 1 + 9 * [i/5] + 7 * [j/11] + 4 * [k/13] }";
3800 pwqp2 = isl_pw_qpolynomial_read_from_str(ctx, str);
3802 pwqp1 = isl_pw_qpolynomial_sub(pwqp1, pwqp2);
3804 assert(isl_pw_qpolynomial_is_zero(pwqp1));
3806 isl_pw_qpolynomial_free(pwqp1);
3808 if (test_pwqp_gist(ctx) < 0)
3809 return -1;
3811 str = "{ [i] -> ([([i/2] + [i/2])/5]) }";
3812 pwqp1 = isl_pw_qpolynomial_read_from_str(ctx, str);
3813 str = "{ [i] -> ([(2 * [i/2])/5]) }";
3814 pwqp2 = isl_pw_qpolynomial_read_from_str(ctx, str);
3816 pwqp1 = isl_pw_qpolynomial_sub(pwqp1, pwqp2);
3818 assert(isl_pw_qpolynomial_is_zero(pwqp1));
3820 isl_pw_qpolynomial_free(pwqp1);
3822 str = "{ [x] -> ([x/2] + [(x+1)/2]) }";
3823 pwqp1 = isl_pw_qpolynomial_read_from_str(ctx, str);
3824 str = "{ [x] -> x }";
3825 pwqp2 = isl_pw_qpolynomial_read_from_str(ctx, str);
3827 pwqp1 = isl_pw_qpolynomial_sub(pwqp1, pwqp2);
3829 assert(isl_pw_qpolynomial_is_zero(pwqp1));
3831 isl_pw_qpolynomial_free(pwqp1);
3833 str = "{ [i] -> ([i/2]) : i >= 0; [i] -> ([i/3]) : i < 0 }";
3834 pwqp1 = isl_pw_qpolynomial_read_from_str(ctx, str);
3835 pwqp2 = isl_pw_qpolynomial_read_from_str(ctx, str);
3836 pwqp1 = isl_pw_qpolynomial_coalesce(pwqp1);
3837 pwqp1 = isl_pw_qpolynomial_sub(pwqp1, pwqp2);
3838 assert(isl_pw_qpolynomial_is_zero(pwqp1));
3839 isl_pw_qpolynomial_free(pwqp1);
3841 str = "{ [a,b,a] -> (([(2*[a/3]+b)/5]) * ([(2*[a/3]+b)/5])) }";
3842 pwqp2 = isl_pw_qpolynomial_read_from_str(ctx, str);
3843 str = "{ [a,b,c] -> (([(2*[a/3]+b)/5]) * ([(2*[c/3]+b)/5])) }";
3844 pwqp1 = isl_pw_qpolynomial_read_from_str(ctx, str);
3845 set = isl_set_read_from_str(ctx, "{ [a,b,a] }");
3846 pwqp1 = isl_pw_qpolynomial_intersect_domain(pwqp1, set);
3847 equal = isl_pw_qpolynomial_plain_is_equal(pwqp1, pwqp2);
3848 isl_pw_qpolynomial_free(pwqp1);
3849 isl_pw_qpolynomial_free(pwqp2);
3850 if (equal < 0)
3851 return -1;
3852 if (!equal)
3853 isl_die(ctx, isl_error_unknown, "unexpected result", return -1);
3855 str = "{ [a,b,c] -> (([(2*[a/3]+1)/5]) * ([(2*[c/3]+1)/5])) : b = 1 }";
3856 pwqp2 = isl_pw_qpolynomial_read_from_str(ctx, str);
3857 str = "{ [a,b,c] -> (([(2*[a/3]+b)/5]) * ([(2*[c/3]+b)/5])) }";
3858 pwqp1 = isl_pw_qpolynomial_read_from_str(ctx, str);
3859 pwqp1 = isl_pw_qpolynomial_fix_val(pwqp1, isl_dim_set, 1,
3860 isl_val_one(ctx));
3861 equal = isl_pw_qpolynomial_plain_is_equal(pwqp1, pwqp2);
3862 isl_pw_qpolynomial_free(pwqp1);
3863 isl_pw_qpolynomial_free(pwqp2);
3864 if (equal < 0)
3865 return -1;
3866 if (!equal)
3867 isl_die(ctx, isl_error_unknown, "unexpected result", return -1);
3869 if (test_pwqp_max(ctx) < 0)
3870 return -1;
3872 return 0;
3875 static int test_split_periods(isl_ctx *ctx)
3877 const char *str;
3878 isl_pw_qpolynomial *pwqp;
3880 str = "{ [U,V] -> 1/3 * U + 2/3 * V - [(U + 2V)/3] + [U/2] : "
3881 "U + 2V + 3 >= 0 and - U -2V >= 0 and - U + 10 >= 0 and "
3882 "U >= 0; [U,V] -> U^2 : U >= 100 }";
3883 pwqp = isl_pw_qpolynomial_read_from_str(ctx, str);
3885 pwqp = isl_pw_qpolynomial_split_periods(pwqp, 2);
3887 isl_pw_qpolynomial_free(pwqp);
3889 if (!pwqp)
3890 return -1;
3892 return 0;
3895 static int test_union(isl_ctx *ctx)
3897 const char *str;
3898 isl_union_set *uset1, *uset2;
3899 isl_union_map *umap1, *umap2;
3900 int equal;
3902 str = "{ [i] : 0 <= i <= 1 }";
3903 uset1 = isl_union_set_read_from_str(ctx, str);
3904 str = "{ [1] -> [0] }";
3905 umap1 = isl_union_map_read_from_str(ctx, str);
3907 umap2 = isl_union_set_lex_gt_union_set(isl_union_set_copy(uset1), uset1);
3908 equal = isl_union_map_is_equal(umap1, umap2);
3910 isl_union_map_free(umap1);
3911 isl_union_map_free(umap2);
3913 if (equal < 0)
3914 return -1;
3915 if (!equal)
3916 isl_die(ctx, isl_error_unknown, "union maps not equal",
3917 return -1);
3919 str = "{ A[i] -> B[i]; B[i] -> C[i]; A[0] -> C[1] }";
3920 umap1 = isl_union_map_read_from_str(ctx, str);
3921 str = "{ A[i]; B[i] }";
3922 uset1 = isl_union_set_read_from_str(ctx, str);
3924 uset2 = isl_union_map_domain(umap1);
3926 equal = isl_union_set_is_equal(uset1, uset2);
3928 isl_union_set_free(uset1);
3929 isl_union_set_free(uset2);
3931 if (equal < 0)
3932 return -1;
3933 if (!equal)
3934 isl_die(ctx, isl_error_unknown, "union sets not equal",
3935 return -1);
3937 return 0;
3940 /* Inputs for basic isl_pw_qpolynomial_bound tests.
3941 * "type" is the type of bound that should be computed.
3942 * "poly" is a string representation of the input.
3943 * "bound" is a string representation of the expected result.
3944 * "tight" is set if the result is expected to be tight.
3946 static struct {
3947 int tight;
3948 enum isl_fold type;
3949 const char *poly;
3950 const char *bound;
3951 } bound_tests[] = {
3952 /* Check that computing a bound of a non-zero polynomial
3953 * over an unbounded domain does not produce a rational value.
3954 * In particular, check that the upper bound is infinity.
3956 { 0, isl_fold_max, "{ [m, n] -> -m * n }", "{ max(infty) }" },
3957 { 1, isl_fold_max, "{ [[a, b, c, d] -> [e]] -> 0 }",
3958 "{ [a, b, c, d] -> max(0) }" },
3959 { 1, isl_fold_max, "{ [[x] -> [x]] -> 1 : exists a : x = 2 a }",
3960 "{ [x] -> max(1) : x mod 2 = 0 }" },
3961 { 1, isl_fold_min, "{ [x=5:10] -> (x + 2)^2 }", "{ min(49) }" },
3962 { 1, isl_fold_max, "{ [0:10] -> 1 }", "{ max(1) }" },
3963 { 1, isl_fold_max, "{ [[m] -> [0:m]] -> m^2 }",
3964 "{ [m] -> max(m^2) : m >= 0 }" },
3967 /* Check that the bound computation can handle differences
3968 * in domain dimension names of the input polynomial and its domain.
3970 static isl_stat test_bound_space(isl_ctx *ctx)
3972 const char *str;
3973 isl_set *set;
3974 isl_pw_qpolynomial *pwqp;
3975 isl_pw_qpolynomial_fold *pwf;
3977 str = "{ [[c] -> [c]] }";
3978 set = isl_set_read_from_str(ctx, str);
3979 str = "{ [[a] -> [b]] -> 1 }";
3980 pwqp = isl_pw_qpolynomial_read_from_str(ctx, str);
3981 pwqp = isl_pw_qpolynomial_intersect_domain(pwqp, set);
3982 pwf = isl_pw_qpolynomial_bound(pwqp, isl_fold_max, NULL);
3983 isl_pw_qpolynomial_fold_free(pwf);
3985 return isl_stat_non_null(pwf);
3988 /* Perform basic isl_pw_qpolynomial_bound tests.
3990 static int test_bound(isl_ctx *ctx)
3992 int i;
3994 if (test_bound_space(ctx) < 0)
3995 return -1;
3997 for (i = 0; i < ARRAY_SIZE(bound_tests); ++i) {
3998 const char *str;
3999 enum isl_fold type;
4000 isl_bool equal, tight;
4001 isl_pw_qpolynomial *pwqp;
4002 isl_pw_qpolynomial_fold *pwf1, *pwf2;
4004 str = bound_tests[i].poly;
4005 pwqp = isl_pw_qpolynomial_read_from_str(ctx, str);
4006 type = bound_tests[i].type;
4007 pwf1 = isl_pw_qpolynomial_bound(pwqp, type, &tight);
4008 str = bound_tests[i].bound;
4009 pwf2 = isl_pw_qpolynomial_fold_read_from_str(ctx, str);
4010 equal = isl_pw_qpolynomial_fold_plain_is_equal(pwf1, pwf2);
4011 isl_pw_qpolynomial_fold_free(pwf2);
4012 isl_pw_qpolynomial_fold_free(pwf1);
4013 if (equal < 0)
4014 return -1;
4015 if (!equal)
4016 isl_die(ctx, isl_error_unknown,
4017 "incorrect bound result", return -1);
4018 if (bound_tests[i].tight && !tight)
4019 isl_die(ctx, isl_error_unknown,
4020 "bound unexpectedly not tight", return -1);
4023 return 0;
4026 /* isl_set is defined to isl_map internally, so the corresponding elements
4027 * are isl_basic_map objects.
4029 #undef EL_BASE
4030 #undef SET_BASE
4031 #define EL_BASE basic_map
4032 #define SET_BASE set
4033 #include "isl_test_list_templ.c"
4035 #undef EL_BASE
4036 #undef SET_BASE
4037 #define EL_BASE basic_set
4038 #define SET_BASE union_set
4039 #include "isl_test_list_templ.c"
4041 #undef EL_BASE
4042 #undef SET_BASE
4043 #define EL_BASE set
4044 #define SET_BASE union_set
4045 #include "isl_test_list_templ.c"
4047 #undef EL_BASE
4048 #undef SET_BASE
4049 #define EL_BASE basic_map
4050 #define SET_BASE map
4051 #include "isl_test_list_templ.c"
4053 #undef EL_BASE
4054 #undef SET_BASE
4055 #define EL_BASE map
4056 #define SET_BASE union_map
4057 #include "isl_test_list_templ.c"
4059 /* Check that the conversion from isl objects to lists works as expected.
4061 static int test_get_list(isl_ctx *ctx)
4063 if (test_get_list_basic_map_from_set(ctx, "{ [0]; [2]; [3] }"))
4064 return -1;
4065 if (test_get_list_basic_set_from_union_set(ctx, "{ A[0]; B[2]; B[3] }"))
4066 return -1;
4067 if (test_get_list_set_from_union_set(ctx, "{ A[0]; A[2]; B[3] }"))
4068 return -1;
4069 if (test_get_list_basic_map_from_map(ctx,
4070 "{ [0] -> [0]; [2] -> [0]; [3] -> [0] }"))
4071 return -1;
4072 if (test_get_list_map_from_union_map(ctx,
4073 "{ A[0] -> [0]; A[2] -> [0]; B[3] -> [0] }"))
4074 return -1;
4076 return 0;
4079 static int test_lift(isl_ctx *ctx)
4081 const char *str;
4082 isl_basic_map *bmap;
4083 isl_basic_set *bset;
4085 str = "{ [i0] : exists e0 : i0 = 4e0 }";
4086 bset = isl_basic_set_read_from_str(ctx, str);
4087 bset = isl_basic_set_lift(bset);
4088 bmap = isl_basic_map_from_range(bset);
4089 bset = isl_basic_map_domain(bmap);
4090 isl_basic_set_free(bset);
4092 return 0;
4095 /* Check that isl_set_is_subset is not confused by identical
4096 * integer divisions.
4097 * The call to isl_set_normalize ensures that the equality constraints
4098 * a = b = 0 are discovered, turning e0 and e1 into identical
4099 * integer divisions. Any further simplification would remove
4100 * the duplicate integer divisions.
4102 static isl_stat test_subset_duplicate_integer_divisions(isl_ctx *ctx)
4104 const char *str;
4105 isl_bool is_subset;
4106 isl_set *set1, *set2;
4108 str = "{ [a, b, c, d] : "
4109 "exists (e0 = floor((a + d)/4), e1 = floor((d)/4), "
4110 "e2 = floor((-a - d + 4 *floor((a + d)/4))/10), "
4111 "e3 = floor((-d + 4*floor((d)/4))/10): "
4112 "10e2 = -a - 2c - d + 4e0 and 10e3 = -2c - d + 4e1 and "
4113 "b >= 0 and a <= 0 and b <= a) }";
4114 set1 = isl_set_read_from_str(ctx, str);
4115 set2 = isl_set_read_from_str(ctx, str);
4116 set2 = isl_set_normalize(set2);
4118 is_subset = isl_set_is_subset(set1, set2);
4120 isl_set_free(set1);
4121 isl_set_free(set2);
4123 if (is_subset < 0)
4124 return isl_stat_error;
4125 if (!is_subset)
4126 isl_die(ctx, isl_error_unknown,
4127 "set is not considered to be a subset of itself",
4128 return isl_stat_error);
4130 return isl_stat_ok;
4133 struct {
4134 const char *set1;
4135 const char *set2;
4136 int subset;
4137 } subset_tests[] = {
4138 { "{ [112, 0] }",
4139 "{ [i0, i1] : exists (e0 = [(i0 - i1)/16], e1: "
4140 "16e0 <= i0 - i1 and 16e0 >= -15 + i0 - i1 and "
4141 "16e1 <= i1 and 16e0 >= -i1 and 16e1 >= -i0 + i1) }", 1 },
4142 { "{ [65] }",
4143 "{ [i] : exists (e0 = [(255i)/256], e1 = [(127i + 65e0)/191], "
4144 "e2 = [(3i + 61e1)/65], e3 = [(52i + 12e2)/61], "
4145 "e4 = [(2i + e3)/3], e5 = [(4i + e3)/4], e6 = [(8i + e3)/12]: "
4146 "3e4 = 2i + e3 and 4e5 = 4i + e3 and 12e6 = 8i + e3 and "
4147 "i <= 255 and 64e3 >= -45 + 67i and i >= 0 and "
4148 "256e0 <= 255i and 256e0 >= -255 + 255i and "
4149 "191e1 <= 127i + 65e0 and 191e1 >= -190 + 127i + 65e0 and "
4150 "65e2 <= 3i + 61e1 and 65e2 >= -64 + 3i + 61e1 and "
4151 "61e3 <= 52i + 12e2 and 61e3 >= -60 + 52i + 12e2) }", 1 },
4152 { "{ [i] : 0 <= i <= 10 }", "{ rat: [i] : 0 <= i <= 10 }", 1 },
4153 { "{ rat: [i] : 0 <= i <= 10 }", "{ [i] : 0 <= i <= 10 }", 0 },
4154 { "{ rat: [0] }", "{ [i] : 0 <= i <= 10 }", 1 },
4155 { "{ rat: [(1)/2] }", "{ [i] : 0 <= i <= 10 }", 0 },
4156 { "{ [t, i] : (exists (e0 = [(2 + t)/4]: 4e0 <= 2 + t and "
4157 "4e0 >= -1 + t and i >= 57 and i <= 62 and "
4158 "4e0 <= 62 + t - i and 4e0 >= -61 + t + i and "
4159 "t >= 0 and t <= 511 and 4e0 <= -57 + t + i and "
4160 "4e0 >= 58 + t - i and i >= 58 + t and i >= 62 - t)) }",
4161 "{ [i0, i1] : (exists (e0 = [(4 + i0)/4]: 4e0 <= 62 + i0 - i1 and "
4162 "4e0 >= 1 + i0 and i0 >= 0 and i0 <= 511 and "
4163 "4e0 <= -57 + i0 + i1)) or "
4164 "(exists (e0 = [(2 + i0)/4]: 4e0 <= i0 and "
4165 "4e0 >= 58 + i0 - i1 and i0 >= 2 and i0 <= 511 and "
4166 "4e0 >= -61 + i0 + i1)) or "
4167 "(i1 <= 66 - i0 and i0 >= 2 and i1 >= 59 + i0) }", 1 },
4168 { "[a, b] -> { : a = 0 and b = -1 }", "[b, a] -> { : b >= -10 }", 1 },
4171 static int test_subset(isl_ctx *ctx)
4173 int i;
4174 isl_set *set1, *set2;
4175 int subset;
4177 if (test_subset_duplicate_integer_divisions(ctx) < 0)
4178 return -1;
4180 for (i = 0; i < ARRAY_SIZE(subset_tests); ++i) {
4181 set1 = isl_set_read_from_str(ctx, subset_tests[i].set1);
4182 set2 = isl_set_read_from_str(ctx, subset_tests[i].set2);
4183 subset = isl_set_is_subset(set1, set2);
4184 isl_set_free(set1);
4185 isl_set_free(set2);
4186 if (subset < 0)
4187 return -1;
4188 if (subset != subset_tests[i].subset)
4189 isl_die(ctx, isl_error_unknown,
4190 "incorrect subset result", return -1);
4193 return 0;
4196 /* Perform a set subtraction with a set that has a non-obviously empty disjunct.
4197 * Older versions of isl would fail on such cases.
4199 static isl_stat test_subtract_empty(isl_ctx *ctx)
4201 const char *str;
4202 isl_set *s1, *s2;
4204 s1 = isl_set_read_from_str(ctx, "{ [0] }");
4205 str = "{ [a] : (exists (e0, e1, e2: 1056e1 <= 32 + a - 33e0 and "
4206 "1089e1 >= a - 33e0 and 1089e1 <= 1 + a - 33e0 and "
4207 "33e2 >= -a + 33e0 + 1056e1 and "
4208 "33e2 < -2a + 66e0 + 2112e1)) or a = 0 }";
4209 s2 = isl_set_read_from_str(ctx, str);
4210 s1 = isl_set_subtract(s1, s2);
4211 isl_set_free(s1);
4213 return isl_stat_non_null(s1);
4216 struct {
4217 const char *minuend;
4218 const char *subtrahend;
4219 const char *difference;
4220 } subtract_domain_tests[] = {
4221 { "{ A[i] -> B[i] }", "{ A[i] }", "{ }" },
4222 { "{ A[i] -> B[i] }", "{ B[i] }", "{ A[i] -> B[i] }" },
4223 { "{ A[i] -> B[i] }", "{ A[i] : i > 0 }", "{ A[i] -> B[i] : i <= 0 }" },
4226 static int test_subtract(isl_ctx *ctx)
4228 int i;
4229 isl_union_map *umap1, *umap2;
4230 isl_union_pw_multi_aff *upma1, *upma2;
4231 isl_union_set *uset;
4232 int equal;
4234 if (test_subtract_empty(ctx) < 0)
4235 return -1;
4237 for (i = 0; i < ARRAY_SIZE(subtract_domain_tests); ++i) {
4238 umap1 = isl_union_map_read_from_str(ctx,
4239 subtract_domain_tests[i].minuend);
4240 uset = isl_union_set_read_from_str(ctx,
4241 subtract_domain_tests[i].subtrahend);
4242 umap2 = isl_union_map_read_from_str(ctx,
4243 subtract_domain_tests[i].difference);
4244 umap1 = isl_union_map_subtract_domain(umap1, uset);
4245 equal = isl_union_map_is_equal(umap1, umap2);
4246 isl_union_map_free(umap1);
4247 isl_union_map_free(umap2);
4248 if (equal < 0)
4249 return -1;
4250 if (!equal)
4251 isl_die(ctx, isl_error_unknown,
4252 "incorrect subtract domain result", return -1);
4255 for (i = 0; i < ARRAY_SIZE(subtract_domain_tests); ++i) {
4256 upma1 = isl_union_pw_multi_aff_read_from_str(ctx,
4257 subtract_domain_tests[i].minuend);
4258 uset = isl_union_set_read_from_str(ctx,
4259 subtract_domain_tests[i].subtrahend);
4260 upma2 = isl_union_pw_multi_aff_read_from_str(ctx,
4261 subtract_domain_tests[i].difference);
4262 upma1 = isl_union_pw_multi_aff_subtract_domain(upma1, uset);
4263 equal = isl_union_pw_multi_aff_plain_is_equal(upma1, upma2);
4264 isl_union_pw_multi_aff_free(upma1);
4265 isl_union_pw_multi_aff_free(upma2);
4266 if (equal < 0)
4267 return -1;
4268 if (!equal)
4269 isl_die(ctx, isl_error_unknown,
4270 "incorrect subtract domain result", return -1);
4273 return 0;
4276 /* Check that intersecting the empty basic set with another basic set
4277 * does not increase the number of constraints. In particular,
4278 * the empty basic set should maintain its canonical representation.
4280 static int test_intersect_1(isl_ctx *ctx)
4282 isl_size n1, n2;
4283 isl_basic_set *bset1, *bset2;
4285 bset1 = isl_basic_set_read_from_str(ctx, "{ [a,b,c] : 1 = 0 }");
4286 bset2 = isl_basic_set_read_from_str(ctx, "{ [1,2,3] }");
4287 n1 = isl_basic_set_n_constraint(bset1);
4288 bset1 = isl_basic_set_intersect(bset1, bset2);
4289 n2 = isl_basic_set_n_constraint(bset1);
4290 isl_basic_set_free(bset1);
4291 if (n1 < 0 || n2 < 0)
4292 return -1;
4293 if (n1 != n2)
4294 isl_die(ctx, isl_error_unknown,
4295 "number of constraints of empty set changed",
4296 return -1);
4298 return 0;
4301 /* Check that intersecting a set with itself does not cause
4302 * an explosion in the number of disjuncts.
4304 static isl_stat test_intersect_2(isl_ctx *ctx)
4306 int i;
4307 isl_set *set;
4309 set = isl_set_read_from_str(ctx, "{ [x,y] : x >= 0 or y >= 0 }");
4310 for (i = 0; i < 100; ++i)
4311 set = isl_set_intersect(set, isl_set_copy(set));
4312 isl_set_free(set);
4313 if (!set)
4314 return isl_stat_error;
4315 return isl_stat_ok;
4318 /* Perform some intersection tests.
4320 static int test_intersect(isl_ctx *ctx)
4322 if (test_intersect_1(ctx) < 0)
4323 return -1;
4324 if (test_intersect_2(ctx) < 0)
4325 return -1;
4327 return 0;
4330 int test_factorize(isl_ctx *ctx)
4332 const char *str;
4333 isl_basic_set *bset;
4334 isl_factorizer *f;
4336 str = "{ [i0, i1, i2, i3, i4, i5, i6, i7] : 3i5 <= 2 - 2i0 and "
4337 "i0 >= -2 and i6 >= 1 + i3 and i7 >= 0 and 3i5 >= -2i0 and "
4338 "2i4 <= i2 and i6 >= 1 + 2i0 + 3i1 and i4 <= -1 and "
4339 "i6 >= 1 + 2i0 + 3i5 and i6 <= 2 + 2i0 + 3i5 and "
4340 "3i5 <= 2 - 2i0 - i2 + 3i4 and i6 <= 2 + 2i0 + 3i1 and "
4341 "i0 <= -1 and i7 <= i2 + i3 - 3i4 - i6 and "
4342 "3i5 >= -2i0 - i2 + 3i4 }";
4343 bset = isl_basic_set_read_from_str(ctx, str);
4344 f = isl_basic_set_factorizer(bset);
4345 isl_basic_set_free(bset);
4346 isl_factorizer_free(f);
4347 if (!f)
4348 isl_die(ctx, isl_error_unknown,
4349 "failed to construct factorizer", return -1);
4351 str = "{ [i0, i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11, i12] : "
4352 "i12 <= 2 + i0 - i11 and 2i8 >= -i4 and i11 >= i1 and "
4353 "3i5 <= -i2 and 2i11 >= -i4 - 2i7 and i11 <= 3 + i0 + 3i9 and "
4354 "i11 <= -i4 - 2i7 and i12 >= -i10 and i2 >= -2 and "
4355 "i11 >= i1 + 3i10 and i11 >= 1 + i0 + 3i9 and "
4356 "i11 <= 1 - i4 - 2i8 and 6i6 <= 6 - i2 and 3i6 >= 1 - i2 and "
4357 "i11 <= 2 + i1 and i12 <= i4 + i11 and i12 >= i0 - i11 and "
4358 "3i5 >= -2 - i2 and i12 >= -1 + i4 + i11 and 3i3 <= 3 - i2 and "
4359 "9i6 <= 11 - i2 + 6i5 and 3i3 >= 1 - i2 and "
4360 "9i6 <= 5 - i2 + 6i3 and i12 <= -1 and i2 <= 0 }";
4361 bset = isl_basic_set_read_from_str(ctx, str);
4362 f = isl_basic_set_factorizer(bset);
4363 isl_basic_set_free(bset);
4364 isl_factorizer_free(f);
4365 if (!f)
4366 isl_die(ctx, isl_error_unknown,
4367 "failed to construct factorizer", return -1);
4369 return 0;
4372 static isl_stat check_injective(__isl_take isl_map *map, void *user)
4374 int *injective = user;
4376 *injective = isl_map_is_injective(map);
4377 isl_map_free(map);
4379 if (*injective < 0 || !*injective)
4380 return isl_stat_error;
4382 return isl_stat_ok;
4385 int test_one_schedule(isl_ctx *ctx, const char *d, const char *w,
4386 const char *r, const char *s, int tilable, int parallel)
4388 int i;
4389 isl_union_set *D;
4390 isl_union_map *W, *R, *S;
4391 isl_union_map *empty;
4392 isl_union_map *dep_raw, *dep_war, *dep_waw, *dep;
4393 isl_union_map *validity, *proximity, *coincidence;
4394 isl_union_map *schedule;
4395 isl_union_map *test;
4396 isl_union_set *delta;
4397 isl_union_set *domain;
4398 isl_set *delta_set;
4399 isl_set *slice;
4400 isl_set *origin;
4401 isl_schedule_constraints *sc;
4402 isl_schedule *sched;
4403 int is_nonneg, is_parallel, is_tilable, is_injection, is_complete;
4404 isl_size n;
4406 D = isl_union_set_read_from_str(ctx, d);
4407 W = isl_union_map_read_from_str(ctx, w);
4408 R = isl_union_map_read_from_str(ctx, r);
4409 S = isl_union_map_read_from_str(ctx, s);
4411 W = isl_union_map_intersect_domain(W, isl_union_set_copy(D));
4412 R = isl_union_map_intersect_domain(R, isl_union_set_copy(D));
4414 empty = isl_union_map_empty(isl_union_map_get_space(S));
4415 isl_union_map_compute_flow(isl_union_map_copy(R),
4416 isl_union_map_copy(W), empty,
4417 isl_union_map_copy(S),
4418 &dep_raw, NULL, NULL, NULL);
4419 isl_union_map_compute_flow(isl_union_map_copy(W),
4420 isl_union_map_copy(W),
4421 isl_union_map_copy(R),
4422 isl_union_map_copy(S),
4423 &dep_waw, &dep_war, NULL, NULL);
4425 dep = isl_union_map_union(dep_waw, dep_war);
4426 dep = isl_union_map_union(dep, dep_raw);
4427 validity = isl_union_map_copy(dep);
4428 coincidence = isl_union_map_copy(dep);
4429 proximity = isl_union_map_copy(dep);
4431 sc = isl_schedule_constraints_on_domain(isl_union_set_copy(D));
4432 sc = isl_schedule_constraints_set_validity(sc, validity);
4433 sc = isl_schedule_constraints_set_coincidence(sc, coincidence);
4434 sc = isl_schedule_constraints_set_proximity(sc, proximity);
4435 sched = isl_schedule_constraints_compute_schedule(sc);
4436 schedule = isl_schedule_get_map(sched);
4437 isl_schedule_free(sched);
4438 isl_union_map_free(W);
4439 isl_union_map_free(R);
4440 isl_union_map_free(S);
4442 is_injection = 1;
4443 isl_union_map_foreach_map(schedule, &check_injective, &is_injection);
4445 domain = isl_union_map_domain(isl_union_map_copy(schedule));
4446 is_complete = isl_union_set_is_subset(D, domain);
4447 isl_union_set_free(D);
4448 isl_union_set_free(domain);
4450 test = isl_union_map_reverse(isl_union_map_copy(schedule));
4451 test = isl_union_map_apply_range(test, dep);
4452 test = isl_union_map_apply_range(test, schedule);
4454 delta = isl_union_map_deltas(test);
4455 n = isl_union_set_n_set(delta);
4456 if (n < 0) {
4457 isl_union_set_free(delta);
4458 return -1;
4460 if (n == 0) {
4461 is_tilable = 1;
4462 is_parallel = 1;
4463 is_nonneg = 1;
4464 isl_union_set_free(delta);
4465 } else {
4466 isl_size dim;
4468 delta_set = isl_set_from_union_set(delta);
4470 slice = isl_set_universe(isl_set_get_space(delta_set));
4471 for (i = 0; i < tilable; ++i)
4472 slice = isl_set_lower_bound_si(slice, isl_dim_set, i, 0);
4473 is_tilable = isl_set_is_subset(delta_set, slice);
4474 isl_set_free(slice);
4476 slice = isl_set_universe(isl_set_get_space(delta_set));
4477 for (i = 0; i < parallel; ++i)
4478 slice = isl_set_fix_si(slice, isl_dim_set, i, 0);
4479 is_parallel = isl_set_is_subset(delta_set, slice);
4480 isl_set_free(slice);
4482 origin = isl_set_universe(isl_set_get_space(delta_set));
4483 dim = isl_set_dim(origin, isl_dim_set);
4484 if (dim < 0)
4485 origin = isl_set_free(origin);
4486 for (i = 0; i < dim; ++i)
4487 origin = isl_set_fix_si(origin, isl_dim_set, i, 0);
4489 delta_set = isl_set_union(delta_set, isl_set_copy(origin));
4490 delta_set = isl_set_lexmin(delta_set);
4492 is_nonneg = isl_set_is_equal(delta_set, origin);
4494 isl_set_free(origin);
4495 isl_set_free(delta_set);
4498 if (is_nonneg < 0 || is_parallel < 0 || is_tilable < 0 ||
4499 is_injection < 0 || is_complete < 0)
4500 return -1;
4501 if (!is_complete)
4502 isl_die(ctx, isl_error_unknown,
4503 "generated schedule incomplete", return -1);
4504 if (!is_injection)
4505 isl_die(ctx, isl_error_unknown,
4506 "generated schedule not injective on each statement",
4507 return -1);
4508 if (!is_nonneg)
4509 isl_die(ctx, isl_error_unknown,
4510 "negative dependences in generated schedule",
4511 return -1);
4512 if (!is_tilable)
4513 isl_die(ctx, isl_error_unknown,
4514 "generated schedule not as tilable as expected",
4515 return -1);
4516 if (!is_parallel)
4517 isl_die(ctx, isl_error_unknown,
4518 "generated schedule not as parallel as expected",
4519 return -1);
4521 return 0;
4524 /* Compute a schedule for the given instance set, validity constraints,
4525 * proximity constraints and context and return a corresponding union map
4526 * representation.
4528 static __isl_give isl_union_map *compute_schedule_with_context(isl_ctx *ctx,
4529 const char *domain, const char *validity, const char *proximity,
4530 const char *context)
4532 isl_set *con;
4533 isl_union_set *dom;
4534 isl_union_map *dep;
4535 isl_union_map *prox;
4536 isl_schedule_constraints *sc;
4537 isl_schedule *schedule;
4538 isl_union_map *sched;
4540 con = isl_set_read_from_str(ctx, context);
4541 dom = isl_union_set_read_from_str(ctx, domain);
4542 dep = isl_union_map_read_from_str(ctx, validity);
4543 prox = isl_union_map_read_from_str(ctx, proximity);
4544 sc = isl_schedule_constraints_on_domain(dom);
4545 sc = isl_schedule_constraints_set_context(sc, con);
4546 sc = isl_schedule_constraints_set_validity(sc, dep);
4547 sc = isl_schedule_constraints_set_proximity(sc, prox);
4548 schedule = isl_schedule_constraints_compute_schedule(sc);
4549 sched = isl_schedule_get_map(schedule);
4550 isl_schedule_free(schedule);
4552 return sched;
4555 /* Compute a schedule for the given instance set, validity constraints and
4556 * proximity constraints and return a corresponding union map representation.
4558 static __isl_give isl_union_map *compute_schedule(isl_ctx *ctx,
4559 const char *domain, const char *validity, const char *proximity)
4561 return compute_schedule_with_context(ctx, domain, validity, proximity,
4562 "{ : }");
4565 /* Check that a schedule can be constructed on the given domain
4566 * with the given validity and proximity constraints.
4568 static int test_has_schedule(isl_ctx *ctx, const char *domain,
4569 const char *validity, const char *proximity)
4571 isl_union_map *sched;
4573 sched = compute_schedule(ctx, domain, validity, proximity);
4574 if (!sched)
4575 return -1;
4577 isl_union_map_free(sched);
4578 return 0;
4581 int test_special_schedule(isl_ctx *ctx, const char *domain,
4582 const char *validity, const char *proximity, const char *expected_sched)
4584 isl_union_map *sched1, *sched2;
4585 int equal;
4587 sched1 = compute_schedule(ctx, domain, validity, proximity);
4588 sched2 = isl_union_map_read_from_str(ctx, expected_sched);
4590 equal = isl_union_map_is_equal(sched1, sched2);
4591 isl_union_map_free(sched1);
4592 isl_union_map_free(sched2);
4594 if (equal < 0)
4595 return -1;
4596 if (!equal)
4597 isl_die(ctx, isl_error_unknown, "unexpected schedule",
4598 return -1);
4600 return 0;
4603 /* Check that the schedule map is properly padded, i.e., that the range
4604 * lives in a single space.
4606 static int test_padded_schedule(isl_ctx *ctx)
4608 const char *str;
4609 isl_union_set *D;
4610 isl_union_map *validity, *proximity;
4611 isl_schedule_constraints *sc;
4612 isl_schedule *sched;
4613 isl_union_map *umap;
4614 isl_union_set *range;
4615 isl_set *set;
4617 str = "[N] -> { S0[i] : 0 <= i <= N; S1[i, j] : 0 <= i, j <= N }";
4618 D = isl_union_set_read_from_str(ctx, str);
4619 validity = isl_union_map_empty(isl_union_set_get_space(D));
4620 proximity = isl_union_map_copy(validity);
4621 sc = isl_schedule_constraints_on_domain(D);
4622 sc = isl_schedule_constraints_set_validity(sc, validity);
4623 sc = isl_schedule_constraints_set_proximity(sc, proximity);
4624 sched = isl_schedule_constraints_compute_schedule(sc);
4625 umap = isl_schedule_get_map(sched);
4626 isl_schedule_free(sched);
4627 range = isl_union_map_range(umap);
4628 set = isl_set_from_union_set(range);
4629 isl_set_free(set);
4631 if (!set)
4632 return -1;
4634 return 0;
4637 /* Check that conditional validity constraints are also taken into
4638 * account across bands.
4639 * In particular, try to make sure that live ranges D[1,0]->C[2,1] and
4640 * D[2,0]->C[3,0] are not local in the outer band of the generated schedule
4641 * and then check that the adjacent order constraint C[2,1]->D[2,0]
4642 * is enforced by the rest of the schedule.
4644 static int test_special_conditional_schedule_constraints(isl_ctx *ctx)
4646 const char *str;
4647 isl_union_set *domain;
4648 isl_union_map *validity, *proximity, *condition;
4649 isl_union_map *sink, *source, *dep;
4650 isl_schedule_constraints *sc;
4651 isl_schedule *schedule;
4652 isl_union_access_info *access;
4653 isl_union_flow *flow;
4654 int empty;
4656 str = "[n] -> { C[k, i] : k <= -1 + n and i >= 0 and i <= -1 + k; "
4657 "A[k] : k >= 1 and k <= -1 + n; "
4658 "B[k, i] : k <= -1 + n and i >= 0 and i <= -1 + k; "
4659 "D[k, i] : k <= -1 + n and i >= 0 and i <= -1 + k }";
4660 domain = isl_union_set_read_from_str(ctx, str);
4661 sc = isl_schedule_constraints_on_domain(domain);
4662 str = "[n] -> { D[k, i] -> C[1 + k, k - i] : "
4663 "k <= -2 + n and i >= 1 and i <= -1 + k; "
4664 "D[k, i] -> C[1 + k, i] : "
4665 "k <= -2 + n and i >= 1 and i <= -1 + k; "
4666 "D[k, 0] -> C[1 + k, k] : k >= 1 and k <= -2 + n; "
4667 "D[k, 0] -> C[1 + k, 0] : k >= 1 and k <= -2 + n }";
4668 validity = isl_union_map_read_from_str(ctx, str);
4669 sc = isl_schedule_constraints_set_validity(sc, validity);
4670 str = "[n] -> { C[k, i] -> D[k, i] : "
4671 "0 <= i <= -1 + k and k <= -1 + n }";
4672 proximity = isl_union_map_read_from_str(ctx, str);
4673 sc = isl_schedule_constraints_set_proximity(sc, proximity);
4674 str = "[n] -> { [D[k, i] -> a[]] -> [C[1 + k, k - i] -> b[]] : "
4675 "i <= -1 + k and i >= 1 and k <= -2 + n; "
4676 "[B[k, i] -> c[]] -> [B[k, 1 + i] -> c[]] : "
4677 "k <= -1 + n and i >= 0 and i <= -2 + k }";
4678 condition = isl_union_map_read_from_str(ctx, str);
4679 str = "[n] -> { [B[k, i] -> e[]] -> [D[k, i] -> a[]] : "
4680 "i >= 0 and i <= -1 + k and k <= -1 + n; "
4681 "[C[k, i] -> b[]] -> [D[k', -1 + k - i] -> a[]] : "
4682 "i >= 0 and i <= -1 + k and k <= -1 + n and "
4683 "k' <= -1 + n and k' >= k - i and k' >= 1 + k; "
4684 "[C[k, i] -> b[]] -> [D[k, -1 + k - i] -> a[]] : "
4685 "i >= 0 and i <= -1 + k and k <= -1 + n; "
4686 "[B[k, i] -> c[]] -> [A[k'] -> d[]] : "
4687 "k <= -1 + n and i >= 0 and i <= -1 + k and "
4688 "k' >= 1 and k' <= -1 + n and k' >= 1 + k }";
4689 validity = isl_union_map_read_from_str(ctx, str);
4690 sc = isl_schedule_constraints_set_conditional_validity(sc, condition,
4691 validity);
4692 schedule = isl_schedule_constraints_compute_schedule(sc);
4693 str = "{ D[2,0] -> [] }";
4694 sink = isl_union_map_read_from_str(ctx, str);
4695 access = isl_union_access_info_from_sink(sink);
4696 str = "{ C[2,1] -> [] }";
4697 source = isl_union_map_read_from_str(ctx, str);
4698 access = isl_union_access_info_set_must_source(access, source);
4699 access = isl_union_access_info_set_schedule(access, schedule);
4700 flow = isl_union_access_info_compute_flow(access);
4701 dep = isl_union_flow_get_must_dependence(flow);
4702 isl_union_flow_free(flow);
4703 empty = isl_union_map_is_empty(dep);
4704 isl_union_map_free(dep);
4706 if (empty < 0)
4707 return -1;
4708 if (empty)
4709 isl_die(ctx, isl_error_unknown,
4710 "conditional validity not respected", return -1);
4712 return 0;
4715 /* Check that the test for violated conditional validity constraints
4716 * is not confused by domain compression.
4717 * In particular, earlier versions of isl would apply
4718 * a schedule on the compressed domains to the original domains,
4719 * resulting in a failure to detect that the default schedule
4720 * violates the conditional validity constraints.
4722 static int test_special_conditional_schedule_constraints_2(isl_ctx *ctx)
4724 const char *str;
4725 isl_bool empty;
4726 isl_union_set *domain;
4727 isl_union_map *validity, *condition;
4728 isl_schedule_constraints *sc;
4729 isl_schedule *schedule;
4730 isl_union_map *umap;
4731 isl_map *map, *ge;
4733 str = "{ A[0, i] : 0 <= i <= 10; B[1, i] : 0 <= i <= 10 }";
4734 domain = isl_union_set_read_from_str(ctx, str);
4735 sc = isl_schedule_constraints_on_domain(domain);
4736 str = "{ B[1, i] -> A[0, i + 1] }";
4737 condition = isl_union_map_read_from_str(ctx, str);
4738 str = "{ A[0, i] -> B[1, i - 1] }";
4739 validity = isl_union_map_read_from_str(ctx, str);
4740 sc = isl_schedule_constraints_set_conditional_validity(sc, condition,
4741 isl_union_map_copy(validity));
4742 schedule = isl_schedule_constraints_compute_schedule(sc);
4743 umap = isl_schedule_get_map(schedule);
4744 isl_schedule_free(schedule);
4745 validity = isl_union_map_apply_domain(validity,
4746 isl_union_map_copy(umap));
4747 validity = isl_union_map_apply_range(validity, umap);
4748 map = isl_map_from_union_map(validity);
4749 ge = isl_map_lex_ge(isl_space_domain(isl_map_get_space(map)));
4750 map = isl_map_intersect(map, ge);
4751 empty = isl_map_is_empty(map);
4752 isl_map_free(map);
4754 if (empty < 0)
4755 return -1;
4756 if (!empty)
4757 isl_die(ctx, isl_error_unknown,
4758 "conditional validity constraints not satisfied",
4759 return -1);
4761 return 0;
4764 /* Input for testing of schedule construction based on
4765 * conditional constraints.
4767 * domain is the iteration domain
4768 * flow are the flow dependences, which determine the validity and
4769 * proximity constraints
4770 * condition are the conditions on the conditional validity constraints
4771 * conditional_validity are the conditional validity constraints
4772 * outer_band_n is the expected number of members in the outer band
4774 struct {
4775 const char *domain;
4776 const char *flow;
4777 const char *condition;
4778 const char *conditional_validity;
4779 int outer_band_n;
4780 } live_range_tests[] = {
4781 /* Contrived example that illustrates that we need to keep
4782 * track of tagged condition dependences and
4783 * tagged conditional validity dependences
4784 * in isl_sched_edge separately.
4785 * In particular, the conditional validity constraints on A
4786 * cannot be satisfied,
4787 * but they can be ignored because there are no corresponding
4788 * condition constraints. However, we do have an additional
4789 * conditional validity constraint that maps to the same
4790 * dependence relation
4791 * as the condition constraint on B. If we did not make a distinction
4792 * between tagged condition and tagged conditional validity
4793 * dependences, then we
4794 * could end up treating this shared dependence as an condition
4795 * constraint on A, forcing a localization of the conditions,
4796 * which is impossible.
4798 { "{ S[i] : 0 <= 1 < 100; T[i] : 0 <= 1 < 100 }",
4799 "{ S[i] -> S[i+1] : 0 <= i < 99 }",
4800 "{ [S[i] -> B[]] -> [S[i+1] -> B[]] : 0 <= i < 99 }",
4801 "{ [S[i] -> A[]] -> [T[i'] -> A[]] : 0 <= i', i < 100 and i != i';"
4802 "[T[i] -> A[]] -> [S[i'] -> A[]] : 0 <= i', i < 100 and i != i';"
4803 "[S[i] -> A[]] -> [S[i+1] -> A[]] : 0 <= i < 99 }",
4806 /* TACO 2013 Fig. 7 */
4807 { "[n] -> { S1[i,j] : 0 <= i,j < n; S2[i,j] : 0 <= i,j < n }",
4808 "[n] -> { S1[i,j] -> S2[i,j] : 0 <= i,j < n;"
4809 "S2[i,j] -> S2[i,j+1] : 0 <= i < n and 0 <= j < n - 1 }",
4810 "[n] -> { [S1[i,j] -> t[]] -> [S2[i,j] -> t[]] : 0 <= i,j < n;"
4811 "[S2[i,j] -> x1[]] -> [S2[i,j+1] -> x1[]] : "
4812 "0 <= i < n and 0 <= j < n - 1 }",
4813 "[n] -> { [S2[i,j] -> t[]] -> [S1[i,j'] -> t[]] : "
4814 "0 <= i < n and 0 <= j < j' < n;"
4815 "[S2[i,j] -> t[]] -> [S1[i',j'] -> t[]] : "
4816 "0 <= i < i' < n and 0 <= j,j' < n;"
4817 "[S2[i,j] -> x1[]] -> [S2[i,j'] -> x1[]] : "
4818 "0 <= i,j,j' < n and j < j' }",
4821 /* TACO 2013 Fig. 7, without tags */
4822 { "[n] -> { S1[i,j] : 0 <= i,j < n; S2[i,j] : 0 <= i,j < n }",
4823 "[n] -> { S1[i,j] -> S2[i,j] : 0 <= i,j < n;"
4824 "S2[i,j] -> S2[i,j+1] : 0 <= i < n and 0 <= j < n - 1 }",
4825 "[n] -> { S1[i,j] -> S2[i,j] : 0 <= i,j < n;"
4826 "S2[i,j] -> S2[i,j+1] : 0 <= i < n and 0 <= j < n - 1 }",
4827 "[n] -> { S2[i,j] -> S1[i,j'] : 0 <= i < n and 0 <= j < j' < n;"
4828 "S2[i,j] -> S1[i',j'] : 0 <= i < i' < n and 0 <= j,j' < n;"
4829 "S2[i,j] -> S2[i,j'] : 0 <= i,j,j' < n and j < j' }",
4832 /* TACO 2013 Fig. 12 */
4833 { "{ S1[i,0] : 0 <= i <= 1; S2[i,j] : 0 <= i <= 1 and 1 <= j <= 2;"
4834 "S3[i,3] : 0 <= i <= 1 }",
4835 "{ S1[i,0] -> S2[i,1] : 0 <= i <= 1;"
4836 "S2[i,1] -> S2[i,2] : 0 <= i <= 1;"
4837 "S2[i,2] -> S3[i,3] : 0 <= i <= 1 }",
4838 "{ [S1[i,0]->t[]] -> [S2[i,1]->t[]] : 0 <= i <= 1;"
4839 "[S2[i,1]->t[]] -> [S2[i,2]->t[]] : 0 <= i <= 1;"
4840 "[S2[i,2]->t[]] -> [S3[i,3]->t[]] : 0 <= i <= 1 }",
4841 "{ [S2[i,1]->t[]] -> [S2[i,2]->t[]] : 0 <= i <= 1;"
4842 "[S2[0,j]->t[]] -> [S2[1,j']->t[]] : 1 <= j,j' <= 2;"
4843 "[S2[0,j]->t[]] -> [S1[1,0]->t[]] : 1 <= j <= 2;"
4844 "[S3[0,3]->t[]] -> [S2[1,j]->t[]] : 1 <= j <= 2;"
4845 "[S3[0,3]->t[]] -> [S1[1,0]->t[]] }",
4850 /* Test schedule construction based on conditional constraints.
4851 * In particular, check the number of members in the outer band node
4852 * as an indication of whether tiling is possible or not.
4854 static int test_conditional_schedule_constraints(isl_ctx *ctx)
4856 int i;
4857 isl_union_set *domain;
4858 isl_union_map *condition;
4859 isl_union_map *flow;
4860 isl_union_map *validity;
4861 isl_schedule_constraints *sc;
4862 isl_schedule *schedule;
4863 isl_schedule_node *node;
4864 isl_size n_member;
4866 if (test_special_conditional_schedule_constraints(ctx) < 0)
4867 return -1;
4868 if (test_special_conditional_schedule_constraints_2(ctx) < 0)
4869 return -1;
4871 for (i = 0; i < ARRAY_SIZE(live_range_tests); ++i) {
4872 domain = isl_union_set_read_from_str(ctx,
4873 live_range_tests[i].domain);
4874 flow = isl_union_map_read_from_str(ctx,
4875 live_range_tests[i].flow);
4876 condition = isl_union_map_read_from_str(ctx,
4877 live_range_tests[i].condition);
4878 validity = isl_union_map_read_from_str(ctx,
4879 live_range_tests[i].conditional_validity);
4880 sc = isl_schedule_constraints_on_domain(domain);
4881 sc = isl_schedule_constraints_set_validity(sc,
4882 isl_union_map_copy(flow));
4883 sc = isl_schedule_constraints_set_proximity(sc, flow);
4884 sc = isl_schedule_constraints_set_conditional_validity(sc,
4885 condition, validity);
4886 schedule = isl_schedule_constraints_compute_schedule(sc);
4887 node = isl_schedule_get_root(schedule);
4888 while (node &&
4889 isl_schedule_node_get_type(node) != isl_schedule_node_band)
4890 node = isl_schedule_node_first_child(node);
4891 n_member = isl_schedule_node_band_n_member(node);
4892 isl_schedule_node_free(node);
4893 isl_schedule_free(schedule);
4895 if (!schedule || n_member < 0)
4896 return -1;
4897 if (n_member != live_range_tests[i].outer_band_n)
4898 isl_die(ctx, isl_error_unknown,
4899 "unexpected number of members in outer band",
4900 return -1);
4902 return 0;
4905 /* Check that the schedule computed for the given instance set and
4906 * dependence relation strongly satisfies the dependences.
4907 * In particular, check that no instance is scheduled before
4908 * or together with an instance on which it depends.
4909 * Earlier versions of isl would produce a schedule that
4910 * only weakly satisfies the dependences.
4912 static int test_strongly_satisfying_schedule(isl_ctx *ctx)
4914 const char *domain, *dep;
4915 isl_union_map *D, *schedule;
4916 isl_map *map, *ge;
4917 int empty;
4919 domain = "{ B[i0, i1] : 0 <= i0 <= 1 and 0 <= i1 <= 11; "
4920 "A[i0] : 0 <= i0 <= 1 }";
4921 dep = "{ B[i0, i1] -> B[i0, 1 + i1] : 0 <= i0 <= 1 and 0 <= i1 <= 10; "
4922 "B[0, 11] -> A[1]; A[i0] -> B[i0, 0] : 0 <= i0 <= 1 }";
4923 schedule = compute_schedule(ctx, domain, dep, dep);
4924 D = isl_union_map_read_from_str(ctx, dep);
4925 D = isl_union_map_apply_domain(D, isl_union_map_copy(schedule));
4926 D = isl_union_map_apply_range(D, schedule);
4927 map = isl_map_from_union_map(D);
4928 ge = isl_map_lex_ge(isl_space_domain(isl_map_get_space(map)));
4929 map = isl_map_intersect(map, ge);
4930 empty = isl_map_is_empty(map);
4931 isl_map_free(map);
4933 if (empty < 0)
4934 return -1;
4935 if (!empty)
4936 isl_die(ctx, isl_error_unknown,
4937 "dependences not strongly satisfied", return -1);
4939 return 0;
4942 /* Compute a schedule for input where the instance set constraints
4943 * conflict with the context constraints.
4944 * Earlier versions of isl did not properly handle this situation.
4946 static int test_conflicting_context_schedule(isl_ctx *ctx)
4948 isl_union_map *schedule;
4949 const char *domain, *context;
4951 domain = "[n] -> { A[] : n >= 0 }";
4952 context = "[n] -> { : n < 0 }";
4953 schedule = compute_schedule_with_context(ctx,
4954 domain, "{}", "{}", context);
4955 isl_union_map_free(schedule);
4957 if (!schedule)
4958 return -1;
4960 return 0;
4963 /* Check that a set of schedule constraints that only allow for
4964 * a coalescing schedule still produces a schedule even if the user
4965 * request a non-coalescing schedule. Earlier versions of isl
4966 * would not handle this case correctly.
4968 static int test_coalescing_schedule(isl_ctx *ctx)
4970 const char *domain, *dep;
4971 isl_union_set *I;
4972 isl_union_map *D;
4973 isl_schedule_constraints *sc;
4974 isl_schedule *schedule;
4975 int treat_coalescing;
4977 domain = "{ S[a, b] : 0 <= a <= 1 and 0 <= b <= 1 }";
4978 dep = "{ S[a, b] -> S[a + b, 1 - b] }";
4979 I = isl_union_set_read_from_str(ctx, domain);
4980 D = isl_union_map_read_from_str(ctx, dep);
4981 sc = isl_schedule_constraints_on_domain(I);
4982 sc = isl_schedule_constraints_set_validity(sc, D);
4983 treat_coalescing = isl_options_get_schedule_treat_coalescing(ctx);
4984 isl_options_set_schedule_treat_coalescing(ctx, 1);
4985 schedule = isl_schedule_constraints_compute_schedule(sc);
4986 isl_options_set_schedule_treat_coalescing(ctx, treat_coalescing);
4987 isl_schedule_free(schedule);
4988 if (!schedule)
4989 return -1;
4990 return 0;
4993 /* Check that the scheduler does not perform any needless
4994 * compound skewing. Earlier versions of isl would compute
4995 * schedules in terms of transformed schedule coefficients and
4996 * would not accurately keep track of the sum of the original
4997 * schedule coefficients. It could then produce the schedule
4998 * S[t,i,j,k] -> [t, 2t + i, 2t + i + j, 2t + i + j + k]
4999 * for the input below instead of the schedule below.
5001 static int test_skewing_schedule(isl_ctx *ctx)
5003 const char *D, *V, *P, *S;
5005 D = "[n] -> { S[t,i,j,k] : 0 <= t,i,j,k < n }";
5006 V = "[n] -> { S[t,i,j,k] -> S[t+1,a,b,c] : 0 <= t,i,j,k,a,b,c < n and "
5007 "-2 <= a-i <= 2 and -1 <= a-i + b-j <= 1 and "
5008 "-1 <= a-i + b-j + c-k <= 1 }";
5009 P = "{ }";
5010 S = "{ S[t,i,j,k] -> [t, 2t + i, t + i + j, 2t + k] }";
5012 return test_special_schedule(ctx, D, V, P, S);
5015 int test_schedule(isl_ctx *ctx)
5017 const char *D, *W, *R, *V, *P, *S;
5018 int max_coincidence;
5019 int treat_coalescing;
5021 /* Handle resulting schedule with zero bands. */
5022 if (test_one_schedule(ctx, "{[]}", "{}", "{}", "{[] -> []}", 0, 0) < 0)
5023 return -1;
5025 /* Jacobi */
5026 D = "[T,N] -> { S1[t,i] : 1 <= t <= T and 2 <= i <= N - 1 }";
5027 W = "{ S1[t,i] -> a[t,i] }";
5028 R = "{ S1[t,i] -> a[t-1,i]; S1[t,i] -> a[t-1,i-1]; "
5029 "S1[t,i] -> a[t-1,i+1] }";
5030 S = "{ S1[t,i] -> [t,i] }";
5031 if (test_one_schedule(ctx, D, W, R, S, 2, 0) < 0)
5032 return -1;
5034 /* Fig. 5 of CC2008 */
5035 D = "[N] -> { S_0[i, j] : i >= 0 and i <= -1 + N and j >= 2 and "
5036 "j <= -1 + N }";
5037 W = "[N] -> { S_0[i, j] -> a[i, j] : i >= 0 and i <= -1 + N and "
5038 "j >= 2 and j <= -1 + N }";
5039 R = "[N] -> { S_0[i, j] -> a[j, i] : i >= 0 and i <= -1 + N and "
5040 "j >= 2 and j <= -1 + N; "
5041 "S_0[i, j] -> a[i, -1 + j] : i >= 0 and i <= -1 + N and "
5042 "j >= 2 and j <= -1 + N }";
5043 S = "[N] -> { S_0[i, j] -> [0, i, 0, j, 0] }";
5044 if (test_one_schedule(ctx, D, W, R, S, 2, 0) < 0)
5045 return -1;
5047 D = "{ S1[i] : 0 <= i <= 10; S2[i] : 0 <= i <= 9 }";
5048 W = "{ S1[i] -> a[i] }";
5049 R = "{ S2[i] -> a[i+1] }";
5050 S = "{ S1[i] -> [0,i]; S2[i] -> [1,i] }";
5051 if (test_one_schedule(ctx, D, W, R, S, 1, 1) < 0)
5052 return -1;
5054 D = "{ S1[i] : 0 <= i < 10; S2[i] : 0 <= i < 10 }";
5055 W = "{ S1[i] -> a[i] }";
5056 R = "{ S2[i] -> a[9-i] }";
5057 S = "{ S1[i] -> [0,i]; S2[i] -> [1,i] }";
5058 if (test_one_schedule(ctx, D, W, R, S, 1, 1) < 0)
5059 return -1;
5061 D = "[N] -> { S1[i] : 0 <= i < N; S2[i] : 0 <= i < N }";
5062 W = "{ S1[i] -> a[i] }";
5063 R = "[N] -> { S2[i] -> a[N-1-i] }";
5064 S = "{ S1[i] -> [0,i]; S2[i] -> [1,i] }";
5065 if (test_one_schedule(ctx, D, W, R, S, 1, 1) < 0)
5066 return -1;
5068 D = "{ S1[i] : 0 < i < 10; S2[i] : 0 <= i < 10 }";
5069 W = "{ S1[i] -> a[i]; S2[i] -> b[i] }";
5070 R = "{ S2[i] -> a[i]; S1[i] -> b[i-1] }";
5071 S = "{ S1[i] -> [i,0]; S2[i] -> [i,1] }";
5072 if (test_one_schedule(ctx, D, W, R, S, 0, 0) < 0)
5073 return -1;
5075 D = "[N] -> { S1[i] : 1 <= i <= N; S2[i,j] : 1 <= i,j <= N }";
5076 W = "{ S1[i] -> a[0,i]; S2[i,j] -> a[i,j] }";
5077 R = "{ S2[i,j] -> a[i-1,j] }";
5078 S = "{ S1[i] -> [0,i,0]; S2[i,j] -> [1,i,j] }";
5079 if (test_one_schedule(ctx, D, W, R, S, 2, 1) < 0)
5080 return -1;
5082 D = "[N] -> { S1[i] : 1 <= i <= N; S2[i,j] : 1 <= i,j <= N }";
5083 W = "{ S1[i] -> a[i,0]; S2[i,j] -> a[i,j] }";
5084 R = "{ S2[i,j] -> a[i,j-1] }";
5085 S = "{ S1[i] -> [0,i,0]; S2[i,j] -> [1,i,j] }";
5086 if (test_one_schedule(ctx, D, W, R, S, 2, 1) < 0)
5087 return -1;
5089 D = "[N] -> { S_0[]; S_1[i] : i >= 0 and i <= -1 + N; S_2[] }";
5090 W = "[N] -> { S_0[] -> a[0]; S_2[] -> b[0]; "
5091 "S_1[i] -> a[1 + i] : i >= 0 and i <= -1 + N }";
5092 R = "[N] -> { S_2[] -> a[N]; S_1[i] -> a[i] : i >= 0 and i <= -1 + N }";
5093 S = "[N] -> { S_1[i] -> [1, i, 0]; S_2[] -> [2, 0, 1]; "
5094 "S_0[] -> [0, 0, 0] }";
5095 if (test_one_schedule(ctx, D, W, R, S, 1, 0) < 0)
5096 return -1;
5097 ctx->opt->schedule_parametric = 0;
5098 if (test_one_schedule(ctx, D, W, R, S, 0, 0) < 0)
5099 return -1;
5100 ctx->opt->schedule_parametric = 1;
5102 D = "[N] -> { S1[i] : 1 <= i <= N; S2[i] : 1 <= i <= N; "
5103 "S3[i,j] : 1 <= i,j <= N; S4[i] : 1 <= i <= N }";
5104 W = "{ S1[i] -> a[i,0]; S2[i] -> a[0,i]; S3[i,j] -> a[i,j] }";
5105 R = "[N] -> { S3[i,j] -> a[i-1,j]; S3[i,j] -> a[i,j-1]; "
5106 "S4[i] -> a[i,N] }";
5107 S = "{ S1[i] -> [0,i,0]; S2[i] -> [1,i,0]; S3[i,j] -> [2,i,j]; "
5108 "S4[i] -> [4,i,0] }";
5109 max_coincidence = isl_options_get_schedule_maximize_coincidence(ctx);
5110 isl_options_set_schedule_maximize_coincidence(ctx, 0);
5111 if (test_one_schedule(ctx, D, W, R, S, 2, 0) < 0)
5112 return -1;
5113 isl_options_set_schedule_maximize_coincidence(ctx, max_coincidence);
5115 D = "[N] -> { S_0[i, j] : i >= 1 and i <= N and j >= 1 and j <= N }";
5116 W = "[N] -> { S_0[i, j] -> s[0] : i >= 1 and i <= N and j >= 1 and "
5117 "j <= N }";
5118 R = "[N] -> { S_0[i, j] -> s[0] : i >= 1 and i <= N and j >= 1 and "
5119 "j <= N; "
5120 "S_0[i, j] -> a[i, j] : i >= 1 and i <= N and j >= 1 and "
5121 "j <= N }";
5122 S = "[N] -> { S_0[i, j] -> [0, i, 0, j, 0] }";
5123 if (test_one_schedule(ctx, D, W, R, S, 0, 0) < 0)
5124 return -1;
5126 D = "[N] -> { S_0[t] : t >= 0 and t <= -1 + N; "
5127 " S_2[t] : t >= 0 and t <= -1 + N; "
5128 " S_1[t, i] : t >= 0 and t <= -1 + N and i >= 0 and "
5129 "i <= -1 + N }";
5130 W = "[N] -> { S_0[t] -> a[t, 0] : t >= 0 and t <= -1 + N; "
5131 " S_2[t] -> b[t] : t >= 0 and t <= -1 + N; "
5132 " S_1[t, i] -> a[t, 1 + i] : t >= 0 and t <= -1 + N and "
5133 "i >= 0 and i <= -1 + N }";
5134 R = "[N] -> { S_1[t, i] -> a[t, i] : t >= 0 and t <= -1 + N and "
5135 "i >= 0 and i <= -1 + N; "
5136 " S_2[t] -> a[t, N] : t >= 0 and t <= -1 + N }";
5137 S = "[N] -> { S_2[t] -> [0, t, 2]; S_1[t, i] -> [0, t, 1, i, 0]; "
5138 " S_0[t] -> [0, t, 0] }";
5140 if (test_one_schedule(ctx, D, W, R, S, 2, 1) < 0)
5141 return -1;
5142 ctx->opt->schedule_parametric = 0;
5143 if (test_one_schedule(ctx, D, W, R, S, 0, 0) < 0)
5144 return -1;
5145 ctx->opt->schedule_parametric = 1;
5147 D = "[N] -> { S1[i,j] : 0 <= i,j < N; S2[i,j] : 0 <= i,j < N }";
5148 S = "{ S1[i,j] -> [0,i,j]; S2[i,j] -> [1,i,j] }";
5149 if (test_one_schedule(ctx, D, "{}", "{}", S, 2, 2) < 0)
5150 return -1;
5152 D = "[M, N] -> { S_1[i] : i >= 0 and i <= -1 + M; "
5153 "S_0[i, j] : i >= 0 and i <= -1 + M and j >= 0 and j <= -1 + N }";
5154 W = "[M, N] -> { S_0[i, j] -> a[j] : i >= 0 and i <= -1 + M and "
5155 "j >= 0 and j <= -1 + N; "
5156 "S_1[i] -> b[0] : i >= 0 and i <= -1 + M }";
5157 R = "[M, N] -> { S_0[i, j] -> a[0] : i >= 0 and i <= -1 + M and "
5158 "j >= 0 and j <= -1 + N; "
5159 "S_1[i] -> b[0] : i >= 0 and i <= -1 + M }";
5160 S = "[M, N] -> { S_1[i] -> [1, i, 0]; S_0[i, j] -> [0, i, 0, j, 0] }";
5161 if (test_one_schedule(ctx, D, W, R, S, 0, 0) < 0)
5162 return -1;
5164 D = "{ S_0[i] : i >= 0 }";
5165 W = "{ S_0[i] -> a[i] : i >= 0 }";
5166 R = "{ S_0[i] -> a[0] : i >= 0 }";
5167 S = "{ S_0[i] -> [0, i, 0] }";
5168 if (test_one_schedule(ctx, D, W, R, S, 0, 0) < 0)
5169 return -1;
5171 D = "{ S_0[i] : i >= 0; S_1[i] : i >= 0 }";
5172 W = "{ S_0[i] -> a[i] : i >= 0; S_1[i] -> b[i] : i >= 0 }";
5173 R = "{ S_0[i] -> b[0] : i >= 0; S_1[i] -> a[i] : i >= 0 }";
5174 S = "{ S_1[i] -> [0, i, 1]; S_0[i] -> [0, i, 0] }";
5175 if (test_one_schedule(ctx, D, W, R, S, 0, 0) < 0)
5176 return -1;
5178 D = "[n] -> { S_0[j, k] : j <= -1 + n and j >= 0 and "
5179 "k <= -1 + n and k >= 0 }";
5180 W = "[n] -> { S_0[j, k] -> B[j] : j <= -1 + n and j >= 0 and " "k <= -1 + n and k >= 0 }";
5181 R = "[n] -> { S_0[j, k] -> B[j] : j <= -1 + n and j >= 0 and "
5182 "k <= -1 + n and k >= 0; "
5183 "S_0[j, k] -> B[k] : j <= -1 + n and j >= 0 and "
5184 "k <= -1 + n and k >= 0; "
5185 "S_0[j, k] -> A[k] : j <= -1 + n and j >= 0 and "
5186 "k <= -1 + n and k >= 0 }";
5187 S = "[n] -> { S_0[j, k] -> [2, j, k] }";
5188 ctx->opt->schedule_outer_coincidence = 1;
5189 if (test_one_schedule(ctx, D, W, R, S, 0, 0) < 0)
5190 return -1;
5191 ctx->opt->schedule_outer_coincidence = 0;
5193 D = "{Stmt_for_body24[i0, i1, i2, i3]:"
5194 "i0 >= 0 and i0 <= 1 and i1 >= 0 and i1 <= 6 and i2 >= 2 and "
5195 "i2 <= 6 - i1 and i3 >= 0 and i3 <= -1 + i2;"
5196 "Stmt_for_body24[i0, i1, 1, 0]:"
5197 "i0 >= 0 and i0 <= 1 and i1 >= 0 and i1 <= 5;"
5198 "Stmt_for_body7[i0, i1, i2]:"
5199 "i0 >= 0 and i0 <= 1 and i1 >= 0 and i1 <= 7 and i2 >= 0 and "
5200 "i2 <= 7 }";
5202 V = "{Stmt_for_body24[0, i1, i2, i3] -> "
5203 "Stmt_for_body24[1, i1, i2, i3]:"
5204 "i3 >= 0 and i3 <= -1 + i2 and i1 >= 0 and i2 <= 6 - i1 and "
5205 "i2 >= 1;"
5206 "Stmt_for_body24[0, i1, i2, i3] -> "
5207 "Stmt_for_body7[1, 1 + i1 + i3, 1 + i1 + i2]:"
5208 "i3 <= -1 + i2 and i2 <= 6 - i1 and i2 >= 1 and i1 >= 0 and "
5209 "i3 >= 0;"
5210 "Stmt_for_body24[0, i1, i2, i3] ->"
5211 "Stmt_for_body7[1, i1, 1 + i1 + i3]:"
5212 "i3 >= 0 and i2 <= 6 - i1 and i1 >= 0 and i3 <= -1 + i2;"
5213 "Stmt_for_body7[0, i1, i2] -> Stmt_for_body7[1, i1, i2]:"
5214 "(i2 >= 1 + i1 and i2 <= 6 and i1 >= 0 and i1 <= 4) or "
5215 "(i2 >= 3 and i2 <= 7 and i1 >= 1 and i2 >= 1 + i1) or "
5216 "(i2 >= 0 and i2 <= i1 and i2 >= -7 + i1 and i1 <= 7);"
5217 "Stmt_for_body7[0, i1, 1 + i1] -> Stmt_for_body7[1, i1, 1 + i1]:"
5218 "i1 <= 6 and i1 >= 0;"
5219 "Stmt_for_body7[0, 0, 7] -> Stmt_for_body7[1, 0, 7];"
5220 "Stmt_for_body7[i0, i1, i2] -> "
5221 "Stmt_for_body24[i0, o1, -1 + i2 - o1, -1 + i1 - o1]:"
5222 "i0 >= 0 and i0 <= 1 and o1 >= 0 and i2 >= 1 + i1 and "
5223 "o1 <= -2 + i2 and i2 <= 7 and o1 <= -1 + i1;"
5224 "Stmt_for_body7[i0, i1, i2] -> "
5225 "Stmt_for_body24[i0, i1, o2, -1 - i1 + i2]:"
5226 "i0 >= 0 and i0 <= 1 and i1 >= 0 and o2 >= -i1 + i2 and "
5227 "o2 >= 1 and o2 <= 6 - i1 and i2 >= 1 + i1 }";
5228 P = V;
5230 treat_coalescing = isl_options_get_schedule_treat_coalescing(ctx);
5231 isl_options_set_schedule_treat_coalescing(ctx, 0);
5232 if (test_has_schedule(ctx, D, V, P) < 0)
5233 return -1;
5234 isl_options_set_schedule_treat_coalescing(ctx, treat_coalescing);
5236 D = "{ S_0[i, j] : i >= 1 and i <= 10 and j >= 1 and j <= 8 }";
5237 V = "{ S_0[i, j] -> S_0[i, 1 + j] : i >= 1 and i <= 10 and "
5238 "j >= 1 and j <= 7;"
5239 "S_0[i, j] -> S_0[1 + i, j] : i >= 1 and i <= 9 and "
5240 "j >= 1 and j <= 8 }";
5241 P = "{ }";
5242 S = "{ S_0[i, j] -> [i + j, i] }";
5243 ctx->opt->schedule_algorithm = ISL_SCHEDULE_ALGORITHM_FEAUTRIER;
5244 if (test_special_schedule(ctx, D, V, P, S) < 0)
5245 return -1;
5246 ctx->opt->schedule_algorithm = ISL_SCHEDULE_ALGORITHM_ISL;
5248 /* Fig. 1 from Feautrier's "Some Efficient Solutions..." pt. 2, 1992 */
5249 D = "[N] -> { S_0[i, j] : i >= 0 and i <= -1 + N and "
5250 "j >= 0 and j <= -1 + i }";
5251 V = "[N] -> { S_0[i, j] -> S_0[i, 1 + j] : j <= -2 + i and "
5252 "i <= -1 + N and j >= 0;"
5253 "S_0[i, -1 + i] -> S_0[1 + i, 0] : i >= 1 and "
5254 "i <= -2 + N }";
5255 P = "{ }";
5256 S = "{ S_0[i, j] -> [i, j] }";
5257 ctx->opt->schedule_algorithm = ISL_SCHEDULE_ALGORITHM_FEAUTRIER;
5258 if (test_special_schedule(ctx, D, V, P, S) < 0)
5259 return -1;
5260 ctx->opt->schedule_algorithm = ISL_SCHEDULE_ALGORITHM_ISL;
5262 /* Test both algorithms on a case with only proximity dependences. */
5263 D = "{ S[i,j] : 0 <= i <= 10 }";
5264 V = "{ }";
5265 P = "{ S[i,j] -> S[i+1,j] : 0 <= i,j <= 10 }";
5266 S = "{ S[i, j] -> [j, i] }";
5267 ctx->opt->schedule_algorithm = ISL_SCHEDULE_ALGORITHM_FEAUTRIER;
5268 if (test_special_schedule(ctx, D, V, P, S) < 0)
5269 return -1;
5270 ctx->opt->schedule_algorithm = ISL_SCHEDULE_ALGORITHM_ISL;
5271 if (test_special_schedule(ctx, D, V, P, S) < 0)
5272 return -1;
5274 D = "{ A[a]; B[] }";
5275 V = "{}";
5276 P = "{ A[a] -> B[] }";
5277 if (test_has_schedule(ctx, D, V, P) < 0)
5278 return -1;
5280 if (test_padded_schedule(ctx) < 0)
5281 return -1;
5283 /* Check that check for progress is not confused by rational
5284 * solution.
5286 D = "[N] -> { S0[i, j] : i >= 0 and i <= N and j >= 0 and j <= N }";
5287 V = "[N] -> { S0[i0, -1 + N] -> S0[2 + i0, 0] : i0 >= 0 and "
5288 "i0 <= -2 + N; "
5289 "S0[i0, i1] -> S0[i0, 1 + i1] : i0 >= 0 and "
5290 "i0 <= N and i1 >= 0 and i1 <= -1 + N }";
5291 P = "{}";
5292 ctx->opt->schedule_algorithm = ISL_SCHEDULE_ALGORITHM_FEAUTRIER;
5293 if (test_has_schedule(ctx, D, V, P) < 0)
5294 return -1;
5295 ctx->opt->schedule_algorithm = ISL_SCHEDULE_ALGORITHM_ISL;
5297 /* Check that we allow schedule rows that are only non-trivial
5298 * on some full-dimensional domains.
5300 D = "{ S1[j] : 0 <= j <= 1; S0[]; S2[k] : 0 <= k <= 1 }";
5301 V = "{ S0[] -> S1[j] : 0 <= j <= 1; S2[0] -> S0[];"
5302 "S1[j] -> S2[1] : 0 <= j <= 1 }";
5303 P = "{}";
5304 ctx->opt->schedule_algorithm = ISL_SCHEDULE_ALGORITHM_FEAUTRIER;
5305 if (test_has_schedule(ctx, D, V, P) < 0)
5306 return -1;
5307 ctx->opt->schedule_algorithm = ISL_SCHEDULE_ALGORITHM_ISL;
5309 if (test_conditional_schedule_constraints(ctx) < 0)
5310 return -1;
5312 if (test_strongly_satisfying_schedule(ctx) < 0)
5313 return -1;
5315 if (test_conflicting_context_schedule(ctx) < 0)
5316 return -1;
5318 if (test_coalescing_schedule(ctx) < 0)
5319 return -1;
5320 if (test_skewing_schedule(ctx) < 0)
5321 return -1;
5323 return 0;
5326 /* Perform scheduling tests using the whole component scheduler.
5328 static int test_schedule_whole(isl_ctx *ctx)
5330 int whole;
5331 int r;
5333 whole = isl_options_get_schedule_whole_component(ctx);
5334 isl_options_set_schedule_whole_component(ctx, 1);
5335 r = test_schedule(ctx);
5336 isl_options_set_schedule_whole_component(ctx, whole);
5338 return r;
5341 /* Perform scheduling tests using the incremental scheduler.
5343 static int test_schedule_incremental(isl_ctx *ctx)
5345 int whole;
5346 int r;
5348 whole = isl_options_get_schedule_whole_component(ctx);
5349 isl_options_set_schedule_whole_component(ctx, 0);
5350 r = test_schedule(ctx);
5351 isl_options_set_schedule_whole_component(ctx, whole);
5353 return r;
5356 int test_plain_injective(isl_ctx *ctx, const char *str, int injective)
5358 isl_union_map *umap;
5359 int test;
5361 umap = isl_union_map_read_from_str(ctx, str);
5362 test = isl_union_map_plain_is_injective(umap);
5363 isl_union_map_free(umap);
5364 if (test < 0)
5365 return -1;
5366 if (test == injective)
5367 return 0;
5368 if (injective)
5369 isl_die(ctx, isl_error_unknown,
5370 "map not detected as injective", return -1);
5371 else
5372 isl_die(ctx, isl_error_unknown,
5373 "map detected as injective", return -1);
5376 int test_injective(isl_ctx *ctx)
5378 const char *str;
5380 if (test_plain_injective(ctx, "{S[i,j] -> A[0]; T[i,j] -> B[1]}", 0))
5381 return -1;
5382 if (test_plain_injective(ctx, "{S[] -> A[0]; T[] -> B[0]}", 1))
5383 return -1;
5384 if (test_plain_injective(ctx, "{S[] -> A[0]; T[] -> A[1]}", 1))
5385 return -1;
5386 if (test_plain_injective(ctx, "{S[] -> A[0]; T[] -> A[0]}", 0))
5387 return -1;
5388 if (test_plain_injective(ctx, "{S[i] -> A[i,0]; T[i] -> A[i,1]}", 1))
5389 return -1;
5390 if (test_plain_injective(ctx, "{S[i] -> A[i]; T[i] -> A[i]}", 0))
5391 return -1;
5392 if (test_plain_injective(ctx, "{S[] -> A[0,0]; T[] -> A[0,1]}", 1))
5393 return -1;
5394 if (test_plain_injective(ctx, "{S[] -> A[0,0]; T[] -> A[1,0]}", 1))
5395 return -1;
5397 str = "{S[] -> A[0,0]; T[] -> A[0,1]; U[] -> A[1,0]}";
5398 if (test_plain_injective(ctx, str, 1))
5399 return -1;
5400 str = "{S[] -> A[0,0]; T[] -> A[0,1]; U[] -> A[0,0]}";
5401 if (test_plain_injective(ctx, str, 0))
5402 return -1;
5404 return 0;
5407 #undef BASE
5408 #define BASE aff
5409 #include "isl_test_plain_equal_templ.c"
5411 #undef BASE
5412 #define BASE pw_multi_aff
5413 #include "isl_test_plain_equal_templ.c"
5415 #undef BASE
5416 #define BASE union_pw_aff
5417 #include "isl_test_plain_equal_templ.c"
5419 /* Basic tests on isl_union_pw_aff.
5421 * In particular, check that isl_union_pw_aff_aff_on_domain
5422 * aligns the parameters of the input objects and
5423 * that isl_union_pw_aff_param_on_domain_id properly
5424 * introduces the parameter.
5426 static int test_upa(isl_ctx *ctx)
5428 const char *str;
5429 isl_id *id;
5430 isl_aff *aff;
5431 isl_union_set *domain;
5432 isl_union_pw_aff *upa;
5433 isl_stat ok;
5435 aff = isl_aff_read_from_str(ctx, "[N] -> { [N] }");
5436 str = "[M] -> { A[i] : 0 <= i < M; B[] }";
5437 domain = isl_union_set_read_from_str(ctx, str);
5438 upa = isl_union_pw_aff_aff_on_domain(domain, aff);
5439 str = "[N, M] -> { A[i] -> [N] : 0 <= i < M; B[] -> [N] }";
5440 ok = union_pw_aff_check_plain_equal(upa, str);
5441 isl_union_pw_aff_free(upa);
5442 if (ok < 0)
5443 return -1;
5445 id = isl_id_alloc(ctx, "N", NULL);
5446 str = "[M] -> { A[i] : 0 <= i < M; B[] }";
5447 domain = isl_union_set_read_from_str(ctx, str);
5448 upa = isl_union_pw_aff_param_on_domain_id(domain, id);
5449 str = "[N, M] -> { A[i] -> [N] : 0 <= i < M; B[] -> [N] }";
5450 ok = union_pw_aff_check_plain_equal(upa, str);
5451 isl_union_pw_aff_free(upa);
5452 if (ok < 0)
5453 return -1;
5455 return 0;
5458 struct {
5459 __isl_give isl_aff *(*fn)(__isl_take isl_aff *aff1,
5460 __isl_take isl_aff *aff2);
5461 } aff_bin_op[] = {
5462 ['+'] = { &isl_aff_add },
5463 ['-'] = { &isl_aff_sub },
5464 ['*'] = { &isl_aff_mul },
5465 ['/'] = { &isl_aff_div },
5468 struct {
5469 const char *arg1;
5470 unsigned char op;
5471 const char *arg2;
5472 const char *res;
5473 } aff_bin_tests[] = {
5474 { "{ [i] -> [i] }", '+', "{ [i] -> [i] }",
5475 "{ [i] -> [2i] }" },
5476 { "{ [i] -> [i] }", '-', "{ [i] -> [i] }",
5477 "{ [i] -> [0] }" },
5478 { "{ [i] -> [i] }", '*', "{ [i] -> [2] }",
5479 "{ [i] -> [2i] }" },
5480 { "{ [i] -> [2] }", '*', "{ [i] -> [i] }",
5481 "{ [i] -> [2i] }" },
5482 { "{ [i] -> [i] }", '/', "{ [i] -> [2] }",
5483 "{ [i] -> [i/2] }" },
5484 { "{ [i] -> [2i] }", '/', "{ [i] -> [2] }",
5485 "{ [i] -> [i] }" },
5486 { "{ [i] -> [i] }", '+', "{ [i] -> [NaN] }",
5487 "{ [i] -> [NaN] }" },
5488 { "{ [i] -> [i] }", '-', "{ [i] -> [NaN] }",
5489 "{ [i] -> [NaN] }" },
5490 { "{ [i] -> [i] }", '*', "{ [i] -> [NaN] }",
5491 "{ [i] -> [NaN] }" },
5492 { "{ [i] -> [2] }", '*', "{ [i] -> [NaN] }",
5493 "{ [i] -> [NaN] }" },
5494 { "{ [i] -> [i] }", '/', "{ [i] -> [NaN] }",
5495 "{ [i] -> [NaN] }" },
5496 { "{ [i] -> [2] }", '/', "{ [i] -> [NaN] }",
5497 "{ [i] -> [NaN] }" },
5498 { "{ [i] -> [NaN] }", '+', "{ [i] -> [i] }",
5499 "{ [i] -> [NaN] }" },
5500 { "{ [i] -> [NaN] }", '-', "{ [i] -> [i] }",
5501 "{ [i] -> [NaN] }" },
5502 { "{ [i] -> [NaN] }", '*', "{ [i] -> [2] }",
5503 "{ [i] -> [NaN] }" },
5504 { "{ [i] -> [NaN] }", '*', "{ [i] -> [i] }",
5505 "{ [i] -> [NaN] }" },
5506 { "{ [i] -> [NaN] }", '/', "{ [i] -> [2] }",
5507 "{ [i] -> [NaN] }" },
5508 { "{ [i] -> [NaN] }", '/', "{ [i] -> [i] }",
5509 "{ [i] -> [NaN] }" },
5510 { "{ [i] -> [i] }", '/', "{ [i] -> [0] }",
5511 "{ [i] -> [NaN] }" },
5514 /* Perform some basic tests of binary operations on isl_aff objects.
5516 static int test_bin_aff(isl_ctx *ctx)
5518 int i;
5519 isl_aff *aff1, *aff2, *res;
5520 __isl_give isl_aff *(*fn)(__isl_take isl_aff *aff1,
5521 __isl_take isl_aff *aff2);
5522 int ok;
5524 for (i = 0; i < ARRAY_SIZE(aff_bin_tests); ++i) {
5525 aff1 = isl_aff_read_from_str(ctx, aff_bin_tests[i].arg1);
5526 aff2 = isl_aff_read_from_str(ctx, aff_bin_tests[i].arg2);
5527 res = isl_aff_read_from_str(ctx, aff_bin_tests[i].res);
5528 fn = aff_bin_op[aff_bin_tests[i].op].fn;
5529 aff1 = fn(aff1, aff2);
5530 if (isl_aff_is_nan(res))
5531 ok = isl_aff_is_nan(aff1);
5532 else
5533 ok = isl_aff_plain_is_equal(aff1, res);
5534 isl_aff_free(aff1);
5535 isl_aff_free(res);
5536 if (ok < 0)
5537 return -1;
5538 if (!ok)
5539 isl_die(ctx, isl_error_unknown,
5540 "unexpected result", return -1);
5543 return 0;
5546 struct {
5547 __isl_give isl_pw_aff *(*fn)(__isl_take isl_pw_aff *pa1,
5548 __isl_take isl_pw_aff *pa2);
5549 } pw_aff_bin_op[] = {
5550 ['m'] = { &isl_pw_aff_min },
5551 ['M'] = { &isl_pw_aff_max },
5554 /* Inputs for binary isl_pw_aff operation tests.
5555 * "arg1" and "arg2" are the two arguments, "op" identifies the operation
5556 * defined by pw_aff_bin_op, and "res" is the expected result.
5558 struct {
5559 const char *arg1;
5560 unsigned char op;
5561 const char *arg2;
5562 const char *res;
5563 } pw_aff_bin_tests[] = {
5564 { "{ [i] -> [i] }", 'm', "{ [i] -> [i] }",
5565 "{ [i] -> [i] }" },
5566 { "{ [i] -> [i] }", 'M', "{ [i] -> [i] }",
5567 "{ [i] -> [i] }" },
5568 { "{ [i] -> [i] }", 'm', "{ [i] -> [0] }",
5569 "{ [i] -> [i] : i <= 0; [i] -> [0] : i > 0 }" },
5570 { "{ [i] -> [i] }", 'M', "{ [i] -> [0] }",
5571 "{ [i] -> [i] : i >= 0; [i] -> [0] : i < 0 }" },
5572 { "{ [i] -> [i] }", 'm', "{ [i] -> [NaN] }",
5573 "{ [i] -> [NaN] }" },
5574 { "{ [i] -> [NaN] }", 'm', "{ [i] -> [i] }",
5575 "{ [i] -> [NaN] }" },
5578 /* Perform some basic tests of binary operations on isl_pw_aff objects.
5580 static int test_bin_pw_aff(isl_ctx *ctx)
5582 int i;
5583 isl_bool ok;
5584 isl_pw_aff *pa1, *pa2, *res;
5586 for (i = 0; i < ARRAY_SIZE(pw_aff_bin_tests); ++i) {
5587 pa1 = isl_pw_aff_read_from_str(ctx, pw_aff_bin_tests[i].arg1);
5588 pa2 = isl_pw_aff_read_from_str(ctx, pw_aff_bin_tests[i].arg2);
5589 res = isl_pw_aff_read_from_str(ctx, pw_aff_bin_tests[i].res);
5590 pa1 = pw_aff_bin_op[pw_aff_bin_tests[i].op].fn(pa1, pa2);
5591 if (isl_pw_aff_involves_nan(res))
5592 ok = isl_pw_aff_involves_nan(pa1);
5593 else
5594 ok = isl_pw_aff_plain_is_equal(pa1, res);
5595 isl_pw_aff_free(pa1);
5596 isl_pw_aff_free(res);
5597 if (ok < 0)
5598 return -1;
5599 if (!ok)
5600 isl_die(ctx, isl_error_unknown,
5601 "unexpected result", return -1);
5604 return 0;
5607 /* Inputs for basic tests of test operations on
5608 * isl_union_pw_multi_aff objects.
5609 * "fn" is the function that is being tested.
5610 * "arg" is a string description of the input.
5611 * "res" is the expected result.
5613 static struct {
5614 isl_bool (*fn)(__isl_keep isl_union_pw_multi_aff *upma1);
5615 const char *arg;
5616 isl_bool res;
5617 } upma_test_tests[] = {
5618 { &isl_union_pw_multi_aff_involves_nan, "{ A[] -> [0]; B[0] -> [1] }",
5619 isl_bool_false },
5620 { &isl_union_pw_multi_aff_involves_nan, "{ A[] -> [NaN]; B[0] -> [1] }",
5621 isl_bool_true },
5622 { &isl_union_pw_multi_aff_involves_nan, "{ A[] -> [0]; B[0] -> [NaN] }",
5623 isl_bool_true },
5624 { &isl_union_pw_multi_aff_involves_nan,
5625 "{ A[] -> [0]; B[0] -> [1, NaN, 5] }",
5626 isl_bool_true },
5627 { &isl_union_pw_multi_aff_involves_locals,
5628 "{ A[] -> [0]; B[0] -> [1] }",
5629 isl_bool_false },
5630 { &isl_union_pw_multi_aff_involves_locals,
5631 "{ A[] -> [0]; B[x] -> [1] : x mod 2 = 0 }",
5632 isl_bool_true },
5633 { &isl_union_pw_multi_aff_involves_locals,
5634 "{ A[] -> [0]; B[x] -> [x // 2] }",
5635 isl_bool_true },
5636 { &isl_union_pw_multi_aff_involves_locals,
5637 "{ A[i] -> [i // 2]; B[0] -> [1] }",
5638 isl_bool_true },
5641 /* Perform some basic tests of test operations on
5642 * isl_union_pw_multi_aff objects.
5644 static isl_stat test_upma_test(isl_ctx *ctx)
5646 int i;
5647 isl_union_pw_multi_aff *upma;
5648 isl_bool res;
5650 for (i = 0; i < ARRAY_SIZE(upma_test_tests); ++i) {
5651 const char *str;
5653 str = upma_test_tests[i].arg;
5654 upma = isl_union_pw_multi_aff_read_from_str(ctx, str);
5655 res = upma_test_tests[i].fn(upma);
5656 isl_union_pw_multi_aff_free(upma);
5657 if (res < 0)
5658 return isl_stat_error;
5659 if (res != upma_test_tests[i].res)
5660 isl_die(ctx, isl_error_unknown,
5661 "unexpected result", return isl_stat_error);
5664 return isl_stat_ok;
5667 struct {
5668 __isl_give isl_union_pw_multi_aff *(*fn)(
5669 __isl_take isl_union_pw_multi_aff *upma1,
5670 __isl_take isl_union_pw_multi_aff *upma2);
5671 const char *arg1;
5672 const char *arg2;
5673 const char *res;
5674 } upma_bin_tests[] = {
5675 { &isl_union_pw_multi_aff_add, "{ A[] -> [0]; B[0] -> [1] }",
5676 "{ B[x] -> [2] : x >= 0 }", "{ B[0] -> [3] }" },
5677 { &isl_union_pw_multi_aff_union_add, "{ A[] -> [0]; B[0] -> [1] }",
5678 "{ B[x] -> [2] : x >= 0 }",
5679 "{ A[] -> [0]; B[0] -> [3]; B[x] -> [2] : x >= 1 }" },
5680 { &isl_union_pw_multi_aff_pullback_union_pw_multi_aff,
5681 "{ A[] -> B[0]; C[x] -> B[1] : x < 10; C[y] -> B[2] : y >= 10 }",
5682 "{ D[i] -> A[] : i < 0; D[i] -> C[i + 5] : i >= 0 }",
5683 "{ D[i] -> B[0] : i < 0; D[i] -> B[1] : 0 <= i < 5; "
5684 "D[i] -> B[2] : i >= 5 }" },
5685 { &isl_union_pw_multi_aff_union_add, "{ B[x] -> A[1] : x <= 0 }",
5686 "{ B[x] -> C[2] : x > 0 }",
5687 "{ B[x] -> A[1] : x <= 0; B[x] -> C[2] : x > 0 }" },
5688 { &isl_union_pw_multi_aff_union_add, "{ B[x] -> A[1] : x <= 0 }",
5689 "{ B[x] -> A[2] : x >= 0 }",
5690 "{ B[x] -> A[1] : x < 0; B[x] -> A[2] : x > 0; B[0] -> A[3] }" },
5692 &isl_union_pw_multi_aff_preimage_domain_wrapped_domain_union_pw_multi_aff,
5693 "{ B[x] -> C[x + 2] }",
5694 "{ D[y] -> B[2y] }",
5695 "{ }" },
5697 &isl_union_pw_multi_aff_preimage_domain_wrapped_domain_union_pw_multi_aff,
5698 "{ [A[x] -> B[x + 1]] -> C[x + 2] }",
5699 "{ D[y] -> B[2y] }",
5700 "{ }" },
5702 &isl_union_pw_multi_aff_preimage_domain_wrapped_domain_union_pw_multi_aff,
5703 "{ [A[x] -> B[x + 1]] -> C[x + 2]; B[x] -> C[x + 2] }",
5704 "{ D[y] -> A[2y] }",
5705 "{ [D[y] -> B[2y + 1]] -> C[2y + 2] }" },
5707 &isl_union_pw_multi_aff_preimage_domain_wrapped_domain_union_pw_multi_aff,
5708 "{ T[A[x] -> B[x + 1]] -> C[x + 2]; B[x] -> C[x + 2] }",
5709 "{ D[y] -> A[2y] }",
5710 "{ T[D[y] -> B[2y + 1]] -> C[2y + 2] }" },
5713 /* Perform some basic tests of binary operations on
5714 * isl_union_pw_multi_aff objects.
5716 static int test_bin_upma(isl_ctx *ctx)
5718 int i;
5719 isl_union_pw_multi_aff *upma1, *upma2, *res;
5720 int ok;
5722 for (i = 0; i < ARRAY_SIZE(upma_bin_tests); ++i) {
5723 upma1 = isl_union_pw_multi_aff_read_from_str(ctx,
5724 upma_bin_tests[i].arg1);
5725 upma2 = isl_union_pw_multi_aff_read_from_str(ctx,
5726 upma_bin_tests[i].arg2);
5727 res = isl_union_pw_multi_aff_read_from_str(ctx,
5728 upma_bin_tests[i].res);
5729 upma1 = upma_bin_tests[i].fn(upma1, upma2);
5730 ok = isl_union_pw_multi_aff_plain_is_equal(upma1, res);
5731 isl_union_pw_multi_aff_free(upma1);
5732 isl_union_pw_multi_aff_free(res);
5733 if (ok < 0)
5734 return -1;
5735 if (!ok)
5736 isl_die(ctx, isl_error_unknown,
5737 "unexpected result", return -1);
5740 return 0;
5743 struct {
5744 __isl_give isl_union_pw_multi_aff *(*fn)(
5745 __isl_take isl_union_pw_multi_aff *upma1,
5746 __isl_take isl_union_pw_multi_aff *upma2);
5747 const char *arg1;
5748 const char *arg2;
5749 } upma_bin_fail_tests[] = {
5750 { &isl_union_pw_multi_aff_union_add, "{ B[x] -> A[1] : x <= 0 }",
5751 "{ B[x] -> C[2] : x >= 0 }" },
5754 /* Perform some basic tests of binary operations on
5755 * isl_union_pw_multi_aff objects that are expected to fail.
5757 static int test_bin_upma_fail(isl_ctx *ctx)
5759 int i, n;
5760 isl_union_pw_multi_aff *upma1, *upma2;
5761 int on_error;
5763 on_error = isl_options_get_on_error(ctx);
5764 isl_options_set_on_error(ctx, ISL_ON_ERROR_CONTINUE);
5765 n = ARRAY_SIZE(upma_bin_fail_tests);
5766 for (i = 0; i < n; ++i) {
5767 upma1 = isl_union_pw_multi_aff_read_from_str(ctx,
5768 upma_bin_fail_tests[i].arg1);
5769 upma2 = isl_union_pw_multi_aff_read_from_str(ctx,
5770 upma_bin_fail_tests[i].arg2);
5771 upma1 = upma_bin_fail_tests[i].fn(upma1, upma2);
5772 isl_union_pw_multi_aff_free(upma1);
5773 if (upma1)
5774 break;
5776 isl_options_set_on_error(ctx, on_error);
5777 if (i < n)
5778 isl_die(ctx, isl_error_unknown,
5779 "operation not expected to succeed", return -1);
5781 return 0;
5784 /* Inputs for basic tests of binary operations on
5785 * pairs of isl_union_pw_multi_aff and isl_union_set objects.
5786 * "fn" is the function that is being tested.
5787 * "arg1" and "arg2" are string descriptions of the inputs.
5788 * "res" is a string description of the expected result.
5790 struct {
5791 __isl_give isl_union_pw_multi_aff *(*fn)(
5792 __isl_take isl_union_pw_multi_aff *upma,
5793 __isl_take isl_union_set *uset);
5794 const char *arg1;
5795 const char *arg2;
5796 const char *res;
5797 } upma_uset_tests[] = {
5798 { &isl_union_pw_multi_aff_intersect_domain_wrapped_range,
5799 "{ A[i] -> B[i] }", "{ B[0] }",
5800 "{ }" },
5801 { &isl_union_pw_multi_aff_intersect_domain_wrapped_domain,
5802 "{ [A[i] -> B[i]] -> C[i + 1] }", "{ A[1]; B[0] }",
5803 "{ [A[1] -> B[1]] -> C[2] }" },
5804 { &isl_union_pw_multi_aff_intersect_domain_wrapped_range,
5805 "{ [A[i] -> B[i]] -> C[i + 1] }", "{ A[1]; B[0] }",
5806 "{ [A[0] -> B[0]] -> C[1] }" },
5807 { &isl_union_pw_multi_aff_intersect_domain_wrapped_range,
5808 "{ [A[i] -> B[i]] -> C[i + 1] }", "[N] -> { B[N] }",
5809 "[N] -> { [A[N] -> B[N]] -> C[N + 1] }" },
5810 { &isl_union_pw_multi_aff_intersect_domain_wrapped_range,
5811 "[M] -> { [A[M] -> B[M]] -> C[M + 1] }", "[N] -> { B[N] }",
5812 "[N, M] -> { [A[N] -> B[N]] -> C[N + 1] : N = M }" },
5813 { &isl_union_pw_multi_aff_intersect_domain_wrapped_range,
5814 "{ [A[] -> B[]] -> C[]; N[A[] -> B[]] -> D[]; [B[] -> A[]] -> E[] }",
5815 "{ B[] }",
5816 "{ [A[] -> B[]] -> C[]; N[A[] -> B[]] -> D[] }" },
5819 /* Perform some basic tests of binary operations on
5820 * pairs of isl_union_pw_multi_aff and isl_union_set objects.
5822 static isl_stat test_upma_uset(isl_ctx *ctx)
5824 int i;
5825 isl_bool ok;
5826 isl_union_pw_multi_aff *upma, *res;
5827 isl_union_set *uset;
5829 for (i = 0; i < ARRAY_SIZE(upma_uset_tests); ++i) {
5830 upma = isl_union_pw_multi_aff_read_from_str(ctx,
5831 upma_uset_tests[i].arg1);
5832 uset = isl_union_set_read_from_str(ctx,
5833 upma_uset_tests[i].arg2);
5834 res = isl_union_pw_multi_aff_read_from_str(ctx,
5835 upma_uset_tests[i].res);
5836 upma = upma_uset_tests[i].fn(upma, uset);
5837 ok = isl_union_pw_multi_aff_plain_is_equal(upma, res);
5838 isl_union_pw_multi_aff_free(upma);
5839 isl_union_pw_multi_aff_free(res);
5840 if (ok < 0)
5841 return isl_stat_error;
5842 if (!ok)
5843 isl_die(ctx, isl_error_unknown,
5844 "unexpected result", return isl_stat_error);
5847 return isl_stat_ok;
5850 /* Inputs for basic tests of unary operations on isl_multi_pw_aff objects.
5851 * "fn" is the function that is tested.
5852 * "arg" is a string description of the input.
5853 * "res" is a string description of the expected result.
5855 struct {
5856 __isl_give isl_multi_pw_aff *(*fn)(__isl_take isl_multi_pw_aff *mpa);
5857 const char *arg;
5858 const char *res;
5859 } mpa_un_tests[] = {
5860 { &isl_multi_pw_aff_range_factor_domain,
5861 "{ A[x] -> [B[(1 : x >= 5)] -> C[(2 : x <= 10)]] }",
5862 "{ A[x] -> B[(1 : x >= 5)] }" },
5863 { &isl_multi_pw_aff_range_factor_range,
5864 "{ A[x] -> [B[(1 : x >= 5)] -> C[(2 : x <= 10)]] }",
5865 "{ A[y] -> C[(2 : y <= 10)] }" },
5866 { &isl_multi_pw_aff_range_factor_domain,
5867 "{ A[x] -> [B[(1 : x >= 5)] -> C[]] }",
5868 "{ A[x] -> B[(1 : x >= 5)] }" },
5869 { &isl_multi_pw_aff_range_factor_range,
5870 "{ A[x] -> [B[(1 : x >= 5)] -> C[]] }",
5871 "{ A[y] -> C[] }" },
5872 { &isl_multi_pw_aff_range_factor_domain,
5873 "{ A[x] -> [B[] -> C[(2 : x <= 10)]] }",
5874 "{ A[x] -> B[] }" },
5875 { &isl_multi_pw_aff_range_factor_range,
5876 "{ A[x] -> [B[] -> C[(2 : x <= 10)]] }",
5877 "{ A[y] -> C[(2 : y <= 10)] }" },
5878 { &isl_multi_pw_aff_range_factor_domain,
5879 "{ A[x] -> [B[] -> C[]] }",
5880 "{ A[x] -> B[] }" },
5881 { &isl_multi_pw_aff_range_factor_range,
5882 "{ A[x] -> [B[] -> C[]] }",
5883 "{ A[y] -> C[] }" },
5884 { &isl_multi_pw_aff_factor_range,
5885 "{ [B[] -> C[]] }",
5886 "{ C[] }" },
5887 { &isl_multi_pw_aff_range_factor_domain,
5888 "{ A[x] -> [B[] -> C[]] : x >= 0 }",
5889 "{ A[x] -> B[] : x >= 0 }" },
5890 { &isl_multi_pw_aff_range_factor_range,
5891 "{ A[x] -> [B[] -> C[]] : x >= 0 }",
5892 "{ A[y] -> C[] : y >= 0 }" },
5893 { &isl_multi_pw_aff_factor_range,
5894 "[N] -> { [B[] -> C[]] : N >= 0 }",
5895 "[N] -> { C[] : N >= 0 }" },
5898 /* Perform some basic tests of unary operations on isl_multi_pw_aff objects.
5900 static int test_un_mpa(isl_ctx *ctx)
5902 int i;
5903 isl_bool ok;
5904 isl_multi_pw_aff *mpa, *res;
5906 for (i = 0; i < ARRAY_SIZE(mpa_un_tests); ++i) {
5907 mpa = isl_multi_pw_aff_read_from_str(ctx, mpa_un_tests[i].arg);
5908 res = isl_multi_pw_aff_read_from_str(ctx, mpa_un_tests[i].res);
5909 mpa = mpa_un_tests[i].fn(mpa);
5910 ok = isl_multi_pw_aff_plain_is_equal(mpa, res);
5911 isl_multi_pw_aff_free(mpa);
5912 isl_multi_pw_aff_free(res);
5913 if (ok < 0)
5914 return -1;
5915 if (!ok)
5916 isl_die(ctx, isl_error_unknown,
5917 "unexpected result", return -1);
5920 return 0;
5923 /* Inputs for basic tests of binary operations on isl_multi_pw_aff objects.
5924 * "fn" is the function that is tested.
5925 * "arg1" and "arg2" are string descriptions of the inputs.
5926 * "res" is a string description of the expected result.
5928 struct {
5929 __isl_give isl_multi_pw_aff *(*fn)(
5930 __isl_take isl_multi_pw_aff *mpa1,
5931 __isl_take isl_multi_pw_aff *mpa2);
5932 const char *arg1;
5933 const char *arg2;
5934 const char *res;
5935 } mpa_bin_tests[] = {
5936 { &isl_multi_pw_aff_add, "{ A[] -> [1] }", "{ A[] -> [2] }",
5937 "{ A[] -> [3] }" },
5938 { &isl_multi_pw_aff_add, "{ A[x] -> [(1 : x >= 5)] }",
5939 "{ A[x] -> [(x : x <= 10)] }",
5940 "{ A[x] -> [(1 + x : 5 <= x <= 10)] }" },
5941 { &isl_multi_pw_aff_add, "{ A[x] -> [] : x >= 5 }",
5942 "{ A[x] -> [] : x <= 10 }",
5943 "{ A[x] -> [] : 5 <= x <= 10 }" },
5944 { &isl_multi_pw_aff_add, "{ A[x] -> [] : x >= 5 }",
5945 "[N] -> { A[x] -> [] : x <= N }",
5946 "[N] -> { A[x] -> [] : 5 <= x <= N }" },
5947 { &isl_multi_pw_aff_add,
5948 "[N] -> { A[x] -> [] : x <= N }",
5949 "{ A[x] -> [] : x >= 5 }",
5950 "[N] -> { A[x] -> [] : 5 <= x <= N }" },
5951 { &isl_multi_pw_aff_range_product, "{ A[x] -> B[(1 : x >= 5)] }",
5952 "{ A[y] -> C[(2 : y <= 10)] }",
5953 "{ A[x] -> [B[(1 : x >= 5)] -> C[(2 : x <= 10)]] }" },
5954 { &isl_multi_pw_aff_range_product, "{ A[x] -> B[1] : x >= 5 }",
5955 "{ A[y] -> C[2] : y <= 10 }",
5956 "{ A[x] -> [B[(1 : x >= 5)] -> C[(2 : x <= 10)]] }" },
5957 { &isl_multi_pw_aff_range_product, "{ A[x] -> B[1] : x >= 5 }",
5958 "[N] -> { A[y] -> C[2] : y <= N }",
5959 "[N] -> { A[x] -> [B[(1 : x >= 5)] -> C[(2 : x <= N)]] }" },
5960 { &isl_multi_pw_aff_range_product, "[N] -> { A[x] -> B[1] : x >= N }",
5961 "{ A[y] -> C[2] : y <= 10 }",
5962 "[N] -> { A[x] -> [B[(1 : x >= N)] -> C[(2 : x <= 10)]] }" },
5963 { &isl_multi_pw_aff_range_product, "{ A[] -> B[1] }", "{ A[] -> C[2] }",
5964 "{ A[] -> [B[1] -> C[2]] }" },
5965 { &isl_multi_pw_aff_range_product, "{ A[] -> B[] }", "{ A[] -> C[] }",
5966 "{ A[] -> [B[] -> C[]] }" },
5967 { &isl_multi_pw_aff_range_product, "{ A[x] -> B[(1 : x >= 5)] }",
5968 "{ A[y] -> C[] : y <= 10 }",
5969 "{ A[x] -> [B[(1 : x >= 5)] -> C[]] : x <= 10 }" },
5970 { &isl_multi_pw_aff_range_product, "{ A[y] -> C[] : y <= 10 }",
5971 "{ A[x] -> B[(1 : x >= 5)] }",
5972 "{ A[x] -> [C[] -> B[(1 : x >= 5)]] : x <= 10 }" },
5973 { &isl_multi_pw_aff_product, "{ A[x] -> B[(1 : x >= 5)] }",
5974 "{ A[y] -> C[(2 : y <= 10)] }",
5975 "{ [A[x] -> A[y]] -> [B[(1 : x >= 5)] -> C[(2 : y <= 10)]] }" },
5976 { &isl_multi_pw_aff_product, "{ A[x] -> B[(1 : x >= 5)] }",
5977 "{ A[y] -> C[] : y <= 10 }",
5978 "{ [A[x] -> A[y]] -> [B[(1 : x >= 5)] -> C[]] : y <= 10 }" },
5979 { &isl_multi_pw_aff_product, "{ A[y] -> C[] : y <= 10 }",
5980 "{ A[x] -> B[(1 : x >= 5)] }",
5981 "{ [A[y] -> A[x]] -> [C[] -> B[(1 : x >= 5)]] : y <= 10 }" },
5982 { &isl_multi_pw_aff_product, "{ A[x] -> B[(1 : x >= 5)] }",
5983 "[N] -> { A[y] -> C[] : y <= N }",
5984 "[N] -> { [A[x] -> A[y]] -> [B[(1 : x >= 5)] -> C[]] : y <= N }" },
5985 { &isl_multi_pw_aff_product, "[N] -> { A[y] -> C[] : y <= N }",
5986 "{ A[x] -> B[(1 : x >= 5)] }",
5987 "[N] -> { [A[y] -> A[x]] -> [C[] -> B[(1 : x >= 5)]] : y <= N }" },
5988 { &isl_multi_pw_aff_product, "{ A[x] -> B[] : x >= 5 }",
5989 "{ A[y] -> C[] : y <= 10 }",
5990 "{ [A[x] -> A[y]] -> [B[] -> C[]] : x >= 5 and y <= 10 }" },
5991 { &isl_multi_pw_aff_product, "{ A[] -> B[1] }", "{ A[] -> C[2] }",
5992 "{ [A[] -> A[]] -> [B[1] -> C[2]] }" },
5993 { &isl_multi_pw_aff_product, "{ A[] -> B[] }", "{ A[] -> C[] }",
5994 "{ [A[] -> A[]] -> [B[] -> C[]] }" },
5995 { &isl_multi_pw_aff_pullback_multi_pw_aff,
5996 "{ B[i,j] -> C[i + 2j] }", "{ A[a,b] -> B[b,a] }",
5997 "{ A[a,b] -> C[b + 2a] }" },
5998 { &isl_multi_pw_aff_pullback_multi_pw_aff,
5999 "{ B[i,j] -> C[i + 2j] }",
6000 "{ A[a,b] -> B[(b : b > a),(a : b > a)] }",
6001 "{ A[a,b] -> C[(b + 2a : b > a)] }" },
6002 { &isl_multi_pw_aff_pullback_multi_pw_aff,
6003 "{ B[i,j] -> C[(i + 2j : j > 4)] }",
6004 "{ A[a,b] -> B[(b : b > a),(a : b > a)] }",
6005 "{ A[a,b] -> C[(b + 2a : b > a > 4)] }" },
6006 { &isl_multi_pw_aff_pullback_multi_pw_aff,
6007 "{ B[i,j] -> C[] }",
6008 "{ A[a,b] -> B[(b : b > a),(a : b > a)] }",
6009 "{ A[a,b] -> C[] }" },
6010 { &isl_multi_pw_aff_pullback_multi_pw_aff,
6011 "{ B[i,j] -> C[] : i > j }",
6012 "{ A[a,b] -> B[b,a] }",
6013 "{ A[a,b] -> C[] : b > a }" },
6014 { &isl_multi_pw_aff_pullback_multi_pw_aff,
6015 "{ B[i,j] -> C[] : j > 5 }",
6016 "{ A[a,b] -> B[(b : b > a),(a : b > a)] }",
6017 "{ A[a,b] -> C[] : b > a > 5 }" },
6018 { &isl_multi_pw_aff_pullback_multi_pw_aff,
6019 "[N] -> { B[i,j] -> C[] : j > N }",
6020 "{ A[a,b] -> B[(b : b > a),(a : b > a)] }",
6021 "[N] -> { A[a,b] -> C[] : b > a > N }" },
6022 { &isl_multi_pw_aff_pullback_multi_pw_aff,
6023 "[M,N] -> { B[] -> C[] : N > 5 }",
6024 "[M,N] -> { A[] -> B[] : M > N }",
6025 "[M,N] -> { A[] -> C[] : M > N > 5 }" },
6028 /* Perform some basic tests of binary operations on isl_multi_pw_aff objects.
6030 static int test_bin_mpa(isl_ctx *ctx)
6032 int i;
6033 isl_bool ok;
6034 isl_multi_pw_aff *mpa1, *mpa2, *res;
6036 for (i = 0; i < ARRAY_SIZE(mpa_bin_tests); ++i) {
6037 mpa1 = isl_multi_pw_aff_read_from_str(ctx,
6038 mpa_bin_tests[i].arg1);
6039 mpa2 = isl_multi_pw_aff_read_from_str(ctx,
6040 mpa_bin_tests[i].arg2);
6041 res = isl_multi_pw_aff_read_from_str(ctx,
6042 mpa_bin_tests[i].res);
6043 mpa1 = mpa_bin_tests[i].fn(mpa1, mpa2);
6044 ok = isl_multi_pw_aff_plain_is_equal(mpa1, res);
6045 isl_multi_pw_aff_free(mpa1);
6046 isl_multi_pw_aff_free(res);
6047 if (ok < 0)
6048 return -1;
6049 if (!ok)
6050 isl_die(ctx, isl_error_unknown,
6051 "unexpected result", return -1);
6054 return 0;
6057 /* Inputs for basic tests of unary operations on
6058 * isl_multi_union_pw_aff objects.
6059 * "fn" is the function that is tested.
6060 * "arg" is a string description of the input.
6061 * "res" is a string description of the expected result.
6063 struct {
6064 __isl_give isl_multi_union_pw_aff *(*fn)(
6065 __isl_take isl_multi_union_pw_aff *mupa);
6066 const char *arg;
6067 const char *res;
6068 } mupa_un_tests[] = {
6069 { &isl_multi_union_pw_aff_factor_range,
6070 "[B[{ A[] -> [1] }] -> C[{ A[] -> [2] }]]",
6071 "C[{ A[] -> [2] }]" },
6072 { &isl_multi_union_pw_aff_factor_range,
6073 "[B[] -> C[{ A[] -> [2] }]]",
6074 "C[{ A[] -> [2] }]" },
6075 { &isl_multi_union_pw_aff_factor_range,
6076 "[B[{ A[] -> [1] }] -> C[]]",
6077 "C[]" },
6078 { &isl_multi_union_pw_aff_factor_range,
6079 "[B[] -> C[]]",
6080 "C[]" },
6081 { &isl_multi_union_pw_aff_factor_range,
6082 "([B[] -> C[]] : { A[x] : x >= 0 })",
6083 "(C[] : { A[x] : x >= 0 })" },
6084 { &isl_multi_union_pw_aff_factor_range,
6085 "[N] -> ([B[] -> C[]] : { A[x] : x <= N })",
6086 "[N] -> (C[] : { A[x] : x <= N })" },
6087 { &isl_multi_union_pw_aff_factor_range,
6088 "[N] -> ([B[] -> C[]] : { : N >= 0 })",
6089 "[N] -> (C[] : { : N >= 0 })" },
6092 /* Perform some basic tests of unary operations on
6093 * isl_multi_union_pw_aff objects.
6095 static int test_un_mupa(isl_ctx *ctx)
6097 int i;
6098 isl_bool ok;
6099 isl_multi_union_pw_aff *mupa, *res;
6101 for (i = 0; i < ARRAY_SIZE(mupa_un_tests); ++i) {
6102 mupa = isl_multi_union_pw_aff_read_from_str(ctx,
6103 mupa_un_tests[i].arg);
6104 res = isl_multi_union_pw_aff_read_from_str(ctx,
6105 mupa_un_tests[i].res);
6106 mupa = mupa_un_tests[i].fn(mupa);
6107 ok = isl_multi_union_pw_aff_plain_is_equal(mupa, res);
6108 isl_multi_union_pw_aff_free(mupa);
6109 isl_multi_union_pw_aff_free(res);
6110 if (ok < 0)
6111 return -1;
6112 if (!ok)
6113 isl_die(ctx, isl_error_unknown,
6114 "unexpected result", return -1);
6117 return 0;
6120 /* Inputs for basic tests of binary operations on
6121 * isl_multi_union_pw_aff objects.
6122 * "fn" is the function that is tested.
6123 * "arg1" and "arg2" are string descriptions of the inputs.
6124 * "res" is a string description of the expected result.
6126 struct {
6127 __isl_give isl_multi_union_pw_aff *(*fn)(
6128 __isl_take isl_multi_union_pw_aff *mupa1,
6129 __isl_take isl_multi_union_pw_aff *mupa2);
6130 const char *arg1;
6131 const char *arg2;
6132 const char *res;
6133 } mupa_bin_tests[] = {
6134 { &isl_multi_union_pw_aff_add, "[{ A[] -> [1] }]", "[{ A[] -> [2] }]",
6135 "[{ A[] -> [3] }]" },
6136 { &isl_multi_union_pw_aff_sub, "[{ A[] -> [1] }]", "[{ A[] -> [2] }]",
6137 "[{ A[] -> [-1] }]" },
6138 { &isl_multi_union_pw_aff_add,
6139 "[{ A[] -> [1]; B[] -> [4] }]",
6140 "[{ A[] -> [2]; C[] -> [5] }]",
6141 "[{ A[] -> [3] }]" },
6142 { &isl_multi_union_pw_aff_union_add,
6143 "[{ A[] -> [1]; B[] -> [4] }]",
6144 "[{ A[] -> [2]; C[] -> [5] }]",
6145 "[{ A[] -> [3]; B[] -> [4]; C[] -> [5] }]" },
6146 { &isl_multi_union_pw_aff_add, "[{ A[x] -> [(1)] : x >= 5 }]",
6147 "[{ A[x] -> [(x)] : x <= 10 }]",
6148 "[{ A[x] -> [(1 + x)] : 5 <= x <= 10 }]" },
6149 { &isl_multi_union_pw_aff_add, "([] : { A[x] : x >= 5 })",
6150 "([] : { A[x] : x <= 10 })",
6151 "([] : { A[x] : 5 <= x <= 10 })" },
6152 { &isl_multi_union_pw_aff_add, "([] : { A[x] : x >= 5 })",
6153 "[N] -> ([] : { A[x] : x <= N })",
6154 "[N] -> ([] : { A[x] : 5 <= x <= N })" },
6155 { &isl_multi_union_pw_aff_add, "[N] -> ([] : { A[x] : x >= N })",
6156 "([] : { A[x] : x <= 10 })",
6157 "[N] -> ([] : { A[x] : N <= x <= 10 })" },
6158 { &isl_multi_union_pw_aff_union_add, "[{ A[x] -> [(1)] : x >= 5 }]",
6159 "[{ A[x] -> [(x)] : x <= 10 }]",
6160 "[{ A[x] -> [(1 + x)] : 5 <= x <= 10; "
6161 "A[x] -> [(1)] : x > 10; A[x] -> [(x)] : x < 5 }]" },
6162 { &isl_multi_union_pw_aff_union_add, "([] : { A[x] : x >= 5 })",
6163 "([] : { A[x] : x <= 10 })",
6164 "([] : { A[x] })" },
6165 { &isl_multi_union_pw_aff_union_add, "([] : { A[x] : x >= 0 })",
6166 "[N] -> ([] : { A[x] : x >= N })",
6167 "[N] -> ([] : { A[x] : x >= 0 or x >= N })" },
6168 { &isl_multi_union_pw_aff_union_add,
6169 "[N] -> ([] : { A[] : N >= 0})",
6170 "[N] -> ([] : { A[] : N <= 0})",
6171 "[N] -> ([] : { A[] })" },
6172 { &isl_multi_union_pw_aff_union_add,
6173 "[N] -> ([] : { A[] })",
6174 "[N] -> ([] : { : })",
6175 "[N] -> ([] : { : })" },
6176 { &isl_multi_union_pw_aff_union_add,
6177 "[N] -> ([] : { : })",
6178 "[N] -> ([] : { A[] })",
6179 "[N] -> ([] : { : })" },
6180 { &isl_multi_union_pw_aff_union_add,
6181 "[N] -> ([] : { : N >= 0})",
6182 "[N] -> ([] : { : N <= 0})",
6183 "[N] -> ([] : { : })" },
6184 { &isl_multi_union_pw_aff_range_product,
6185 "B[{ A[] -> [1] }]",
6186 "C[{ A[] -> [2] }]",
6187 "[B[{ A[] -> [1] }] -> C[{ A[] -> [2] }]]" },
6188 { &isl_multi_union_pw_aff_range_product,
6189 "(B[] : { A[x] : x >= 5 })",
6190 "(C[] : { A[x] : x <= 10 })",
6191 "([B[] -> C[]] : { A[x] : 5 <= x <= 10 })" },
6192 { &isl_multi_union_pw_aff_range_product,
6193 "B[{ A[x] -> [x + 1] : x >= 5 }]",
6194 "(C[] : { A[x] : x <= 10 })",
6195 "[B[{ A[x] -> [x + 1] : 5 <= x <= 10 }] -> C[]]" },
6196 { &isl_multi_union_pw_aff_range_product,
6197 "(C[] : { A[x] : x <= 10 })",
6198 "B[{ A[x] -> [x + 1] : x >= 5 }]",
6199 "[C[] -> B[{ A[x] -> [x + 1] : 5 <= x <= 10 }]]" },
6200 { &isl_multi_union_pw_aff_range_product,
6201 "B[{ A[x] -> [x + 1] : x >= 5 }]",
6202 "[N] -> (C[] : { A[x] : x <= N })",
6203 "[N] -> [B[{ A[x] -> [x + 1] : 5 <= x <= N }] -> C[]]" },
6204 { &isl_multi_union_pw_aff_range_product,
6205 "[N] -> (C[] : { A[x] : x <= N })",
6206 "B[{ A[x] -> [x + 1] : x >= 5 }]",
6207 "[N] -> [C[] -> B[{ A[x] -> [x + 1] : 5 <= x <= N }]]" },
6208 { &isl_multi_union_pw_aff_range_product,
6209 "B[{ A[] -> [1]; D[] -> [3] }]",
6210 "C[{ A[] -> [2] }]",
6211 "[B[{ A[] -> [1]; D[] -> [3] }] -> C[{ A[] -> [2] }]]" },
6212 { &isl_multi_union_pw_aff_range_product,
6213 "B[] }]",
6214 "(C[] : { A[x] })",
6215 "([B[] -> C[]] : { A[x] })" },
6216 { &isl_multi_union_pw_aff_range_product,
6217 "(B[] : { A[x] })",
6218 "C[] }]",
6219 "([B[] -> C[]] : { A[x] })" },
6222 /* Perform some basic tests of binary operations on
6223 * isl_multi_union_pw_aff objects.
6225 static int test_bin_mupa(isl_ctx *ctx)
6227 int i;
6228 isl_bool ok;
6229 isl_multi_union_pw_aff *mupa1, *mupa2, *res;
6231 for (i = 0; i < ARRAY_SIZE(mupa_bin_tests); ++i) {
6232 mupa1 = isl_multi_union_pw_aff_read_from_str(ctx,
6233 mupa_bin_tests[i].arg1);
6234 mupa2 = isl_multi_union_pw_aff_read_from_str(ctx,
6235 mupa_bin_tests[i].arg2);
6236 res = isl_multi_union_pw_aff_read_from_str(ctx,
6237 mupa_bin_tests[i].res);
6238 mupa1 = mupa_bin_tests[i].fn(mupa1, mupa2);
6239 ok = isl_multi_union_pw_aff_plain_is_equal(mupa1, res);
6240 isl_multi_union_pw_aff_free(mupa1);
6241 isl_multi_union_pw_aff_free(res);
6242 if (ok < 0)
6243 return -1;
6244 if (!ok)
6245 isl_die(ctx, isl_error_unknown,
6246 "unexpected result", return -1);
6249 return 0;
6252 /* Inputs for basic tests of binary operations on
6253 * pairs of isl_multi_union_pw_aff and isl_set objects.
6254 * "fn" is the function that is tested.
6255 * "arg1" and "arg2" are string descriptions of the inputs.
6256 * "res" is a string description of the expected result.
6258 struct {
6259 __isl_give isl_multi_union_pw_aff *(*fn)(
6260 __isl_take isl_multi_union_pw_aff *mupa,
6261 __isl_take isl_set *set);
6262 const char *arg1;
6263 const char *arg2;
6264 const char *res;
6265 } mupa_set_tests[] = {
6266 { &isl_multi_union_pw_aff_intersect_range,
6267 "C[{ B[i,j] -> [i + 2j] }]", "{ C[1] }",
6268 "C[{ B[i,j] -> [i + 2j] : i + 2j = 1 }]" },
6269 { &isl_multi_union_pw_aff_intersect_range,
6270 "C[{ B[i,j] -> [i + 2j] }]", "[N] -> { C[N] }",
6271 "[N] -> C[{ B[i,j] -> [i + 2j] : i + 2j = N }]" },
6272 { &isl_multi_union_pw_aff_intersect_range,
6273 "[N] -> C[{ B[i,j] -> [i + 2j + N] }]", "{ C[1] }",
6274 "[N] -> C[{ B[i,j] -> [i + 2j + N] : i + 2j + N = 1 }]" },
6275 { &isl_multi_union_pw_aff_intersect_range,
6276 "C[{ B[i,j] -> [i + 2j] }]", "[N] -> { C[x] : N >= 0 }",
6277 "[N] -> C[{ B[i,j] -> [i + 2j] : N >= 0 }]" },
6278 { &isl_multi_union_pw_aff_intersect_range,
6279 "C[]", "{ C[] }", "C[]" },
6280 { &isl_multi_union_pw_aff_intersect_range,
6281 "[N] -> (C[] : { : N >= 0 })",
6282 "{ C[] }",
6283 "[N] -> (C[] : { : N >= 0 })" },
6284 { &isl_multi_union_pw_aff_intersect_range,
6285 "(C[] : { A[a,b] })",
6286 "{ C[] }",
6287 "(C[] : { A[a,b] })" },
6288 { &isl_multi_union_pw_aff_intersect_range,
6289 "[N] -> (C[] : { A[a,b] : a,b <= N })",
6290 "{ C[] }",
6291 "[N] -> (C[] : { A[a,b] : a,b <= N })" },
6292 { &isl_multi_union_pw_aff_intersect_range,
6293 "C[]",
6294 "[N] -> { C[] : N >= 0 }",
6295 "[N] -> (C[] : { : N >= 0 })" },
6296 { &isl_multi_union_pw_aff_intersect_range,
6297 "(C[] : { A[a,b] })",
6298 "[N] -> { C[] : N >= 0 }",
6299 "[N] -> (C[] : { A[a,b] : N >= 0 })" },
6300 { &isl_multi_union_pw_aff_intersect_range,
6301 "[N] -> (C[] : { : N >= 0 })",
6302 "[N] -> { C[] : N < 1024 }",
6303 "[N] -> (C[] : { : 0 <= N < 1024 })" },
6304 { &isl_multi_union_pw_aff_intersect_params,
6305 "C[{ B[i,j] -> [i + 2j] }]", "[N] -> { : N >= 0 }",
6306 "[N] -> C[{ B[i,j] -> [i + 2j] : N >= 0}]" },
6307 { &isl_multi_union_pw_aff_intersect_params,
6308 "[N] -> C[{ B[i,j] -> [i + 2j] : N <= 256 }]", "[N] -> { : N >= 0 }",
6309 "[N] -> C[{ B[i,j] -> [i + 2j] : 0 <= N <= 256 }]" },
6310 { &isl_multi_union_pw_aff_intersect_params,
6311 "[N] -> C[{ B[i,j] -> [i + 2j] : N <= 256 }]", "{ : }",
6312 "[N] -> C[{ B[i,j] -> [i + 2j] : N <= 256 }]" },
6313 { &isl_multi_union_pw_aff_intersect_params,
6314 "C[]", "[N] -> { : N >= 0 }",
6315 "[N] -> (C[] : { : N >= 0 })" },
6316 { &isl_multi_union_pw_aff_intersect_params,
6317 "(C[] : { A[a,b] })", "[N] -> { : N >= 0 }",
6318 "[N] -> (C[] : { A[a,b] : N >= 0 })" },
6319 { &isl_multi_union_pw_aff_intersect_params,
6320 "[N] -> (C[] : { A[a,N] })", "{ : }",
6321 "[N] -> (C[] : { A[a,N] })" },
6322 { &isl_multi_union_pw_aff_intersect_params,
6323 "[N] -> (C[] : { A[a,b] : N <= 256 })", "[N] -> { : N >= 0 }",
6324 "[N] -> (C[] : { A[a,b] : 0 <= N <= 256 })" },
6327 /* Perform some basic tests of binary operations on
6328 * pairs of isl_multi_union_pw_aff and isl_set objects.
6330 static int test_mupa_set(isl_ctx *ctx)
6332 int i;
6333 isl_bool ok;
6334 isl_multi_union_pw_aff *mupa, *res;
6335 isl_set *set;
6337 for (i = 0; i < ARRAY_SIZE(mupa_set_tests); ++i) {
6338 mupa = isl_multi_union_pw_aff_read_from_str(ctx,
6339 mupa_set_tests[i].arg1);
6340 set = isl_set_read_from_str(ctx, mupa_set_tests[i].arg2);
6341 res = isl_multi_union_pw_aff_read_from_str(ctx,
6342 mupa_set_tests[i].res);
6343 mupa = mupa_set_tests[i].fn(mupa, set);
6344 ok = isl_multi_union_pw_aff_plain_is_equal(mupa, res);
6345 isl_multi_union_pw_aff_free(mupa);
6346 isl_multi_union_pw_aff_free(res);
6347 if (ok < 0)
6348 return -1;
6349 if (!ok)
6350 isl_die(ctx, isl_error_unknown,
6351 "unexpected result", return -1);
6354 return 0;
6357 /* Inputs for basic tests of binary operations on
6358 * pairs of isl_multi_union_pw_aff and isl_union_set objects.
6359 * "fn" is the function that is tested.
6360 * "arg1" and "arg2" are string descriptions of the inputs.
6361 * "res" is a string description of the expected result.
6363 struct {
6364 __isl_give isl_multi_union_pw_aff *(*fn)(
6365 __isl_take isl_multi_union_pw_aff *mupa,
6366 __isl_take isl_union_set *uset);
6367 const char *arg1;
6368 const char *arg2;
6369 const char *res;
6370 } mupa_uset_tests[] = {
6371 { &isl_multi_union_pw_aff_intersect_domain,
6372 "C[{ B[i,j] -> [i + 2j] }]", "{ B[i,i] }",
6373 "C[{ B[i,i] -> [3i] }]" },
6374 { &isl_multi_union_pw_aff_intersect_domain,
6375 "(C[] : { B[i,j] })", "{ B[i,i] }",
6376 "(C[] : { B[i,i] })" },
6377 { &isl_multi_union_pw_aff_intersect_domain,
6378 "(C[] : { B[i,j] })", "[N] -> { B[N,N] }",
6379 "[N] -> (C[] : { B[N,N] })" },
6380 { &isl_multi_union_pw_aff_intersect_domain,
6381 "C[]", "{ B[i,i] }",
6382 "(C[] : { B[i,i] })" },
6383 { &isl_multi_union_pw_aff_intersect_domain,
6384 "[N] -> (C[] : { : N >= 0 })", "{ B[i,i] }",
6385 "[N] -> (C[] : { B[i,i] : N >= 0 })" },
6388 /* Perform some basic tests of binary operations on
6389 * pairs of isl_multi_union_pw_aff and isl_union_set objects.
6391 static int test_mupa_uset(isl_ctx *ctx)
6393 int i;
6394 isl_bool ok;
6395 isl_multi_union_pw_aff *mupa, *res;
6396 isl_union_set *uset;
6398 for (i = 0; i < ARRAY_SIZE(mupa_uset_tests); ++i) {
6399 mupa = isl_multi_union_pw_aff_read_from_str(ctx,
6400 mupa_uset_tests[i].arg1);
6401 uset = isl_union_set_read_from_str(ctx,
6402 mupa_uset_tests[i].arg2);
6403 res = isl_multi_union_pw_aff_read_from_str(ctx,
6404 mupa_uset_tests[i].res);
6405 mupa = mupa_uset_tests[i].fn(mupa, uset);
6406 ok = isl_multi_union_pw_aff_plain_is_equal(mupa, res);
6407 isl_multi_union_pw_aff_free(mupa);
6408 isl_multi_union_pw_aff_free(res);
6409 if (ok < 0)
6410 return -1;
6411 if (!ok)
6412 isl_die(ctx, isl_error_unknown,
6413 "unexpected result", return -1);
6416 return 0;
6419 /* Inputs for basic tests of binary operations on
6420 * pairs of isl_multi_union_pw_aff and isl_multi_aff objects.
6421 * "fn" is the function that is tested.
6422 * "arg1" and "arg2" are string descriptions of the inputs.
6423 * "res" is a string description of the expected result.
6425 struct {
6426 __isl_give isl_multi_union_pw_aff *(*fn)(
6427 __isl_take isl_multi_union_pw_aff *mupa,
6428 __isl_take isl_multi_aff *ma);
6429 const char *arg1;
6430 const char *arg2;
6431 const char *res;
6432 } mupa_ma_tests[] = {
6433 { &isl_multi_union_pw_aff_apply_multi_aff,
6434 "C[{ A[i,j] -> [i]; B[i,j] -> [j] }, "
6435 "{ A[i,j] -> [j]; B[i,j] -> [i] }]",
6436 "{ C[a,b] -> D[b,a] }",
6437 "D[{ A[i,j] -> [j]; B[i,j] -> [i] }, "
6438 "{ A[i,j] -> [i]; B[i,j] -> [j] }]" },
6439 { &isl_multi_union_pw_aff_apply_multi_aff,
6440 "C[{ A[i,j] -> [i] : i >= 0; B[i,j] -> [j] }, "
6441 "{ A[i,j] -> [j]; B[i,j] -> [i] }]",
6442 "{ C[a,b] -> D[b,a] }",
6443 "D[{ A[i,j] -> [j] : i >= 0; B[i,j] -> [i] }, "
6444 "{ A[i,j] -> [i] : i >= 0; B[i,j] -> [j] }]" },
6445 { &isl_multi_union_pw_aff_apply_multi_aff,
6446 "C[{ A[i,j] -> [i]; B[i,j] -> [j] }]",
6447 "[N] -> { C[a] -> D[a + N] }",
6448 "[N] -> D[{ A[i,j] -> [i + N]; B[i,j] -> [j + N] }] " },
6449 { &isl_multi_union_pw_aff_apply_multi_aff,
6450 "C[]",
6451 "{ C[] -> D[] }",
6452 "D[]" },
6453 { &isl_multi_union_pw_aff_apply_multi_aff,
6454 "[N] -> (C[] : { : N >= 0 })",
6455 "{ C[] -> D[] }",
6456 "[N] -> (D[] : { : N >= 0 })" },
6457 { &isl_multi_union_pw_aff_apply_multi_aff,
6458 "C[]",
6459 "[N] -> { C[] -> D[N] }",
6460 "[N] -> D[{ [N] }]" },
6461 { &isl_multi_union_pw_aff_apply_multi_aff,
6462 "(C[] : { A[i,j] : i >= j })",
6463 "{ C[] -> D[] }",
6464 "(D[] : { A[i,j] : i >= j })" },
6465 { &isl_multi_union_pw_aff_apply_multi_aff,
6466 "[N] -> (C[] : { A[i,j] : N >= 0 })",
6467 "{ C[] -> D[] }",
6468 "[N] -> (D[] : { A[i,j] : N >= 0 })" },
6469 { &isl_multi_union_pw_aff_apply_multi_aff,
6470 "(C[] : { A[i,j] : i >= j })",
6471 "[N] -> { C[] -> D[N] }",
6472 "[N] -> (D[{ A[i,j] -> [N] : i >= j }])" },
6475 /* Perform some basic tests of binary operations on
6476 * pairs of isl_multi_union_pw_aff and isl_multi_aff objects.
6478 static int test_mupa_ma(isl_ctx *ctx)
6480 int i;
6481 isl_bool ok;
6482 isl_multi_union_pw_aff *mupa, *res;
6483 isl_multi_aff *ma;
6485 for (i = 0; i < ARRAY_SIZE(mupa_ma_tests); ++i) {
6486 mupa = isl_multi_union_pw_aff_read_from_str(ctx,
6487 mupa_ma_tests[i].arg1);
6488 ma = isl_multi_aff_read_from_str(ctx, mupa_ma_tests[i].arg2);
6489 res = isl_multi_union_pw_aff_read_from_str(ctx,
6490 mupa_ma_tests[i].res);
6491 mupa = mupa_ma_tests[i].fn(mupa, ma);
6492 ok = isl_multi_union_pw_aff_plain_is_equal(mupa, res);
6493 isl_multi_union_pw_aff_free(mupa);
6494 isl_multi_union_pw_aff_free(res);
6495 if (ok < 0)
6496 return -1;
6497 if (!ok)
6498 isl_die(ctx, isl_error_unknown,
6499 "unexpected result", return -1);
6502 return 0;
6505 /* Inputs for basic tests of binary operations on
6506 * pairs of isl_multi_union_pw_aff and isl_pw_aff objects.
6507 * "fn" is the function that is tested.
6508 * "arg1" and "arg2" are string descriptions of the inputs.
6509 * "res" is a string description of the expected result.
6511 struct {
6512 __isl_give isl_union_pw_aff *(*fn)(
6513 __isl_take isl_multi_union_pw_aff *mupa,
6514 __isl_take isl_pw_aff *pa);
6515 const char *arg1;
6516 const char *arg2;
6517 const char *res;
6518 } mupa_pa_tests[] = {
6519 { &isl_multi_union_pw_aff_apply_pw_aff,
6520 "C[{ A[i,j] -> [i]; B[i,j] -> [j] }]",
6521 "[N] -> { C[a] -> [a + N] }",
6522 "[N] -> { A[i,j] -> [i + N]; B[i,j] -> [j + N] }" },
6523 { &isl_multi_union_pw_aff_apply_pw_aff,
6524 "C[{ A[i,j] -> [i]; B[i,j] -> [j] }]",
6525 "{ C[a] -> [a] : a >= 0; C[a] -> [-a] : a < 0 }",
6526 "{ A[i,j] -> [i] : i >= 0; A[i,j] -> [-i] : i < 0; "
6527 "B[i,j] -> [j] : j >= 0; B[i,j] -> [-j] : j < 0 }" },
6528 { &isl_multi_union_pw_aff_apply_pw_aff,
6529 "C[]",
6530 "[N] -> { C[] -> [N] }",
6531 "[N] -> { [N] }" },
6532 { &isl_multi_union_pw_aff_apply_pw_aff,
6533 "C[]",
6534 "[N] -> { C[] -> [N] : N >= 0; C[] -> [-N] : N < 0 }",
6535 "[N] -> { [N] : N >= 0; [-N] : N < 0 }" },
6536 { &isl_multi_union_pw_aff_apply_pw_aff,
6537 "[N] -> (C[] : { : N >= 0 })",
6538 "[N] -> { C[] -> [N] }",
6539 "[N] -> { [N] : N >= 0 }" },
6540 { &isl_multi_union_pw_aff_apply_pw_aff,
6541 "[N] -> (C[] : { : N >= 0 })",
6542 "[N] -> { C[] -> [N] : N >= 0; C[] -> [-N] : N < 0 }",
6543 "[N] -> { [N] : N >= 0 }" },
6544 { &isl_multi_union_pw_aff_apply_pw_aff,
6545 "[N] -> (C[] : { : N >= 0 })",
6546 "{ C[] -> [0] }",
6547 "[N] -> { [0] : N >= 0 }" },
6548 { &isl_multi_union_pw_aff_apply_pw_aff,
6549 "(C[] : { A[i,j] : i >= j })",
6550 "[N] -> { C[] -> [N] }",
6551 "[N] -> { A[i,j] -> [N] : i >= j }" },
6552 { &isl_multi_union_pw_aff_apply_pw_aff,
6553 "(C[] : { A[i,j] : i >= j })",
6554 "[N] -> { C[] -> [N] : N >= 0 }",
6555 "[N] -> { A[i,j] -> [N] : i >= j and N >= 0 }" },
6558 /* Perform some basic tests of binary operations on
6559 * pairs of isl_multi_union_pw_aff and isl_pw_aff objects.
6561 static int test_mupa_pa(isl_ctx *ctx)
6563 int i;
6564 isl_bool ok;
6565 isl_multi_union_pw_aff *mupa;
6566 isl_union_pw_aff *upa, *res;
6567 isl_pw_aff *pa;
6569 for (i = 0; i < ARRAY_SIZE(mupa_pa_tests); ++i) {
6570 mupa = isl_multi_union_pw_aff_read_from_str(ctx,
6571 mupa_pa_tests[i].arg1);
6572 pa = isl_pw_aff_read_from_str(ctx, mupa_pa_tests[i].arg2);
6573 res = isl_union_pw_aff_read_from_str(ctx,
6574 mupa_pa_tests[i].res);
6575 upa = mupa_pa_tests[i].fn(mupa, pa);
6576 ok = isl_union_pw_aff_plain_is_equal(upa, res);
6577 isl_union_pw_aff_free(upa);
6578 isl_union_pw_aff_free(res);
6579 if (ok < 0)
6580 return -1;
6581 if (!ok)
6582 isl_die(ctx, isl_error_unknown,
6583 "unexpected result", return -1);
6586 return 0;
6589 /* Inputs for basic tests of binary operations on
6590 * pairs of isl_multi_union_pw_aff and isl_pw_multi_aff objects.
6591 * "fn" is the function that is tested.
6592 * "arg1" and "arg2" are string descriptions of the inputs.
6593 * "res" is a string description of the expected result.
6595 struct {
6596 __isl_give isl_multi_union_pw_aff *(*fn)(
6597 __isl_take isl_multi_union_pw_aff *mupa,
6598 __isl_take isl_pw_multi_aff *pma);
6599 const char *arg1;
6600 const char *arg2;
6601 const char *res;
6602 } mupa_pma_tests[] = {
6603 { &isl_multi_union_pw_aff_apply_pw_multi_aff,
6604 "C[{ A[i,j] -> [i]; B[i,j] -> [j] }, "
6605 "{ A[i,j] -> [j]; B[i,j] -> [i] }]",
6606 "{ C[a,b] -> D[b,a] }",
6607 "D[{ A[i,j] -> [j]; B[i,j] -> [i] }, "
6608 "{ A[i,j] -> [i]; B[i,j] -> [j] }]" },
6609 { &isl_multi_union_pw_aff_apply_pw_multi_aff,
6610 "C[{ A[i,j] -> [i] : i >= 0; B[i,j] -> [j] }, "
6611 "{ A[i,j] -> [j]; B[i,j] -> [i] }]",
6612 "{ C[a,b] -> D[b,a] }",
6613 "D[{ A[i,j] -> [j] : i >= 0; B[i,j] -> [i] }, "
6614 "{ A[i,j] -> [i] : i >= 0; B[i,j] -> [j] }]" },
6615 { &isl_multi_union_pw_aff_apply_pw_multi_aff,
6616 "C[{ A[i,j] -> [i]; B[i,j] -> [j] }]",
6617 "[N] -> { C[a] -> D[a + N] }",
6618 "[N] -> D[{ A[i,j] -> [i + N]; B[i,j] -> [j + N] }]" },
6619 { &isl_multi_union_pw_aff_apply_pw_multi_aff,
6620 "C[{ A[i,j] -> [i]; B[i,j] -> [j] }]",
6621 "{ C[a] -> D[a] : a >= 0; C[a] -> D[-a] : a < 0 }",
6622 "D[{ A[i,j] -> [i] : i >= 0; A[i,j] -> [-i] : i < 0; "
6623 "B[i,j] -> [j] : j >= 0; B[i,j] -> [-j] : j < 0 }]" },
6624 { &isl_multi_union_pw_aff_apply_pw_multi_aff,
6625 "C[{ A[i,j] -> [i]; B[i,j] -> [j] }, "
6626 "{ A[i,j] -> [j]; B[i,j] -> [i] }]",
6627 "{ C[a,b] -> D[a,b] : a >= b; C[a,b] -> D[b,a] : a < b }",
6628 "D[{ A[i,j] -> [i] : i >= j; A[i,j] -> [j] : i < j; "
6629 "B[i,j] -> [j] : i <= j; B[i,j] -> [i] : i > j }, "
6630 "{ A[i,j] -> [j] : i >= j; A[i,j] -> [i] : i < j; "
6631 "B[i,j] -> [i] : i <= j; B[i,j] -> [j] : i > j }]" },
6632 { &isl_multi_union_pw_aff_apply_pw_multi_aff,
6633 "C[]",
6634 "{ C[] -> D[] }",
6635 "D[]" },
6636 { &isl_multi_union_pw_aff_apply_pw_multi_aff,
6637 "[N] -> (C[] : { : N >= 0 })",
6638 "{ C[] -> D[] }",
6639 "[N] -> (D[] : { : N >= 0 })" },
6640 { &isl_multi_union_pw_aff_apply_pw_multi_aff,
6641 "C[]",
6642 "[N] -> { C[] -> D[N] }",
6643 "[N] -> D[{ [N] }]" },
6644 { &isl_multi_union_pw_aff_apply_pw_multi_aff,
6645 "(C[] : { A[i,j] : i >= j })",
6646 "{ C[] -> D[] }",
6647 "(D[] : { A[i,j] : i >= j })" },
6648 { &isl_multi_union_pw_aff_apply_pw_multi_aff,
6649 "[N] -> (C[] : { A[i,j] : N >= 0 })",
6650 "{ C[] -> D[] }",
6651 "[N] -> (D[] : { A[i,j] : N >= 0 })" },
6652 { &isl_multi_union_pw_aff_apply_pw_multi_aff,
6653 "(C[] : { A[i,j] : i >= j })",
6654 "[N] -> { C[] -> D[N] }",
6655 "[N] -> (D[{ A[i,j] -> [N] : i >= j }])" },
6656 { &isl_multi_union_pw_aff_apply_pw_multi_aff,
6657 "C[]",
6658 "[N] -> { C[] -> D[N] : N >= 0; C[] -> D[-N] : N < 0 }",
6659 "[N] -> D[{ [N] : N >= 0; [-N] : N < 0 }]" },
6660 { &isl_multi_union_pw_aff_apply_pw_multi_aff,
6661 "[N] -> (C[] : { : N >= 0 })",
6662 "[N] -> { C[] -> D[N] }",
6663 "[N] -> D[{ [N] : N >= 0 }]" },
6664 { &isl_multi_union_pw_aff_apply_pw_multi_aff,
6665 "[N] -> (C[] : { : N >= 0 })",
6666 "[N] -> { C[] -> D[N] : N >= 0; C[] -> D[-N] : N < 0 }",
6667 "[N] -> D[{ [N] : N >= 0 }]" },
6668 { &isl_multi_union_pw_aff_apply_pw_multi_aff,
6669 "[N] -> (C[] : { : N >= 0 })",
6670 "{ C[] -> D[0] }",
6671 "[N] -> D[{ [0] : N >= 0 }]" },
6672 { &isl_multi_union_pw_aff_apply_pw_multi_aff,
6673 "(C[] : { A[i,j] : i >= j })",
6674 "[N] -> { C[] -> D[N] : N >= 0 }",
6675 "[N] -> D[{ A[i,j] -> [N] : i >= j and N >= 0 }]" },
6678 /* Perform some basic tests of binary operations on
6679 * pairs of isl_multi_union_pw_aff and isl_pw_multi_aff objects.
6681 static int test_mupa_pma(isl_ctx *ctx)
6683 int i;
6684 isl_bool ok;
6685 isl_multi_union_pw_aff *mupa, *res;
6686 isl_pw_multi_aff *pma;
6688 for (i = 0; i < ARRAY_SIZE(mupa_pma_tests); ++i) {
6689 mupa = isl_multi_union_pw_aff_read_from_str(ctx,
6690 mupa_pma_tests[i].arg1);
6691 pma = isl_pw_multi_aff_read_from_str(ctx,
6692 mupa_pma_tests[i].arg2);
6693 res = isl_multi_union_pw_aff_read_from_str(ctx,
6694 mupa_pma_tests[i].res);
6695 mupa = mupa_pma_tests[i].fn(mupa, pma);
6696 ok = isl_multi_union_pw_aff_plain_is_equal(mupa, res);
6697 isl_multi_union_pw_aff_free(mupa);
6698 isl_multi_union_pw_aff_free(res);
6699 if (ok < 0)
6700 return -1;
6701 if (!ok)
6702 isl_die(ctx, isl_error_unknown,
6703 "unexpected result", return -1);
6706 return 0;
6709 /* Inputs for basic tests of binary operations on
6710 * pairs of isl_multi_union_pw_aff and isl_union_pw_multi_aff objects.
6711 * "fn" is the function that is tested.
6712 * "arg1" and "arg2" are string descriptions of the inputs.
6713 * "res" is a string description of the expected result.
6715 struct {
6716 __isl_give isl_multi_union_pw_aff *(*fn)(
6717 __isl_take isl_multi_union_pw_aff *mupa,
6718 __isl_take isl_union_pw_multi_aff *upma);
6719 const char *arg1;
6720 const char *arg2;
6721 const char *res;
6722 } mupa_upma_tests[] = {
6723 { &isl_multi_union_pw_aff_pullback_union_pw_multi_aff,
6724 "C[{ B[i,j] -> [i + 2j] }]", "{ A[a,b] -> B[b,a] }",
6725 "C[{ A[a,b] -> [b + 2a] }]" },
6726 { &isl_multi_union_pw_aff_pullback_union_pw_multi_aff,
6727 "C[{ B[i,j] -> [i + 2j] }]",
6728 "{ A[a,b] -> B[b,a] : b > a }",
6729 "C[{ A[a,b] -> [b + 2a] : b > a }]" },
6730 { &isl_multi_union_pw_aff_pullback_union_pw_multi_aff,
6731 "C[{ B[i,j] -> [i + 2j] : j > 4 }]",
6732 "{ A[a,b] -> B[b,a] : b > a }",
6733 "C[{ A[a,b] -> [b + 2a] : b > a > 4 }]" },
6734 { &isl_multi_union_pw_aff_pullback_union_pw_multi_aff,
6735 "C[{ B[i,j] -> [i + 2j] }]",
6736 "{ A[a,b] -> B[b,a] : a > b; A[a,b] -> B[a,b] : a <= b }",
6737 "C[{ A[a,b] -> [b + 2a] : a > b; A[a,b] -> [a + 2b] : a <= b }]" },
6738 { &isl_multi_union_pw_aff_pullback_union_pw_multi_aff,
6739 "(C[] : { B[a,b] })",
6740 "{ A[a,b] -> B[b,a] }",
6741 "(C[] : { A[a,b] })" },
6742 { &isl_multi_union_pw_aff_pullback_union_pw_multi_aff,
6743 "(C[] : { B[a,b] })",
6744 "{ B[a,b] -> A[b,a] }",
6745 "(C[] : { })" },
6746 { &isl_multi_union_pw_aff_pullback_union_pw_multi_aff,
6747 "(C[] : { B[a,b] })",
6748 "{ A[a,b] -> B[b,a] : a > b }",
6749 "(C[] : { A[a,b] : a > b })" },
6750 { &isl_multi_union_pw_aff_pullback_union_pw_multi_aff,
6751 "(C[] : { B[a,b] : a > b })",
6752 "{ A[a,b] -> B[b,a] }",
6753 "(C[] : { A[a,b] : b > a })" },
6754 { &isl_multi_union_pw_aff_pullback_union_pw_multi_aff,
6755 "[N] -> (C[] : { B[a,b] : a > N })",
6756 "{ A[a,b] -> B[b,a] : a > b }",
6757 "[N] -> (C[] : { A[a,b] : a > b > N })" },
6758 { &isl_multi_union_pw_aff_pullback_union_pw_multi_aff,
6759 "(C[] : { B[a,b] : a > b })",
6760 "[N] -> { A[a,b] -> B[b,a] : a > N }",
6761 "[N] -> (C[] : { A[a,b] : b > a > N })" },
6762 { &isl_multi_union_pw_aff_pullback_union_pw_multi_aff,
6763 "C[]",
6764 "{ A[a,b] -> B[b,a] }",
6765 "C[]" },
6766 { &isl_multi_union_pw_aff_pullback_union_pw_multi_aff,
6767 "[N] -> (C[] : { : N >= 0 })",
6768 "{ A[a,b] -> B[b,a] }",
6769 "[N] -> (C[] : { : N >= 0 })" },
6770 { &isl_multi_union_pw_aff_pullback_union_pw_multi_aff,
6771 "C[]",
6772 "[N] -> { A[a,b] -> B[b,a] : N >= 0 }",
6773 "[N] -> (C[] : { : N >= 0 })" },
6776 /* Perform some basic tests of binary operations on
6777 * pairs of isl_multi_union_pw_aff and isl_union_pw_multi_aff objects.
6779 static int test_mupa_upma(isl_ctx *ctx)
6781 int i;
6782 isl_bool ok;
6783 isl_multi_union_pw_aff *mupa, *res;
6784 isl_union_pw_multi_aff *upma;
6786 for (i = 0; i < ARRAY_SIZE(mupa_upma_tests); ++i) {
6787 mupa = isl_multi_union_pw_aff_read_from_str(ctx,
6788 mupa_upma_tests[i].arg1);
6789 upma = isl_union_pw_multi_aff_read_from_str(ctx,
6790 mupa_upma_tests[i].arg2);
6791 res = isl_multi_union_pw_aff_read_from_str(ctx,
6792 mupa_upma_tests[i].res);
6793 mupa = mupa_upma_tests[i].fn(mupa, upma);
6794 ok = isl_multi_union_pw_aff_plain_is_equal(mupa, res);
6795 isl_multi_union_pw_aff_free(mupa);
6796 isl_multi_union_pw_aff_free(res);
6797 if (ok < 0)
6798 return -1;
6799 if (!ok)
6800 isl_die(ctx, isl_error_unknown,
6801 "unexpected result", return -1);
6804 return 0;
6807 /* Check that the input tuple of an isl_aff can be set properly.
6809 static isl_stat test_aff_set_tuple_id(isl_ctx *ctx)
6811 isl_id *id;
6812 isl_aff *aff;
6813 isl_stat equal;
6815 aff = isl_aff_read_from_str(ctx, "{ [x] -> [x + 1] }");
6816 id = isl_id_alloc(ctx, "A", NULL);
6817 aff = isl_aff_set_tuple_id(aff, isl_dim_in, id);
6818 equal = aff_check_plain_equal(aff, "{ A[x] -> [x + 1] }");
6819 isl_aff_free(aff);
6820 if (equal < 0)
6821 return isl_stat_error;
6823 return isl_stat_ok;
6826 /* Check that affine expressions get normalized on addition/subtraction.
6827 * In particular, check that (final) unused integer divisions get removed
6828 * such that an expression derived from expressions with integer divisions
6829 * is found to be obviously equal to one that is created directly.
6831 static isl_stat test_aff_normalize(isl_ctx *ctx)
6833 isl_aff *aff, *aff2;
6834 isl_stat ok;
6836 aff = isl_aff_read_from_str(ctx, "{ [x] -> [x//2] }");
6837 aff2 = isl_aff_read_from_str(ctx, "{ [x] -> [1 + x//2] }");
6838 aff = isl_aff_sub(aff2, aff);
6839 ok = aff_check_plain_equal(aff, "{ [x] -> [1] }");
6840 isl_aff_free(aff);
6842 return ok;
6845 int test_aff(isl_ctx *ctx)
6847 const char *str;
6848 isl_set *set;
6849 isl_space *space;
6850 isl_local_space *ls;
6851 isl_aff *aff;
6852 int zero;
6853 isl_stat equal;
6855 if (test_upa(ctx) < 0)
6856 return -1;
6857 if (test_bin_aff(ctx) < 0)
6858 return -1;
6859 if (test_bin_pw_aff(ctx) < 0)
6860 return -1;
6861 if (test_upma_test(ctx) < 0)
6862 return -1;
6863 if (test_bin_upma(ctx) < 0)
6864 return -1;
6865 if (test_bin_upma_fail(ctx) < 0)
6866 return -1;
6867 if (test_upma_uset(ctx) < 0)
6868 return -1;
6869 if (test_un_mpa(ctx) < 0)
6870 return -1;
6871 if (test_bin_mpa(ctx) < 0)
6872 return -1;
6873 if (test_un_mupa(ctx) < 0)
6874 return -1;
6875 if (test_bin_mupa(ctx) < 0)
6876 return -1;
6877 if (test_mupa_set(ctx) < 0)
6878 return -1;
6879 if (test_mupa_uset(ctx) < 0)
6880 return -1;
6881 if (test_mupa_ma(ctx) < 0)
6882 return -1;
6883 if (test_mupa_pa(ctx) < 0)
6884 return -1;
6885 if (test_mupa_pma(ctx) < 0)
6886 return -1;
6887 if (test_mupa_upma(ctx) < 0)
6888 return -1;
6890 space = isl_space_set_alloc(ctx, 0, 1);
6891 ls = isl_local_space_from_space(space);
6892 aff = isl_aff_zero_on_domain(ls);
6894 aff = isl_aff_add_coefficient_si(aff, isl_dim_in, 0, 1);
6895 aff = isl_aff_scale_down_ui(aff, 3);
6896 aff = isl_aff_floor(aff);
6897 aff = isl_aff_add_coefficient_si(aff, isl_dim_in, 0, 1);
6898 aff = isl_aff_scale_down_ui(aff, 2);
6899 aff = isl_aff_floor(aff);
6900 aff = isl_aff_add_coefficient_si(aff, isl_dim_in, 0, 1);
6902 str = "{ [10] }";
6903 set = isl_set_read_from_str(ctx, str);
6904 aff = isl_aff_gist(aff, set);
6906 aff = isl_aff_add_constant_si(aff, -16);
6907 zero = isl_aff_plain_is_zero(aff);
6908 isl_aff_free(aff);
6910 if (zero < 0)
6911 return -1;
6912 if (!zero)
6913 isl_die(ctx, isl_error_unknown, "unexpected result", return -1);
6915 aff = isl_aff_read_from_str(ctx, "{ [-1] }");
6916 aff = isl_aff_scale_down_ui(aff, 64);
6917 aff = isl_aff_floor(aff);
6918 equal = aff_check_plain_equal(aff, "{ [-1] }");
6919 isl_aff_free(aff);
6920 if (equal < 0)
6921 return -1;
6923 if (test_aff_set_tuple_id(ctx) < 0)
6924 return -1;
6925 if (test_aff_normalize(ctx) < 0)
6926 return -1;
6928 return 0;
6931 /* Inputs for isl_set_bind tests.
6932 * "set" is the input set.
6933 * "tuple" is the binding tuple.
6934 * "res" is the expected result.
6936 static
6937 struct {
6938 const char *set;
6939 const char *tuple;
6940 const char *res;
6941 } bind_set_tests[] = {
6942 { "{ A[M, N] : M mod 2 = 0 and N mod 8 = 3 }",
6943 "{ A[M, N] }",
6944 "[M, N] -> { : M mod 2 = 0 and N mod 8 = 3 }" },
6945 { "{ B[N, M] : M mod 2 = 0 and N mod 8 = 3 }",
6946 "{ B[N, M] }",
6947 "[M, N] -> { : M mod 2 = 0 and N mod 8 = 3 }" },
6948 { "[M] -> { C[N] : M mod 2 = 0 and N mod 8 = 3 }",
6949 "{ C[N] }",
6950 "[M, N] -> { : M mod 2 = 0 and N mod 8 = 3 }" },
6951 { "[M] -> { D[x, N] : x mod 2 = 0 and N mod 8 = 3 and M >= 0 }",
6952 "{ D[M, N] }",
6953 "[M, N] -> { : M mod 2 = 0 and N mod 8 = 3 and M >= 0 }" },
6956 /* Perform basic isl_set_bind tests.
6958 static isl_stat test_bind_set(isl_ctx *ctx)
6960 int i;
6962 for (i = 0; i < ARRAY_SIZE(bind_set_tests); ++i) {
6963 const char *str;
6964 isl_set *set;
6965 isl_multi_id *tuple;
6966 isl_stat r;
6968 set = isl_set_read_from_str(ctx, bind_set_tests[i].set);
6969 str = bind_set_tests[i].tuple;
6970 tuple = isl_multi_id_read_from_str(ctx, str);
6971 set = isl_set_bind(set, tuple);
6972 r = set_check_equal(set, bind_set_tests[i].res);
6973 isl_set_free(set);
6974 if (r < 0)
6975 return isl_stat_error;
6978 return isl_stat_ok;
6981 /* Inputs for isl_map_bind_domain tests.
6982 * "map" is the input map.
6983 * "tuple" is the binding tuple.
6984 * "res" is the expected result.
6986 struct {
6987 const char *map;
6988 const char *tuple;
6989 const char *res;
6990 } bind_map_domain_tests[] = {
6991 { "{ A[M, N] -> [M + floor(N/2)] }",
6992 "{ A[M, N] }",
6993 "[M, N] -> { [M + floor(N/2)] }" },
6994 { "{ B[N, M] -> [M + floor(N/2)] }",
6995 "{ B[N, M] }",
6996 "[N, M] -> { [M + floor(N/2)] }" },
6997 { "[M] -> { C[N] -> [M + floor(N/2)] }",
6998 "{ C[N] }",
6999 "[M, N] -> { [M + floor(N/2)] }" },
7000 { "[M] -> { C[x, N] -> [x + floor(N/2)] }",
7001 "{ C[M, N] }",
7002 "[M, N] -> { [M + floor(N/2)] }" },
7003 { "[M] -> { C[x, N] -> [M + floor(N/2)] }",
7004 "{ C[M, N] }",
7005 "[M, N] -> { [M + floor(N/2)] }" },
7006 { "[A, M] -> { C[N, x] -> [x + floor(N/2)] }",
7007 "{ C[N, M] }",
7008 "[A, N, M] -> { [M + floor(N/2)] }" },
7011 /* Perform basic isl_map_bind_domain tests.
7013 static isl_stat test_bind_map_domain(isl_ctx *ctx)
7015 int i;
7017 for (i = 0; i < ARRAY_SIZE(bind_map_domain_tests); ++i) {
7018 const char *str;
7019 isl_map *map;
7020 isl_set *set;
7021 isl_multi_id *tuple;
7022 isl_stat r;
7024 str = bind_map_domain_tests[i].map;
7025 map = isl_map_read_from_str(ctx, str);
7026 str = bind_map_domain_tests[i].tuple;
7027 tuple = isl_multi_id_read_from_str(ctx, str);
7028 set = isl_map_bind_domain(map, tuple);
7029 str = bind_map_domain_tests[i].res;
7030 r = set_check_equal(set, str);
7031 isl_set_free(set);
7032 if (r < 0)
7033 return isl_stat_error;
7036 return isl_stat_ok;
7039 /* Inputs for isl_union_map_bind_range tests.
7040 * "map" is the input union map.
7041 * "tuple" is the binding tuple.
7042 * "res" is the expected result.
7044 struct {
7045 const char *map;
7046 const char *tuple;
7047 const char *res;
7048 } bind_umap_range_tests[] = {
7049 { "{ B[N, M] -> A[M, N] : M mod 2 = 0 and N mod 8 = 3 }",
7050 "{ A[M, N] }",
7051 "[M, N] -> { B[N, M] : M mod 2 = 0 and N mod 8 = 3 }" },
7052 { "{ B[N, M] -> A[M, N] : M mod 2 = 0 and N mod 8 = 3 }",
7053 "{ B[M, N] }",
7054 "{ }" },
7055 { "{ A[] -> B[]; C[] -> D[]; E[] -> B[] }",
7056 "{ B[] }",
7057 "{ A[]; E[] }" },
7060 /* Perform basic isl_union_map_bind_range tests.
7062 static isl_stat test_bind_umap_range(isl_ctx *ctx)
7064 int i;
7066 for (i = 0; i < ARRAY_SIZE(bind_umap_range_tests); ++i) {
7067 const char *str;
7068 isl_union_map *umap;
7069 isl_union_set *uset;
7070 isl_multi_id *tuple;
7071 isl_stat r;
7073 str = bind_umap_range_tests[i].map;
7074 umap = isl_union_map_read_from_str(ctx, str);
7075 str = bind_umap_range_tests[i].tuple;
7076 tuple = isl_multi_id_read_from_str(ctx, str);
7077 uset = isl_union_map_bind_range(umap, tuple);
7078 str = bind_umap_range_tests[i].res;
7079 r = uset_check_equal(uset, str);
7080 isl_union_set_free(uset);
7081 if (r < 0)
7082 return isl_stat_error;
7085 return isl_stat_ok;
7088 /* Inputs for isl_pw_multi_aff_bind_domain tests.
7089 * "pma" is the input expression.
7090 * "tuple" is the binding tuple.
7091 * "res" is the expected result.
7093 struct {
7094 const char *pma;
7095 const char *tuple;
7096 const char *res;
7097 } bind_pma_domain_tests[] = {
7098 { "{ A[M, N] -> [M + floor(N/2)] }",
7099 "{ A[M, N] }",
7100 "[M, N] -> { [M + floor(N/2)] }" },
7101 { "{ B[N, M] -> [M + floor(N/2)] }",
7102 "{ B[N, M] }",
7103 "[N, M] -> { [M + floor(N/2)] }" },
7104 { "[M] -> { C[N] -> [M + floor(N/2)] }",
7105 "{ C[N] }",
7106 "[M, N] -> { [M + floor(N/2)] }" },
7107 { "[M] -> { C[x, N] -> [x + floor(N/2)] }",
7108 "{ C[M, N] }",
7109 "[M, N] -> { [M + floor(N/2)] }" },
7110 { "[M] -> { C[x, N] -> [M + floor(N/2)] }",
7111 "{ C[M, N] }",
7112 "[M, N] -> { [M + floor(N/2)] }" },
7113 { "[A, M] -> { C[N, x] -> [x + floor(N/2)] }",
7114 "{ C[N, M] }",
7115 "[A, N, M] -> { [M + floor(N/2)] }" },
7118 /* Perform basic isl_pw_multi_aff_bind_domain tests.
7120 static isl_stat test_bind_pma_domain(isl_ctx *ctx)
7122 int i;
7124 for (i = 0; i < ARRAY_SIZE(bind_pma_domain_tests); ++i) {
7125 const char *str;
7126 isl_pw_multi_aff *pma;
7127 isl_multi_id *tuple;
7128 isl_stat r;
7130 str = bind_pma_domain_tests[i].pma;
7131 pma = isl_pw_multi_aff_read_from_str(ctx, str);
7132 str = bind_pma_domain_tests[i].tuple;
7133 tuple = isl_multi_id_read_from_str(ctx, str);
7134 pma = isl_pw_multi_aff_bind_domain(pma, tuple);
7135 str = bind_pma_domain_tests[i].res;
7136 r = pw_multi_aff_check_plain_equal(pma, str);
7137 isl_pw_multi_aff_free(pma);
7138 if (r < 0)
7139 return isl_stat_error;
7142 return isl_stat_ok;
7145 /* Inputs for isl_pw_multi_aff_bind_domain_wrapped_domain tests.
7146 * "pma" is the input expression.
7147 * "tuple" is the binding tuple.
7148 * "res" is the expected result.
7150 struct {
7151 const char *pma;
7152 const char *tuple;
7153 const char *res;
7154 } bind_pma_domain_wrapped_tests[] = {
7155 { "{ [A[M, N] -> B[]] -> [M + floor(N/2)] }",
7156 "{ A[M, N] }",
7157 "[M, N] -> { B[] -> [M + floor(N/2)] }" },
7158 { "{ [B[N, M] -> D[]] -> [M + floor(N/2)] }",
7159 "{ B[N, M] }",
7160 "[N, M] -> { D[] -> [M + floor(N/2)] }" },
7161 { "[M] -> { [C[N] -> B[x]] -> [x + M + floor(N/2)] }",
7162 "{ C[N] }",
7163 "[M, N] -> { B[x] -> [x + M + floor(N/2)] }" },
7164 { "[M] -> { [C[x, N] -> B[]] -> [x + floor(N/2)] }",
7165 "{ C[M, N] }",
7166 "[M, N] -> { B[] -> [M + floor(N/2)] }" },
7167 { "[M] -> { [C[x, N] -> B[]] -> [M + floor(N/2)] }",
7168 "{ C[M, N] }",
7169 "[M, N] -> { B[] -> [M + floor(N/2)] }" },
7170 { "[A, M] -> { [C[N, x] -> B[]] -> [x + floor(N/2)] }",
7171 "{ C[N, M] }",
7172 "[A, N, M] -> { B[] -> [M + floor(N/2)] }" },
7175 /* Perform basic isl_pw_multi_aff_bind_domain_wrapped_domain tests.
7177 static isl_stat test_bind_pma_domain_wrapped(isl_ctx *ctx)
7179 int i;
7181 for (i = 0; i < ARRAY_SIZE(bind_pma_domain_wrapped_tests); ++i) {
7182 const char *str;
7183 isl_pw_multi_aff *pma;
7184 isl_multi_id *tuple;
7185 isl_stat r;
7187 str = bind_pma_domain_wrapped_tests[i].pma;
7188 pma = isl_pw_multi_aff_read_from_str(ctx, str);
7189 str = bind_pma_domain_wrapped_tests[i].tuple;
7190 tuple = isl_multi_id_read_from_str(ctx, str);
7191 pma = isl_pw_multi_aff_bind_domain_wrapped_domain(pma, tuple);
7192 str = bind_pma_domain_wrapped_tests[i].res;
7193 r = pw_multi_aff_check_plain_equal(pma, str);
7194 isl_pw_multi_aff_free(pma);
7195 if (r < 0)
7196 return isl_stat_error;
7199 return isl_stat_ok;
7202 /* Inputs for isl_aff_bind_id tests.
7203 * "aff" is the input expression.
7204 * "id" is the binding id.
7205 * "res" is the expected result.
7207 static
7208 struct {
7209 const char *aff;
7210 const char *id;
7211 const char *res;
7212 } bind_aff_tests[] = {
7213 { "{ [4] }", "M", "[M = 4] -> { : }" },
7214 { "{ B[x] -> [floor(x/2)] }", "M", "[M] -> { B[x] : M = floor(x/2) }" },
7215 { "[M] -> { [4] }", "M", "[M = 4] -> { : }" },
7216 { "[M] -> { [floor(M/2)] }", "M", "[M] -> { : floor(M/2) = M }" },
7217 { "{ [NaN] }", "M", "{ : false }" },
7218 { "{ A[x] -> [NaN] }", "M", "{ A[x] : false }" },
7221 /* Perform basic isl_aff_bind_id tests.
7223 static isl_stat test_bind_aff(isl_ctx *ctx)
7225 int i;
7227 for (i = 0; i < ARRAY_SIZE(bind_aff_tests); ++i) {
7228 isl_aff *aff;
7229 isl_set *res;
7230 isl_id *id;
7231 isl_stat r;
7233 aff = isl_aff_read_from_str(ctx, bind_aff_tests[i].aff);
7234 id = isl_id_read_from_str(ctx, bind_aff_tests[i].id);
7235 res = isl_set_from_basic_set(isl_aff_bind_id(aff, id));
7236 r = set_check_equal(res, bind_aff_tests[i].res);
7237 isl_set_free(res);
7238 if (r < 0)
7239 return isl_stat_error;
7242 return isl_stat_ok;
7245 /* Inputs for isl_pw_aff_bind_id tests.
7246 * "pa" is the input expression.
7247 * "id" is the binding id.
7248 * "res" is the expected result.
7250 static
7251 struct {
7252 const char *pa;
7253 const char *id;
7254 const char *res;
7255 } bind_pa_tests[] = {
7256 { "{ [4] }", "M", "[M = 4] -> { : }" },
7257 { "{ B[x] -> [floor(x/2)] }", "M", "[M] -> { B[x] : M = floor(x/2) }" },
7258 { "[M] -> { [4] }", "M", "[M = 4] -> { : }" },
7259 { "[M] -> { [floor(M/2)] }", "M", "[M] -> { : floor(M/2) = M }" },
7260 { "[M] -> { [M] : M >= 0; [-M] : M < 0 }", "M", "[M] -> { : M >= 0 }" },
7261 { "{ [NaN] }", "M", "{ : false }" },
7262 { "{ A[x] -> [NaN] }", "M", "{ A[x] : false }" },
7265 /* Perform basic isl_pw_aff_bind_id tests.
7267 static isl_stat test_bind_pa(isl_ctx *ctx)
7269 int i;
7271 for (i = 0; i < ARRAY_SIZE(bind_pa_tests); ++i) {
7272 isl_pw_aff *pa;
7273 isl_set *res;
7274 isl_id *id;
7275 isl_stat r;
7277 pa = isl_pw_aff_read_from_str(ctx, bind_pa_tests[i].pa);
7278 id = isl_id_read_from_str(ctx, bind_pa_tests[i].id);
7279 res = isl_pw_aff_bind_id(pa, id);
7280 r = set_check_equal(res, bind_pa_tests[i].res);
7281 isl_set_free(res);
7282 if (r < 0)
7283 return isl_stat_error;
7286 return isl_stat_ok;
7289 /* Inputs for isl_multi_union_pw_aff_bind tests.
7290 * "mupa" is the input expression.
7291 * "tuple" is the binding tuple.
7292 * "res" is the expected result.
7294 static
7295 struct {
7296 const char *mupa;
7297 const char *tuple;
7298 const char *res;
7299 } bind_mupa_tests[] = {
7300 { "A[{ [4] }, { [5] }]",
7301 "{ A[M, N] }",
7302 "[M = 4, N = 5] -> { : }" },
7303 { "A[{ B[x] -> [floor(x/2)] }, { B[y] -> [y + 5] }]",
7304 "{ A[M, N] }",
7305 "[M, N] -> { B[x] : M = floor(x/2) and N = x + 5 }" },
7306 { "[M] -> A[{ [4] }, { [M + 1] }]",
7307 "{ A[M, N] }",
7308 "[M = 4, N = 5] -> { : }" },
7311 /* Perform basic isl_multi_union_pw_aff_bind tests.
7313 static isl_stat test_bind_mupa(isl_ctx *ctx)
7315 int i;
7317 for (i = 0; i < ARRAY_SIZE(bind_mupa_tests); ++i) {
7318 const char *str;
7319 isl_multi_union_pw_aff *mupa;
7320 isl_union_set *res;
7321 isl_multi_id *tuple;
7322 isl_stat r;
7324 str = bind_mupa_tests[i].mupa;
7325 mupa = isl_multi_union_pw_aff_read_from_str(ctx, str);
7326 str = bind_mupa_tests[i].tuple;
7327 tuple = isl_multi_id_read_from_str(ctx, str);
7328 res = isl_multi_union_pw_aff_bind(mupa, tuple);
7329 r = uset_check_equal(res, bind_mupa_tests[i].res);
7330 isl_union_set_free(res);
7331 if (r < 0)
7332 return isl_stat_error;
7335 return isl_stat_ok;
7338 /* Perform tests that reinterpret dimensions as parameters.
7340 static int test_bind(isl_ctx *ctx)
7342 if (test_bind_set(ctx) < 0)
7343 return -1;
7344 if (test_bind_map_domain(ctx) < 0)
7345 return -1;
7346 if (test_bind_umap_range(ctx) < 0)
7347 return -1;
7348 if (test_bind_pma_domain(ctx) < 0)
7349 return -1;
7350 if (test_bind_pma_domain_wrapped(ctx) < 0)
7351 return -1;
7352 if (test_bind_aff(ctx) < 0)
7353 return -1;
7354 if (test_bind_pa(ctx) < 0)
7355 return -1;
7356 if (test_bind_mupa(ctx) < 0)
7357 return -1;
7359 return 0;
7362 /* Inputs for isl_set_unbind_params tests.
7363 * "set" is the input parameter domain.
7364 * "tuple" is the tuple of the constructed set.
7365 * "res" is the expected result.
7367 struct {
7368 const char *set;
7369 const char *tuple;
7370 const char *res;
7371 } unbind_set_tests[] = {
7372 { "[M, N] -> { : M mod 2 = 0 and N mod 8 = 3 }",
7373 "{ A[M, N] }",
7374 "{ A[M, N] : M mod 2 = 0 and N mod 8 = 3 }" },
7375 { "[M, N] -> { : M mod 2 = 0 and N mod 8 = 3 }",
7376 "{ B[N, M] }",
7377 "{ B[N, M] : M mod 2 = 0 and N mod 8 = 3 }" },
7378 { "[M, N] -> { : M mod 2 = 0 and N mod 8 = 3 }",
7379 "{ C[N] }",
7380 "[M] -> { C[N] : M mod 2 = 0 and N mod 8 = 3 }" },
7381 { "[M, N] -> { : M mod 2 = 0 and N mod 8 = 3 }",
7382 "{ D[T, N] }",
7383 "[M] -> { D[x, N] : M mod 2 = 0 and N mod 8 = 3 }" },
7386 /* Perform basic isl_set_unbind_params tests.
7388 static isl_stat test_unbind_set(isl_ctx *ctx)
7390 int i;
7392 for (i = 0; i < ARRAY_SIZE(unbind_set_tests); ++i) {
7393 const char *str;
7394 isl_set *set;
7395 isl_multi_id *tuple;
7396 isl_stat r;
7398 set = isl_set_read_from_str(ctx, unbind_set_tests[i].set);
7399 str = unbind_set_tests[i].tuple;
7400 tuple = isl_multi_id_read_from_str(ctx, str);
7401 set = isl_set_unbind_params(set, tuple);
7402 r = set_check_equal(set, unbind_set_tests[i].res);
7403 isl_set_free(set);
7404 if (r < 0)
7405 return isl_stat_error;
7408 return isl_stat_ok;
7411 /* Inputs for isl_aff_unbind_params_insert_domain tests.
7412 * "aff" is the input affine expression defined over a parameter domain.
7413 * "tuple" is the tuple of the domain that gets introduced.
7414 * "res" is the expected result.
7416 struct {
7417 const char *aff;
7418 const char *tuple;
7419 const char *res;
7420 } unbind_aff_tests[] = {
7421 { "[M, N] -> { [M + floor(N/2)] }",
7422 "{ A[M, N] }",
7423 "{ A[M, N] -> [M + floor(N/2)] }" },
7424 { "[M, N] -> { [M + floor(N/2)] }",
7425 "{ B[N, M] }",
7426 "{ B[N, M] -> [M + floor(N/2)] }" },
7427 { "[M, N] -> { [M + floor(N/2)] }",
7428 "{ C[N] }",
7429 "[M] -> { C[N] -> [M + floor(N/2)] }" },
7430 { "[M, N] -> { [M + floor(N/2)] }",
7431 "{ D[A, B, C, N, Z] }",
7432 "[M] -> { D[A, B, C, N, Z] -> [M + floor(N/2)] }" },
7435 /* Perform basic isl_aff_unbind_params_insert_domain tests.
7437 static isl_stat test_unbind_aff(isl_ctx *ctx)
7439 int i;
7441 for (i = 0; i < ARRAY_SIZE(unbind_aff_tests); ++i) {
7442 const char *str;
7443 isl_aff *aff;
7444 isl_multi_id *tuple;
7445 isl_stat r;
7447 aff = isl_aff_read_from_str(ctx, unbind_aff_tests[i].aff);
7448 str = unbind_aff_tests[i].tuple;
7449 tuple = isl_multi_id_read_from_str(ctx, str);
7450 aff = isl_aff_unbind_params_insert_domain(aff, tuple);
7451 r = aff_check_plain_equal(aff, unbind_aff_tests[i].res);
7452 isl_aff_free(aff);
7453 if (r < 0)
7454 return isl_stat_error;
7457 return isl_stat_ok;
7460 /* Inputs for isl_multi_aff_unbind_params_insert_domain tests.
7461 * "ma" is the input multi affine expression defined over a parameter domain.
7462 * "tuple" is the tuple of the domain that gets introduced.
7463 * "res" is the expected result.
7465 static struct {
7466 const char *ma;
7467 const char *tuple;
7468 const char *res;
7469 } unbind_multi_aff_tests[] = {
7470 { "[M, N] -> { T[M + floor(N/2)] }",
7471 "{ A[M, N] }",
7472 "{ A[M, N] -> T[M + floor(N/2)] }" },
7473 { "[M, N] -> { [M + floor(N/2)] }",
7474 "{ B[N, M] }",
7475 "{ B[N, M] -> [M + floor(N/2)] }" },
7476 { "[M, N] -> { [M + floor(N/2)] }",
7477 "{ C[N] }",
7478 "[M] -> { C[N] -> [M + floor(N/2)] }" },
7479 { "[M, N] -> { [M + floor(N/2)] }",
7480 "{ D[A, B, C, N, Z] }",
7481 "[M] -> { D[A, B, C, N, Z] -> [M + floor(N/2)] }" },
7482 { "[M, N] -> { T[M + floor(N/2), N + floor(M/3)] }",
7483 "{ A[M, N] }",
7484 "{ A[M, N] -> T[M + floor(N/2), N + floor(M/3)] }" },
7487 /* Perform basic isl_multi_aff_unbind_params_insert_domain tests.
7489 static isl_stat test_unbind_multi_aff(isl_ctx *ctx)
7491 int i;
7493 for (i = 0; i < ARRAY_SIZE(unbind_multi_aff_tests); ++i) {
7494 const char *str;
7495 isl_multi_aff *ma;
7496 isl_multi_id *tuple;
7497 isl_stat r;
7499 str = unbind_multi_aff_tests[i].ma;
7500 ma = isl_multi_aff_read_from_str(ctx, str);
7501 str = unbind_multi_aff_tests[i].tuple;
7502 tuple = isl_multi_id_read_from_str(ctx, str);
7503 ma = isl_multi_aff_unbind_params_insert_domain(ma, tuple);
7504 str = unbind_multi_aff_tests[i].res;
7505 r = multi_aff_check_plain_equal(ma, str);
7506 isl_multi_aff_free(ma);
7507 if (r < 0)
7508 return isl_stat_error;
7511 return isl_stat_ok;
7514 /* Perform tests that reinterpret parameters.
7516 static int test_unbind(isl_ctx *ctx)
7518 if (test_unbind_set(ctx) < 0)
7519 return -1;
7520 if (test_unbind_aff(ctx) < 0)
7521 return -1;
7522 if (test_unbind_multi_aff(ctx) < 0)
7523 return -1;
7525 return 0;
7528 /* Check that "pa" consists of a single expression.
7530 static int check_single_piece(isl_ctx *ctx, __isl_take isl_pw_aff *pa)
7532 isl_size n;
7534 n = isl_pw_aff_n_piece(pa);
7535 isl_pw_aff_free(pa);
7537 if (n < 0)
7538 return -1;
7539 if (n != 1)
7540 isl_die(ctx, isl_error_unknown, "expecting single expression",
7541 return -1);
7543 return 0;
7546 /* Check that the computation below results in a single expression.
7547 * One or two expressions may result depending on which constraint
7548 * ends up being considered as redundant with respect to the other
7549 * constraints after the projection that is performed internally
7550 * by isl_set_dim_min.
7552 static int test_dim_max_1(isl_ctx *ctx)
7554 const char *str;
7555 isl_set *set;
7556 isl_pw_aff *pa;
7558 str = "[n] -> { [a, b] : n >= 0 and 4a >= -4 + n and b >= 0 and "
7559 "-4a <= b <= 3 and b < n - 4a }";
7560 set = isl_set_read_from_str(ctx, str);
7561 pa = isl_set_dim_min(set, 0);
7562 return check_single_piece(ctx, pa);
7565 /* Check that the computation below results in a single expression.
7566 * The PIP problem corresponding to these constraints has a row
7567 * that causes a split of the solution domain. The solver should
7568 * first pick rows that split off empty parts such that the actual
7569 * solution domain does not get split.
7570 * Note that the description contains some redundant constraints.
7571 * If these constraints get removed first, then the row mentioned
7572 * above does not appear in the PIP problem.
7574 static int test_dim_max_2(isl_ctx *ctx)
7576 const char *str;
7577 isl_set *set;
7578 isl_pw_aff *pa;
7580 str = "[P, N] -> { [a] : a < N and a >= 0 and N > P and a <= P and "
7581 "N > 0 and P >= 0 }";
7582 set = isl_set_read_from_str(ctx, str);
7583 pa = isl_set_dim_max(set, 0);
7584 return check_single_piece(ctx, pa);
7587 int test_dim_max(isl_ctx *ctx)
7589 int equal;
7590 const char *str;
7591 isl_set *set1, *set2;
7592 isl_set *set;
7593 isl_map *map;
7594 isl_pw_aff *pwaff;
7596 if (test_dim_max_1(ctx) < 0)
7597 return -1;
7598 if (test_dim_max_2(ctx) < 0)
7599 return -1;
7601 str = "[N] -> { [i] : 0 <= i <= min(N,10) }";
7602 set = isl_set_read_from_str(ctx, str);
7603 pwaff = isl_set_dim_max(set, 0);
7604 set1 = isl_set_from_pw_aff(pwaff);
7605 str = "[N] -> { [10] : N >= 10; [N] : N <= 9 and N >= 0 }";
7606 set2 = isl_set_read_from_str(ctx, str);
7607 equal = isl_set_is_equal(set1, set2);
7608 isl_set_free(set1);
7609 isl_set_free(set2);
7610 if (equal < 0)
7611 return -1;
7612 if (!equal)
7613 isl_die(ctx, isl_error_unknown, "unexpected result", return -1);
7615 str = "[N] -> { [i] : 0 <= i <= max(2N,N+6) }";
7616 set = isl_set_read_from_str(ctx, str);
7617 pwaff = isl_set_dim_max(set, 0);
7618 set1 = isl_set_from_pw_aff(pwaff);
7619 str = "[N] -> { [6 + N] : -6 <= N <= 5; [2N] : N >= 6 }";
7620 set2 = isl_set_read_from_str(ctx, str);
7621 equal = isl_set_is_equal(set1, set2);
7622 isl_set_free(set1);
7623 isl_set_free(set2);
7624 if (equal < 0)
7625 return -1;
7626 if (!equal)
7627 isl_die(ctx, isl_error_unknown, "unexpected result", return -1);
7629 str = "[N] -> { [i] : 0 <= i <= 2N or 0 <= i <= N+6 }";
7630 set = isl_set_read_from_str(ctx, str);
7631 pwaff = isl_set_dim_max(set, 0);
7632 set1 = isl_set_from_pw_aff(pwaff);
7633 str = "[N] -> { [6 + N] : -6 <= N <= 5; [2N] : N >= 6 }";
7634 set2 = isl_set_read_from_str(ctx, str);
7635 equal = isl_set_is_equal(set1, set2);
7636 isl_set_free(set1);
7637 isl_set_free(set2);
7638 if (equal < 0)
7639 return -1;
7640 if (!equal)
7641 isl_die(ctx, isl_error_unknown, "unexpected result", return -1);
7643 str = "[N,M] -> { [i,j] -> [([i/16]), i%16, ([j/16]), j%16] : "
7644 "0 <= i < N and 0 <= j < M }";
7645 map = isl_map_read_from_str(ctx, str);
7646 set = isl_map_range(map);
7648 pwaff = isl_set_dim_max(isl_set_copy(set), 0);
7649 set1 = isl_set_from_pw_aff(pwaff);
7650 str = "[N,M] -> { [([(N-1)/16])] : M,N > 0 }";
7651 set2 = isl_set_read_from_str(ctx, str);
7652 equal = isl_set_is_equal(set1, set2);
7653 isl_set_free(set1);
7654 isl_set_free(set2);
7656 pwaff = isl_set_dim_max(isl_set_copy(set), 3);
7657 set1 = isl_set_from_pw_aff(pwaff);
7658 str = "[N,M] -> { [t] : t = min(M-1,15) and M,N > 0 }";
7659 set2 = isl_set_read_from_str(ctx, str);
7660 if (equal >= 0 && equal)
7661 equal = isl_set_is_equal(set1, set2);
7662 isl_set_free(set1);
7663 isl_set_free(set2);
7665 isl_set_free(set);
7667 if (equal < 0)
7668 return -1;
7669 if (!equal)
7670 isl_die(ctx, isl_error_unknown, "unexpected result", return -1);
7672 /* Check that solutions are properly merged. */
7673 str = "[n] -> { [a, b, c] : c >= -4a - 2b and "
7674 "c <= -1 + n - 4a - 2b and c >= -2b and "
7675 "4a >= -4 + n and c >= 0 }";
7676 set = isl_set_read_from_str(ctx, str);
7677 pwaff = isl_set_dim_min(set, 2);
7678 set1 = isl_set_from_pw_aff(pwaff);
7679 str = "[n] -> { [(0)] : n >= 1 }";
7680 set2 = isl_set_read_from_str(ctx, str);
7681 equal = isl_set_is_equal(set1, set2);
7682 isl_set_free(set1);
7683 isl_set_free(set2);
7685 if (equal < 0)
7686 return -1;
7687 if (!equal)
7688 isl_die(ctx, isl_error_unknown, "unexpected result", return -1);
7690 /* Check that empty solution lie in the right space. */
7691 str = "[n] -> { [t,a] : 1 = 0 }";
7692 set = isl_set_read_from_str(ctx, str);
7693 pwaff = isl_set_dim_max(set, 0);
7694 set1 = isl_set_from_pw_aff(pwaff);
7695 str = "[n] -> { [t] : 1 = 0 }";
7696 set2 = isl_set_read_from_str(ctx, str);
7697 equal = isl_set_is_equal(set1, set2);
7698 isl_set_free(set1);
7699 isl_set_free(set2);
7701 if (equal < 0)
7702 return -1;
7703 if (!equal)
7704 isl_die(ctx, isl_error_unknown, "unexpected result", return -1);
7706 return 0;
7709 /* Basic test for isl_pw_multi_aff_product.
7711 * Check that multiple pieces are properly handled.
7713 static int test_product_pma(isl_ctx *ctx)
7715 isl_stat equal;
7716 const char *str;
7717 isl_pw_multi_aff *pma1, *pma2;
7719 str = "{ A[i] -> B[1] : i < 0; A[i] -> B[2] : i >= 0 }";
7720 pma1 = isl_pw_multi_aff_read_from_str(ctx, str);
7721 str = "{ C[] -> D[] }";
7722 pma2 = isl_pw_multi_aff_read_from_str(ctx, str);
7723 pma1 = isl_pw_multi_aff_product(pma1, pma2);
7724 str = "{ [A[i] -> C[]] -> [B[(1)] -> D[]] : i < 0;"
7725 "[A[i] -> C[]] -> [B[(2)] -> D[]] : i >= 0 }";
7726 equal = pw_multi_aff_check_plain_equal(pma1, str);
7727 isl_pw_multi_aff_free(pma1);
7728 if (equal < 0)
7729 return -1;
7731 return 0;
7734 int test_product(isl_ctx *ctx)
7736 const char *str;
7737 isl_set *set;
7738 isl_union_set *uset1, *uset2;
7739 int ok;
7741 str = "{ A[i] }";
7742 set = isl_set_read_from_str(ctx, str);
7743 set = isl_set_product(set, isl_set_copy(set));
7744 ok = isl_set_is_wrapping(set);
7745 isl_set_free(set);
7746 if (ok < 0)
7747 return -1;
7748 if (!ok)
7749 isl_die(ctx, isl_error_unknown, "unexpected result", return -1);
7751 str = "{ [] }";
7752 uset1 = isl_union_set_read_from_str(ctx, str);
7753 uset1 = isl_union_set_product(uset1, isl_union_set_copy(uset1));
7754 str = "{ [[] -> []] }";
7755 uset2 = isl_union_set_read_from_str(ctx, str);
7756 ok = isl_union_set_is_equal(uset1, uset2);
7757 isl_union_set_free(uset1);
7758 isl_union_set_free(uset2);
7759 if (ok < 0)
7760 return -1;
7761 if (!ok)
7762 isl_die(ctx, isl_error_unknown, "unexpected result", return -1);
7764 if (test_product_pma(ctx) < 0)
7765 return -1;
7767 return 0;
7770 /* Check that two sets are not considered disjoint just because
7771 * they have a different set of (named) parameters.
7773 static int test_disjoint(isl_ctx *ctx)
7775 const char *str;
7776 isl_set *set, *set2;
7777 int disjoint;
7779 str = "[n] -> { [[]->[]] }";
7780 set = isl_set_read_from_str(ctx, str);
7781 str = "{ [[]->[]] }";
7782 set2 = isl_set_read_from_str(ctx, str);
7783 disjoint = isl_set_is_disjoint(set, set2);
7784 isl_set_free(set);
7785 isl_set_free(set2);
7786 if (disjoint < 0)
7787 return -1;
7788 if (disjoint)
7789 isl_die(ctx, isl_error_unknown, "unexpected result", return -1);
7791 return 0;
7794 /* Inputs for isl_pw_multi_aff_is_equal tests.
7795 * "f1" and "f2" are the two function that need to be compared.
7796 * "equal" is the expected result.
7798 struct {
7799 int equal;
7800 const char *f1;
7801 const char *f2;
7802 } pma_equal_tests[] = {
7803 { 1, "[N] -> { [floor(N/2)] : 0 <= N <= 1 }",
7804 "[N] -> { [0] : 0 <= N <= 1 }" },
7805 { 1, "[N] -> { [floor(N/2)] : 0 <= N <= 2 }",
7806 "[N] -> { [0] : 0 <= N <= 1; [1] : N = 2 }" },
7807 { 0, "[N] -> { [floor(N/2)] : 0 <= N <= 2 }",
7808 "[N] -> { [0] : 0 <= N <= 1 }" },
7809 { 0, "{ [NaN] }", "{ [NaN] }" },
7812 int test_equal(isl_ctx *ctx)
7814 int i;
7815 const char *str;
7816 isl_set *set, *set2;
7817 int equal;
7819 str = "{ S_6[i] }";
7820 set = isl_set_read_from_str(ctx, str);
7821 str = "{ S_7[i] }";
7822 set2 = isl_set_read_from_str(ctx, str);
7823 equal = isl_set_is_equal(set, set2);
7824 isl_set_free(set);
7825 isl_set_free(set2);
7826 if (equal < 0)
7827 return -1;
7828 if (equal)
7829 isl_die(ctx, isl_error_unknown, "unexpected result", return -1);
7831 for (i = 0; i < ARRAY_SIZE(pma_equal_tests); ++i) {
7832 int expected = pma_equal_tests[i].equal;
7833 isl_pw_multi_aff *f1, *f2;
7835 f1 = isl_pw_multi_aff_read_from_str(ctx, pma_equal_tests[i].f1);
7836 f2 = isl_pw_multi_aff_read_from_str(ctx, pma_equal_tests[i].f2);
7837 equal = isl_pw_multi_aff_is_equal(f1, f2);
7838 isl_pw_multi_aff_free(f1);
7839 isl_pw_multi_aff_free(f2);
7840 if (equal < 0)
7841 return -1;
7842 if (equal != expected)
7843 isl_die(ctx, isl_error_unknown,
7844 "unexpected equality result", return -1);
7847 return 0;
7850 static int test_plain_fixed(isl_ctx *ctx, __isl_take isl_map *map,
7851 enum isl_dim_type type, unsigned pos, int fixed)
7853 isl_bool test;
7855 test = isl_map_plain_is_fixed(map, type, pos, NULL);
7856 isl_map_free(map);
7857 if (test < 0)
7858 return -1;
7859 if (test == fixed)
7860 return 0;
7861 if (fixed)
7862 isl_die(ctx, isl_error_unknown,
7863 "map not detected as fixed", return -1);
7864 else
7865 isl_die(ctx, isl_error_unknown,
7866 "map detected as fixed", return -1);
7869 int test_fixed(isl_ctx *ctx)
7871 const char *str;
7872 isl_map *map;
7874 str = "{ [i] -> [i] }";
7875 map = isl_map_read_from_str(ctx, str);
7876 if (test_plain_fixed(ctx, map, isl_dim_out, 0, 0))
7877 return -1;
7878 str = "{ [i] -> [1] }";
7879 map = isl_map_read_from_str(ctx, str);
7880 if (test_plain_fixed(ctx, map, isl_dim_out, 0, 1))
7881 return -1;
7882 str = "{ S_1[p1] -> [o0] : o0 = -2 and p1 >= 1 and p1 <= 7 }";
7883 map = isl_map_read_from_str(ctx, str);
7884 if (test_plain_fixed(ctx, map, isl_dim_out, 0, 1))
7885 return -1;
7886 map = isl_map_read_from_str(ctx, str);
7887 map = isl_map_neg(map);
7888 if (test_plain_fixed(ctx, map, isl_dim_out, 0, 1))
7889 return -1;
7891 return 0;
7894 struct isl_vertices_test_data {
7895 const char *set;
7896 int n;
7897 const char *vertex[6];
7898 } vertices_tests[] = {
7899 { "{ A[t, i] : t = 12 and i >= 4 and i <= 12 }",
7900 2, { "{ A[12, 4] }", "{ A[12, 12] }" } },
7901 { "{ A[t, i] : t = 14 and i = 1 }",
7902 1, { "{ A[14, 1] }" } },
7903 { "[n, m] -> { [a, b, c] : b <= a and a <= n and b > 0 and c >= b and "
7904 "c <= m and m <= n and m > 0 }",
7905 6, {
7906 "[n, m] -> { [n, m, m] : 0 < m <= n }",
7907 "[n, m] -> { [n, 1, m] : 0 < m <= n }",
7908 "[n, m] -> { [n, 1, 1] : 0 < m <= n }",
7909 "[n, m] -> { [m, m, m] : 0 < m <= n }",
7910 "[n, m] -> { [1, 1, m] : 0 < m <= n }",
7911 "[n, m] -> { [1, 1, 1] : 0 < m <= n }"
7912 } },
7913 /* An input with implicit equality constraints among the parameters. */
7914 { "[N, M] -> { [a, b] : M >= 3 and 9 + 3M <= a <= 29 + 2N + 11M and "
7915 "2b >= M + a and 5 - 2N - M + a <= 2b <= 3 + a and "
7916 "3b >= 15 + a }",
7917 2, {
7918 "[N, M] -> { [(21), (12)] : M = 3 and N >= 0 }",
7919 "[N, M] -> { [(61 + 2N), (32 + N)] : M = 3 and N >= 0 }",
7924 /* Check that "vertex" corresponds to one of the vertices in data->vertex.
7926 static isl_stat find_vertex(__isl_take isl_vertex *vertex, void *user)
7928 struct isl_vertices_test_data *data = user;
7929 isl_ctx *ctx;
7930 isl_multi_aff *ma;
7931 isl_basic_set *bset;
7932 isl_pw_multi_aff *pma;
7933 int i;
7934 isl_bool equal;
7936 ctx = isl_vertex_get_ctx(vertex);
7937 bset = isl_vertex_get_domain(vertex);
7938 ma = isl_vertex_get_expr(vertex);
7939 pma = isl_pw_multi_aff_alloc(isl_set_from_basic_set(bset), ma);
7941 for (i = 0; i < data->n; ++i) {
7942 isl_pw_multi_aff *pma_i;
7944 pma_i = isl_pw_multi_aff_read_from_str(ctx, data->vertex[i]);
7945 equal = isl_pw_multi_aff_plain_is_equal(pma, pma_i);
7946 isl_pw_multi_aff_free(pma_i);
7948 if (equal < 0 || equal)
7949 break;
7952 isl_pw_multi_aff_free(pma);
7953 isl_vertex_free(vertex);
7955 if (equal < 0)
7956 return isl_stat_error;
7958 return equal ? isl_stat_ok : isl_stat_error;
7961 int test_vertices(isl_ctx *ctx)
7963 int i;
7965 for (i = 0; i < ARRAY_SIZE(vertices_tests); ++i) {
7966 isl_basic_set *bset;
7967 isl_vertices *vertices;
7968 int ok = 1;
7969 isl_size n;
7971 bset = isl_basic_set_read_from_str(ctx, vertices_tests[i].set);
7972 vertices = isl_basic_set_compute_vertices(bset);
7973 n = isl_vertices_get_n_vertices(vertices);
7974 if (vertices_tests[i].n != n)
7975 ok = 0;
7976 if (isl_vertices_foreach_vertex(vertices, &find_vertex,
7977 &vertices_tests[i]) < 0)
7978 ok = 0;
7979 isl_vertices_free(vertices);
7980 isl_basic_set_free(bset);
7982 if (n < 0)
7983 return -1;
7984 if (!ok)
7985 isl_die(ctx, isl_error_unknown, "unexpected vertices",
7986 return -1);
7989 return 0;
7992 /* Inputs for basic tests of unary operations on isl_union_map.
7993 * "fn" is the function that is being tested.
7994 * "arg" is a string description of the input.
7995 * "res" is a string description of the expected result.
7997 static struct {
7998 __isl_give isl_union_map *(*fn)(__isl_take isl_union_map *umap);
7999 const char *arg;
8000 const char *res;
8001 } umap_un_tests[] = {
8002 { &isl_union_map_range_reverse,
8003 "{ A[] -> [B[] -> C[]]; A[] -> B[]; A[0] -> N[B[1] -> B[2]] }",
8004 "{ A[] -> [C[] -> B[]]; A[0] -> N[B[2] -> B[1]] }" },
8005 { &isl_union_map_range_reverse,
8006 "{ A[] -> N[B[] -> C[]] }",
8007 "{ A[] -> [C[] -> B[]] }" },
8008 { &isl_union_map_range_reverse,
8009 "{ A[] -> N[B[x] -> B[y]] }",
8010 "{ A[] -> N[B[*] -> B[*]] }" },
8013 /* Perform basic tests of unary operations on isl_union_map.
8015 static isl_stat test_un_union_map(isl_ctx *ctx)
8017 int i;
8019 for (i = 0; i < ARRAY_SIZE(umap_un_tests); ++i) {
8020 const char *str;
8021 isl_union_map *umap, *res;
8022 isl_bool equal;
8024 str = umap_un_tests[i].arg;
8025 umap = isl_union_map_read_from_str(ctx, str);
8026 str = umap_un_tests[i].res;
8027 res = isl_union_map_read_from_str(ctx, str);
8028 umap = umap_un_tests[i].fn(umap);
8029 equal = isl_union_map_is_equal(umap, res);
8030 isl_union_map_free(umap);
8031 isl_union_map_free(res);
8032 if (equal < 0)
8033 return isl_stat_error;
8034 if (!equal)
8035 isl_die(ctx, isl_error_unknown,
8036 "unexpected result", return isl_stat_error);
8039 return isl_stat_ok;
8042 /* Inputs for basic tests of binary operations on isl_union_map.
8043 * "fn" is the function that is being tested.
8044 * "arg1" and "arg2" are string descriptions of the inputs.
8045 * "res" is a string description of the expected result.
8047 static struct {
8048 __isl_give isl_union_map *(*fn)(__isl_take isl_union_map *umap1,
8049 __isl_take isl_union_map *umap2);
8050 const char *arg1;
8051 const char *arg2;
8052 const char *res;
8053 } umap_bin_tests[] = {
8054 { &isl_union_map_intersect,
8055 "[n] -> { A[i] -> [] : 0 <= i <= n; B[] -> [] }",
8056 "[m] -> { A[i] -> [] : 0 <= i <= m; C[] -> [] }",
8057 "[m, n] -> { A[i] -> [] : 0 <= i <= n and i <= m }" },
8058 { &isl_union_map_intersect_domain_factor_domain,
8059 "{ [A[i] -> B[i + 1]] -> C[i + 2] }",
8060 "[N] -> { B[i] -> C[N] }",
8061 "{ }" },
8062 { &isl_union_map_intersect_domain_factor_domain,
8063 "{ [A[i] -> B[i + 1]] -> C[i + 2] }",
8064 "[N] -> { A[i] -> C[N] }",
8065 "[N] -> { [A[N - 2] -> B[N - 1]] -> C[N] }" },
8066 { &isl_union_map_intersect_domain_factor_domain,
8067 "{ T[A[i] -> B[i + 1]] -> C[i + 2] }",
8068 "[N] -> { A[i] -> C[N] }",
8069 "[N] -> { T[A[N - 2] -> B[N - 1]] -> C[N] }" },
8070 { &isl_union_map_intersect_domain_factor_range,
8071 "{ [A[i] -> B[i + 1]] -> C[i + 2] }",
8072 "[N] -> { B[i] -> C[N] }",
8073 "[N] -> { [A[N - 2] -> B[N - 1]] -> C[N] }" },
8074 { &isl_union_map_intersect_domain_factor_range,
8075 "{ T[A[i] -> B[i + 1]] -> C[i + 2] }",
8076 "[N] -> { B[i] -> C[N] }",
8077 "[N] -> { T[A[N - 2] -> B[N - 1]] -> C[N] }" },
8078 { &isl_union_map_intersect_domain_factor_range,
8079 "{ [A[i] -> B[i + 1]] -> C[i + 2] }",
8080 "[N] -> { A[i] -> C[N] }",
8081 "{ }" },
8082 { &isl_union_map_intersect_range_factor_domain,
8083 "{ A[i] -> [B[i + 1] -> C[i + 2]] }",
8084 "[N] -> { A[i] -> B[N] }",
8085 "[N] -> { A[N - 1] -> [B[N] -> C[N + 1]] }" },
8086 { &isl_union_map_intersect_range_factor_domain,
8087 "{ A[i] -> T[B[i + 1] -> C[i + 2]] }",
8088 "[N] -> { A[i] -> B[N] }",
8089 "[N] -> { A[N - 1] -> T[B[N] -> C[N + 1]] }" },
8090 { &isl_union_map_intersect_range_factor_domain,
8091 "{ A[i] -> [B[i + 1] -> C[i + 2]] }",
8092 "[N] -> { A[i] -> C[N] }",
8093 "{ }" },
8094 { &isl_union_map_intersect_range_factor_range,
8095 "{ A[i] -> [B[i + 1] -> C[i + 2]] }",
8096 "[N] -> { A[i] -> C[N] }",
8097 "[N] -> { A[N - 2] -> [B[N - 1] -> C[N]] }" },
8098 { &isl_union_map_intersect_range_factor_range,
8099 "{ A[i] -> T[B[i + 1] -> C[i + 2]] }",
8100 "[N] -> { A[i] -> C[N] }",
8101 "[N] -> { A[N - 2] -> T[B[N - 1] -> C[N]] }" },
8102 { &isl_union_map_intersect_range_factor_range,
8103 "{ A[i] -> [B[i + 1] -> C[i + 2]] }",
8104 "[N] -> { A[i] -> B[N] }",
8105 "{ }" },
8108 /* Perform basic tests of binary operations on isl_union_map.
8110 static isl_stat test_bin_union_map(isl_ctx *ctx)
8112 int i;
8114 for (i = 0; i < ARRAY_SIZE(umap_bin_tests); ++i) {
8115 const char *str;
8116 isl_union_map *umap1, *umap2, *res;
8117 isl_bool equal;
8119 str = umap_bin_tests[i].arg1;
8120 umap1 = isl_union_map_read_from_str(ctx, str);
8121 str = umap_bin_tests[i].arg2;
8122 umap2 = isl_union_map_read_from_str(ctx, str);
8123 str = umap_bin_tests[i].res;
8124 res = isl_union_map_read_from_str(ctx, str);
8125 umap1 = umap_bin_tests[i].fn(umap1, umap2);
8126 equal = isl_union_map_is_equal(umap1, res);
8127 isl_union_map_free(umap1);
8128 isl_union_map_free(res);
8129 if (equal < 0)
8130 return isl_stat_error;
8131 if (!equal)
8132 isl_die(ctx, isl_error_unknown,
8133 "unexpected result", return isl_stat_error);
8136 return isl_stat_ok;
8139 /* Check that isl_union_set_contains finds space independently
8140 * of the parameters.
8142 static isl_stat test_union_set_contains(isl_ctx *ctx)
8144 const char *str;
8145 isl_bool ok;
8146 isl_space *space;
8147 isl_id *id;
8148 isl_union_set *uset;
8150 str = "[N] -> { A[0:N]; B[*,*] }";
8151 uset = isl_union_set_read_from_str(ctx, str);
8152 space = isl_space_unit(ctx);
8153 id = isl_id_alloc(ctx, "A", NULL);
8154 space = isl_space_add_named_tuple_id_ui(space, id, 1);
8155 ok = isl_union_set_contains(uset, space);
8156 isl_space_free(space);
8157 isl_union_set_free(uset);
8159 if (ok < 0)
8160 return isl_stat_error;
8161 if (!ok)
8162 isl_die(ctx, isl_error_unknown,
8163 "unexpected result", return isl_stat_error);
8165 return isl_stat_ok;
8168 /* Perform basic tests of operations on isl_union_map or isl_union_set.
8170 static int test_union_map(isl_ctx *ctx)
8172 if (test_un_union_map(ctx) < 0)
8173 return -1;
8174 if (test_bin_union_map(ctx) < 0)
8175 return -1;
8176 if (test_union_set_contains(ctx) < 0)
8177 return -1;
8178 return 0;
8181 int test_union_pw(isl_ctx *ctx)
8183 int equal;
8184 const char *str;
8185 isl_union_set *uset;
8186 isl_union_pw_qpolynomial *upwqp1, *upwqp2;
8188 str = "{ [x] -> x^2 }";
8189 upwqp1 = isl_union_pw_qpolynomial_read_from_str(ctx, str);
8190 upwqp2 = isl_union_pw_qpolynomial_copy(upwqp1);
8191 uset = isl_union_pw_qpolynomial_domain(upwqp1);
8192 upwqp1 = isl_union_pw_qpolynomial_copy(upwqp2);
8193 upwqp1 = isl_union_pw_qpolynomial_intersect_domain(upwqp1, uset);
8194 equal = isl_union_pw_qpolynomial_plain_is_equal(upwqp1, upwqp2);
8195 isl_union_pw_qpolynomial_free(upwqp1);
8196 isl_union_pw_qpolynomial_free(upwqp2);
8197 if (equal < 0)
8198 return -1;
8199 if (!equal)
8200 isl_die(ctx, isl_error_unknown, "unexpected result", return -1);
8202 return 0;
8205 /* Inputs for basic tests of functions that select
8206 * subparts of the domain of an isl_multi_union_pw_aff.
8207 * "fn" is the function that is tested.
8208 * "arg" is a string description of the input.
8209 * "res" is a string description of the expected result.
8211 struct {
8212 __isl_give isl_union_set *(*fn)(
8213 __isl_take isl_multi_union_pw_aff *mupa);
8214 const char *arg;
8215 const char *res;
8216 } un_locus_tests[] = {
8217 { &isl_multi_union_pw_aff_zero_union_set,
8218 "F[{ A[i,j] -> [i]; B[i,j] -> [i] }]",
8219 "{ A[0,j]; B[0,j] }" },
8220 { &isl_multi_union_pw_aff_zero_union_set,
8221 "F[{ A[i,j] -> [i-j]; B[i,j] -> [i-j] : i >= 0 }]",
8222 "{ A[i,i]; B[i,i] : i >= 0 }" },
8223 { &isl_multi_union_pw_aff_zero_union_set,
8224 "(F[] : { A[i,j]; B[i,i] : i >= 0 })",
8225 "{ A[i,j]; B[i,i] : i >= 0 }" },
8228 /* Perform some basic tests of functions that select
8229 * subparts of the domain of an isl_multi_union_pw_aff.
8231 static int test_un_locus(isl_ctx *ctx)
8233 int i;
8234 isl_bool ok;
8235 isl_union_set *uset, *res;
8236 isl_multi_union_pw_aff *mupa;
8238 for (i = 0; i < ARRAY_SIZE(un_locus_tests); ++i) {
8239 mupa = isl_multi_union_pw_aff_read_from_str(ctx,
8240 un_locus_tests[i].arg);
8241 res = isl_union_set_read_from_str(ctx, un_locus_tests[i].res);
8242 uset = un_locus_tests[i].fn(mupa);
8243 ok = isl_union_set_is_equal(uset, res);
8244 isl_union_set_free(uset);
8245 isl_union_set_free(res);
8246 if (ok < 0)
8247 return -1;
8248 if (!ok)
8249 isl_die(ctx, isl_error_unknown,
8250 "unexpected result", return -1);
8253 return 0;
8256 /* Inputs for basic tests of functions that select
8257 * subparts of an isl_union_map based on a relation
8258 * specified by an isl_multi_union_pw_aff.
8259 * "fn" is the function that is tested.
8260 * "arg1" and "arg2" are string descriptions of the inputs.
8261 * "res" is a string description of the expected result.
8263 struct {
8264 __isl_give isl_union_map *(*fn)(
8265 __isl_take isl_union_map *umap,
8266 __isl_take isl_multi_union_pw_aff *mupa);
8267 const char *arg1;
8268 const char *arg2;
8269 const char *res;
8270 } bin_locus_tests[] = {
8271 { &isl_union_map_eq_at_multi_union_pw_aff,
8272 "{ A[i,j] -> B[i',j'] }",
8273 "F[{ A[i,j] -> [i]; B[i,j] -> [i] }]",
8274 "{ A[i,j] -> B[i,j'] }" },
8275 { &isl_union_map_eq_at_multi_union_pw_aff,
8276 "{ A[i,j] -> B[i',j'] }",
8277 "F[{ A[i,j] -> [i]; B[i,j] -> [i] }, "
8278 "{ A[i,j] -> [j]; B[i,j] -> [j] }]",
8279 "{ A[i,j] -> B[i,j] }" },
8280 { &isl_union_map_eq_at_multi_union_pw_aff,
8281 "{ A[i,j] -> B[i',j']; A[i,j] -> C[i',j'] }",
8282 "F[{ A[i,j] -> [i]; B[i,j] -> [i] }]",
8283 "{ A[i,j] -> B[i,j'] }" },
8284 { &isl_union_map_eq_at_multi_union_pw_aff,
8285 "{ A[i,j] -> B[i',j']; A[i,j] -> C[i',j'] }",
8286 "F[{ A[i,j] -> [i]; B[i,j] -> [i]; C[i,j] -> [0] }]",
8287 "{ A[i,j] -> B[i,j']; A[0,j] -> C[i',j'] }" },
8288 { &isl_union_map_eq_at_multi_union_pw_aff,
8289 "{ A[i,j] -> B[i',j'] }",
8290 "F[{ A[i,j] -> [i] : i > j; B[i,j] -> [i] }]",
8291 "{ A[i,j] -> B[i,j'] : i > j }" },
8292 { &isl_union_map_lex_le_at_multi_union_pw_aff,
8293 "{ A[i,j] -> B[i',j'] }",
8294 "F[{ A[i,j] -> [i]; B[i,j] -> [i] }, "
8295 "{ A[i,j] -> [j]; B[i,j] -> [j] }]",
8296 "{ A[i,j] -> B[i',j'] : i,j <<= i',j' }" },
8297 { &isl_union_map_lex_lt_at_multi_union_pw_aff,
8298 "{ A[i,j] -> B[i',j'] }",
8299 "F[{ A[i,j] -> [i]; B[i,j] -> [i] }, "
8300 "{ A[i,j] -> [j]; B[i,j] -> [j] }]",
8301 "{ A[i,j] -> B[i',j'] : i,j << i',j' }" },
8302 { &isl_union_map_lex_ge_at_multi_union_pw_aff,
8303 "{ A[i,j] -> B[i',j'] }",
8304 "F[{ A[i,j] -> [i]; B[i,j] -> [i] }, "
8305 "{ A[i,j] -> [j]; B[i,j] -> [j] }]",
8306 "{ A[i,j] -> B[i',j'] : i,j >>= i',j' }" },
8307 { &isl_union_map_lex_gt_at_multi_union_pw_aff,
8308 "{ A[i,j] -> B[i',j'] }",
8309 "F[{ A[i,j] -> [i]; B[i,j] -> [i] }, "
8310 "{ A[i,j] -> [j]; B[i,j] -> [j] }]",
8311 "{ A[i,j] -> B[i',j'] : i,j >> i',j' }" },
8312 { &isl_union_map_eq_at_multi_union_pw_aff,
8313 "{ A[i,j] -> B[i',j']; A[i,j] -> C[i',j'] }",
8314 "(F[] : { A[i,j]; B[i,j] })",
8315 "{ A[i,j] -> B[i',j'] }" },
8316 { &isl_union_map_eq_at_multi_union_pw_aff,
8317 "{ A[i,j] -> B[i',j'] }",
8318 "(F[] : { A[i,j] : i > j; B[i,j] : i < j })",
8319 "{ A[i,j] -> B[i',j'] : i > j and i' < j' }" },
8320 { &isl_union_map_eq_at_multi_union_pw_aff,
8321 "[N] -> { A[i,j] -> B[i',j'] : i,i' <= N }",
8322 "(F[] : { A[i,j] : i > j; B[i,j] : i < j })",
8323 "[N] -> { A[i,j] -> B[i',j'] : i > j and i' < j' and i,i' <= N }" },
8324 { &isl_union_map_eq_at_multi_union_pw_aff,
8325 "{ A[i,j] -> B[i',j'] }",
8326 "[N] -> (F[] : { A[i,j] : i < N; B[i,j] : i < N })",
8327 "[N] -> { A[i,j] -> B[i',j'] : i,i' < N }" },
8328 { &isl_union_map_eq_at_multi_union_pw_aff,
8329 "{ A[i,j] -> B[i',j'] }",
8330 "[N] -> (F[] : { : N >= 0 })",
8331 "[N] -> { A[i,j] -> B[i',j'] : N >= 0 }" },
8334 /* Perform some basic tests of functions that select
8335 * subparts of an isl_union_map based on a relation
8336 * specified by an isl_multi_union_pw_aff.
8338 static int test_bin_locus(isl_ctx *ctx)
8340 int i;
8341 isl_bool ok;
8342 isl_union_map *umap, *res;
8343 isl_multi_union_pw_aff *mupa;
8345 for (i = 0; i < ARRAY_SIZE(bin_locus_tests); ++i) {
8346 umap = isl_union_map_read_from_str(ctx,
8347 bin_locus_tests[i].arg1);
8348 mupa = isl_multi_union_pw_aff_read_from_str(ctx,
8349 bin_locus_tests[i].arg2);
8350 res = isl_union_map_read_from_str(ctx, bin_locus_tests[i].res);
8351 umap = bin_locus_tests[i].fn(umap, mupa);
8352 ok = isl_union_map_is_equal(umap, res);
8353 isl_union_map_free(umap);
8354 isl_union_map_free(res);
8355 if (ok < 0)
8356 return -1;
8357 if (!ok)
8358 isl_die(ctx, isl_error_unknown,
8359 "unexpected result", return -1);
8362 return 0;
8365 /* Inputs for basic tests of functions that determine
8366 * the part of the domain where two isl_multi_aff objects
8367 * related to each other in a specific way.
8368 * "fn" is the function that is being tested.
8369 * "arg1" and "arg2" are string descriptions of the inputs.
8370 * "res" is a string description of the expected result.
8372 static struct {
8373 __isl_give isl_set *(*fn)(__isl_take isl_multi_aff *ma1,
8374 __isl_take isl_multi_aff *ma2);
8375 const char *arg1;
8376 const char *arg2;
8377 const char *res;
8378 } bin_locus_ma_tests[] = {
8379 { &isl_multi_aff_lex_le_set, "{ [] }", "{ [] }", "{ : }" },
8380 { &isl_multi_aff_lex_lt_set, "{ [] }", "{ [] }", "{ : false }" },
8381 { &isl_multi_aff_lex_le_set,
8382 "{ A[i] -> [i] }", "{ A[i] -> [0] }",
8383 "{ A[i] : i <= 0 }" },
8384 { &isl_multi_aff_lex_lt_set,
8385 "{ A[i] -> [i] }", "{ A[i] -> [0] }",
8386 "{ A[i] : i < 0 }" },
8387 { &isl_multi_aff_lex_le_set,
8388 "{ A[i] -> [i, i] }", "{ A[i] -> [0, 0] }",
8389 "{ A[i] : i <= 0 }" },
8390 { &isl_multi_aff_lex_le_set,
8391 "{ A[i] -> [i, 0] }", "{ A[i] -> [0, 0] }",
8392 "{ A[i] : i <= 0 }" },
8393 { &isl_multi_aff_lex_le_set,
8394 "{ A[i] -> [i, 1] }", "{ A[i] -> [0, 0] }",
8395 "{ A[i] : i < 0 }" },
8398 /* Perform some basic tests of functions that determine
8399 * the part of the domain where two isl_multi_aff objects
8400 * related to each other in a specific way.
8402 static isl_stat test_bin_locus_ma(isl_ctx *ctx)
8404 int i;
8406 for (i = 0; i < ARRAY_SIZE(bin_locus_ma_tests); ++i) {
8407 const char *str;
8408 isl_bool ok;
8409 isl_multi_aff *ma1, *ma2;
8410 isl_set *set, *res;
8412 str = bin_locus_ma_tests[i].arg1;
8413 ma1 = isl_multi_aff_read_from_str(ctx, str);
8414 str = bin_locus_ma_tests[i].arg2;
8415 ma2 = isl_multi_aff_read_from_str(ctx, str);
8416 res = isl_set_read_from_str(ctx, bin_locus_ma_tests[i].res);
8417 set = bin_locus_ma_tests[i].fn(ma1, ma2);
8418 ok = isl_set_is_equal(set, res);
8419 isl_set_free(set);
8420 isl_set_free(res);
8421 if (ok < 0)
8422 return isl_stat_error;
8423 if (!ok)
8424 isl_die(ctx, isl_error_unknown,
8425 "unexpected result", return isl_stat_error);
8428 return isl_stat_ok;
8431 /* Perform basic locus tests.
8433 static int test_locus(isl_ctx *ctx)
8435 if (test_un_locus(ctx) < 0)
8436 return -1;
8437 if (test_bin_locus(ctx) < 0)
8438 return -1;
8439 if (test_bin_locus_ma(ctx) < 0)
8440 return -1;
8441 return 0;
8444 /* Test that isl_union_pw_qpolynomial_eval picks up the function
8445 * defined over the correct domain space.
8447 static int test_eval_1(isl_ctx *ctx)
8449 const char *str;
8450 isl_point *pnt;
8451 isl_set *set;
8452 isl_union_pw_qpolynomial *upwqp;
8453 isl_val *v;
8454 int cmp;
8456 str = "{ A[x] -> x^2; B[x] -> -x^2 }";
8457 upwqp = isl_union_pw_qpolynomial_read_from_str(ctx, str);
8458 str = "{ A[6] }";
8459 set = isl_set_read_from_str(ctx, str);
8460 pnt = isl_set_sample_point(set);
8461 v = isl_union_pw_qpolynomial_eval(upwqp, pnt);
8462 cmp = isl_val_cmp_si(v, 36);
8463 isl_val_free(v);
8465 if (!v)
8466 return -1;
8467 if (cmp != 0)
8468 isl_die(ctx, isl_error_unknown, "unexpected value", return -1);
8470 return 0;
8473 /* Check that isl_qpolynomial_eval handles getting called on a void point.
8475 static int test_eval_2(isl_ctx *ctx)
8477 const char *str;
8478 isl_point *pnt;
8479 isl_set *set;
8480 isl_qpolynomial *qp;
8481 isl_val *v;
8482 isl_bool ok;
8484 str = "{ A[x] -> [x] }";
8485 qp = isl_qpolynomial_from_aff(isl_aff_read_from_str(ctx, str));
8486 str = "{ A[x] : false }";
8487 set = isl_set_read_from_str(ctx, str);
8488 pnt = isl_set_sample_point(set);
8489 v = isl_qpolynomial_eval(qp, pnt);
8490 ok = isl_val_is_nan(v);
8491 isl_val_free(v);
8493 if (ok < 0)
8494 return -1;
8495 if (!ok)
8496 isl_die(ctx, isl_error_unknown, "expecting NaN", return -1);
8498 return 0;
8501 /* Check that a polynomial (without local variables) can be evaluated
8502 * in a rational point.
8504 static isl_stat test_eval_3(isl_ctx *ctx)
8506 isl_pw_qpolynomial *pwqp;
8507 isl_point *pnt;
8508 isl_val *v;
8509 isl_stat r;
8511 pwqp = isl_pw_qpolynomial_read_from_str(ctx, "{ [x] -> x^2 }");
8512 pnt = isl_point_zero(isl_pw_qpolynomial_get_domain_space(pwqp));
8513 v = isl_val_read_from_str(ctx, "1/2");
8514 pnt = isl_point_set_coordinate_val(pnt, isl_dim_set, 0, v);
8515 v = isl_pw_qpolynomial_eval(pwqp, pnt);
8516 r = val_check_equal(v, "1/4");
8517 isl_val_free(v);
8519 return r;
8522 /* Inputs for isl_pw_aff_eval test.
8523 * "f" is the affine function.
8524 * "p" is the point where the function should be evaluated.
8525 * "res" is the expected result.
8527 struct {
8528 const char *f;
8529 const char *p;
8530 const char *res;
8531 } aff_eval_tests[] = {
8532 { "{ [i] -> [2 * i] }", "{ [4] }", "8" },
8533 { "{ [i] -> [2 * i] }", "{ [x] : false }", "NaN" },
8534 { "{ [i] -> [i + floor(i/2) + floor(i/3)] }", "{ [0] }", "0" },
8535 { "{ [i] -> [i + floor(i/2) + floor(i/3)] }", "{ [1] }", "1" },
8536 { "{ [i] -> [i + floor(i/2) + floor(i/3)] }", "{ [2] }", "3" },
8537 { "{ [i] -> [i + floor(i/2) + floor(i/3)] }", "{ [3] }", "5" },
8538 { "{ [i] -> [i + floor(i/2) + floor(i/3)] }", "{ [4] }", "7" },
8539 { "{ [i] -> [floor((3 * floor(i/2))/5)] }", "{ [0] }", "0" },
8540 { "{ [i] -> [floor((3 * floor(i/2))/5)] }", "{ [1] }", "0" },
8541 { "{ [i] -> [floor((3 * floor(i/2))/5)] }", "{ [2] }", "0" },
8542 { "{ [i] -> [floor((3 * floor(i/2))/5)] }", "{ [3] }", "0" },
8543 { "{ [i] -> [floor((3 * floor(i/2))/5)] }", "{ [4] }", "1" },
8544 { "{ [i] -> [floor((3 * floor(i/2))/5)] }", "{ [6] }", "1" },
8545 { "{ [i] -> [floor((3 * floor(i/2))/5)] }", "{ [8] }", "2" },
8546 { "{ [i] -> [i] : i > 0; [i] -> [-i] : i < 0 }", "{ [4] }", "4" },
8547 { "{ [i] -> [i] : i > 0; [i] -> [-i] : i < 0 }", "{ [-2] }", "2" },
8548 { "{ [i] -> [i] : i > 0; [i] -> [-i] : i < 0 }", "{ [0] }", "NaN" },
8549 { "[N] -> { [2 * N] }", "[N] -> { : N = 4 }", "8" },
8550 { "{ [i, j] -> [(i + j)/2] }", "{ [1, 1] }", "1" },
8551 { "{ [i, j] -> [(i + j)/2] }", "{ [1, 2] }", "3/2" },
8552 { "{ [i] -> [i] : i mod 2 = 0 }", "{ [4] }", "4" },
8553 { "{ [i] -> [i] : i mod 2 = 0 }", "{ [3] }", "NaN" },
8554 { "{ [i] -> [i] : i mod 2 = 0 }", "{ [x] : false }", "NaN" },
8557 /* Perform basic isl_pw_aff_eval tests.
8559 static int test_eval_aff(isl_ctx *ctx)
8561 int i;
8563 for (i = 0; i < ARRAY_SIZE(aff_eval_tests); ++i) {
8564 isl_stat r;
8565 isl_pw_aff *pa;
8566 isl_set *set;
8567 isl_point *pnt;
8568 isl_val *v;
8570 pa = isl_pw_aff_read_from_str(ctx, aff_eval_tests[i].f);
8571 set = isl_set_read_from_str(ctx, aff_eval_tests[i].p);
8572 pnt = isl_set_sample_point(set);
8573 v = isl_pw_aff_eval(pa, pnt);
8574 r = val_check_equal(v, aff_eval_tests[i].res);
8575 isl_val_free(v);
8576 if (r < 0)
8577 return -1;
8579 return 0;
8582 /* Perform basic evaluation tests.
8584 static int test_eval(isl_ctx *ctx)
8586 if (test_eval_1(ctx) < 0)
8587 return -1;
8588 if (test_eval_2(ctx) < 0)
8589 return -1;
8590 if (test_eval_3(ctx) < 0)
8591 return -1;
8592 if (test_eval_aff(ctx) < 0)
8593 return -1;
8594 return 0;
8597 /* Descriptions of sets that are tested for reparsing after printing.
8599 const char *output_tests[] = {
8600 "{ [1, y] : 0 <= y <= 1; [x, -x] : 0 <= x <= 1 }",
8601 "{ [x] : 1 = 0 }",
8602 "{ [x] : false }",
8603 "{ [x] : x mod 2 = 0 }",
8604 "{ [x] : x mod 2 = 1 }",
8605 "{ [x, y] : x mod 2 = 0 and 3*floor(y/2) < x }",
8606 "{ [y, x] : x mod 2 = 0 and 3*floor(y/2) < x }",
8607 "{ [x, y] : x mod 2 = 0 and 3*floor(y/2) = x + y }",
8608 "{ [y, x] : x mod 2 = 0 and 3*floor(y/2) = x + y }",
8609 "[n] -> { [y, x] : 2*((x + 2y) mod 3) = n }",
8610 "{ [x, y] : (2*floor(x/3) + 3*floor(y/4)) mod 5 = x }",
8613 /* Check that printing a set and reparsing a set from the printed output
8614 * results in the same set.
8616 static int test_output_set(isl_ctx *ctx)
8618 int i;
8619 char *str;
8620 isl_set *set1, *set2;
8621 isl_bool equal;
8623 for (i = 0; i < ARRAY_SIZE(output_tests); ++i) {
8624 set1 = isl_set_read_from_str(ctx, output_tests[i]);
8625 str = isl_set_to_str(set1);
8626 set2 = isl_set_read_from_str(ctx, str);
8627 free(str);
8628 equal = isl_set_is_equal(set1, set2);
8629 isl_set_free(set1);
8630 isl_set_free(set2);
8631 if (equal < 0)
8632 return -1;
8633 if (!equal)
8634 isl_die(ctx, isl_error_unknown,
8635 "parsed output not the same", return -1);
8638 return 0;
8641 /* Check that an isl_multi_aff is printed using a consistent space.
8643 static isl_stat test_output_ma(isl_ctx *ctx)
8645 char *str;
8646 isl_bool equal;
8647 isl_aff *aff;
8648 isl_multi_aff *ma, *ma2;
8650 ma = isl_multi_aff_read_from_str(ctx, "{ [a, b] -> [a + b] }");
8651 aff = isl_aff_read_from_str(ctx, "{ [c, d] -> [c + d] }");
8652 ma = isl_multi_aff_set_aff(ma, 0, aff);
8653 str = isl_multi_aff_to_str(ma);
8654 ma2 = isl_multi_aff_read_from_str(ctx, str);
8655 free(str);
8656 equal = isl_multi_aff_plain_is_equal(ma, ma2);
8657 isl_multi_aff_free(ma2);
8658 isl_multi_aff_free(ma);
8660 if (equal < 0)
8661 return isl_stat_error;
8662 if (!equal)
8663 isl_die(ctx, isl_error_unknown, "bad conversion",
8664 return isl_stat_error);
8666 return isl_stat_ok;
8669 /* Check that an isl_multi_pw_aff is printed using a consistent space.
8671 static isl_stat test_output_mpa(isl_ctx *ctx)
8673 char *str;
8674 isl_bool equal;
8675 isl_pw_aff *pa;
8676 isl_multi_pw_aff *mpa, *mpa2;
8678 mpa = isl_multi_pw_aff_read_from_str(ctx, "{ [a, b] -> [a + b] }");
8679 pa = isl_pw_aff_read_from_str(ctx, "{ [c, d] -> [c + d] }");
8680 mpa = isl_multi_pw_aff_set_pw_aff(mpa, 0, pa);
8681 str = isl_multi_pw_aff_to_str(mpa);
8682 mpa2 = isl_multi_pw_aff_read_from_str(ctx, str);
8683 free(str);
8684 equal = isl_multi_pw_aff_plain_is_equal(mpa, mpa2);
8685 isl_multi_pw_aff_free(mpa2);
8686 isl_multi_pw_aff_free(mpa);
8688 if (equal < 0)
8689 return isl_stat_error;
8690 if (!equal)
8691 isl_die(ctx, isl_error_unknown, "bad conversion",
8692 return isl_stat_error);
8694 return isl_stat_ok;
8697 int test_output(isl_ctx *ctx)
8699 char *s;
8700 const char *str;
8701 isl_pw_aff *pa;
8702 isl_printer *p;
8703 int equal;
8705 if (test_output_set(ctx) < 0)
8706 return -1;
8707 if (test_output_ma(ctx) < 0)
8708 return -1;
8709 if (test_output_mpa(ctx) < 0)
8710 return -1;
8712 str = "[x] -> { [1] : x % 4 <= 2; [2] : x = 3 }";
8713 pa = isl_pw_aff_read_from_str(ctx, str);
8715 p = isl_printer_to_str(ctx);
8716 p = isl_printer_set_output_format(p, ISL_FORMAT_C);
8717 p = isl_printer_print_pw_aff(p, pa);
8718 s = isl_printer_get_str(p);
8719 isl_printer_free(p);
8720 isl_pw_aff_free(pa);
8721 if (!s)
8722 equal = -1;
8723 else
8724 equal = !strcmp(s, "4 * floord(x, 4) + 2 >= x ? 1 : 2");
8725 free(s);
8726 if (equal < 0)
8727 return -1;
8728 if (!equal)
8729 isl_die(ctx, isl_error_unknown, "unexpected result", return -1);
8731 return 0;
8734 int test_sample(isl_ctx *ctx)
8736 const char *str;
8737 isl_basic_set *bset1, *bset2;
8738 int empty, subset;
8740 str = "{ [a, b, c, d, e, f, g, h, i, j, k] : "
8741 "3i >= 1073741823b - c - 1073741823e + f and c >= 0 and "
8742 "3i >= -1 + 3221225466b + c + d - 3221225466e - f and "
8743 "2e >= a - b and 3e <= 2a and 3k <= -a and f <= -1 + a and "
8744 "3i <= 4 - a + 4b + 2c - e - 2f and 3k <= -a + c - f and "
8745 "3h >= -2 + a and 3g >= -3 - a and 3k >= -2 - a and "
8746 "3i >= -2 - a - 2c + 3e + 2f and 3h <= a + c - f and "
8747 "3h >= a + 2147483646b + 2c - 2147483646e - 2f and "
8748 "3g <= -1 - a and 3i <= 1 + c + d - f and a <= 1073741823 and "
8749 "f >= 1 - a + 1073741822b + c + d - 1073741822e and "
8750 "3i >= 1 + 2b - 2c + e + 2f + 3g and "
8751 "1073741822f <= 1073741822 - a + 1073741821b + 1073741822c +"
8752 "d - 1073741821e and "
8753 "3j <= 3 - a + 3b and 3g <= -2 - 2b + c + d - e - f and "
8754 "3j >= 1 - a + b + 2e and "
8755 "3f >= -3 + a + 3221225462b + 3c + d - 3221225465e and "
8756 "3i <= 4 - a + 4b - e and "
8757 "f <= 1073741822 + 1073741822b - 1073741822e and 3h <= a and "
8758 "f >= 0 and 2e <= 4 - a + 5b - d and 2e <= a - b + d and "
8759 "c <= -1 + a and 3i >= -2 - a + 3e and "
8760 "1073741822e <= 1073741823 - a + 1073741822b + c and "
8761 "3g >= -4 + 3221225464b + 3c + d - 3221225467e - 3f and "
8762 "3i >= -1 + 3221225466b + 3c + d - 3221225466e - 3f and "
8763 "1073741823e >= 1 + 1073741823b - d and "
8764 "3i >= 1073741823b + c - 1073741823e - f and "
8765 "3i >= 1 + 2b + e + 3g }";
8766 bset1 = isl_basic_set_read_from_str(ctx, str);
8767 bset2 = isl_basic_set_sample(isl_basic_set_copy(bset1));
8768 empty = isl_basic_set_is_empty(bset2);
8769 subset = isl_basic_set_is_subset(bset2, bset1);
8770 isl_basic_set_free(bset1);
8771 isl_basic_set_free(bset2);
8772 if (empty < 0 || subset < 0)
8773 return -1;
8774 if (empty)
8775 isl_die(ctx, isl_error_unknown, "point not found", return -1);
8776 if (!subset)
8777 isl_die(ctx, isl_error_unknown, "bad point found", return -1);
8779 return 0;
8782 /* Perform a projection on a basic set that is known to be empty
8783 * but that has not been assigned a canonical representation.
8784 * Earlier versions of isl would run into a stack overflow
8785 * on this example.
8787 static int test_empty_projection(isl_ctx *ctx)
8789 const char *str;
8790 isl_bool empty;
8791 isl_basic_set *bset;
8793 str = "{ [a, b, c, d, e, f, g, h] : 5f = 1 + 4a - b + 5c - d - 2e and "
8794 "3h = 2 + b + c and 14c >= 9 - 3a + 25b and "
8795 "4c <= 50 - 3a + 23b and 6b <= -39 + a and "
8796 "9g >= -6 + 3a + b + c and e < a + b - 2d and "
8797 "7d >= -5 + 2a + 2b and 5g >= -14 + a - 4b + d + 2e and "
8798 "9g <= -28 - 5b - 2c + 3d + 6e }";
8799 bset = isl_basic_set_read_from_str(ctx, str);
8800 empty = isl_basic_set_is_empty(bset);
8801 bset = isl_basic_set_params(bset);
8802 isl_basic_set_free(bset);
8804 if (empty < 0)
8805 return -1;
8807 return 0;
8810 int test_fixed_power(isl_ctx *ctx)
8812 const char *str;
8813 isl_map *map;
8814 isl_val *exp;
8815 int equal;
8817 str = "{ [i] -> [i + 1] }";
8818 map = isl_map_read_from_str(ctx, str);
8819 exp = isl_val_int_from_si(ctx, 23);
8820 map = isl_map_fixed_power_val(map, exp);
8821 equal = map_check_equal(map, "{ [i] -> [i + 23] }");
8822 isl_map_free(map);
8823 if (equal < 0)
8824 return -1;
8826 return 0;
8829 int test_slice(isl_ctx *ctx)
8831 const char *str;
8832 isl_map *map;
8833 int equal;
8835 str = "{ [i] -> [j] }";
8836 map = isl_map_read_from_str(ctx, str);
8837 map = isl_map_equate(map, isl_dim_in, 0, isl_dim_out, 0);
8838 equal = map_check_equal(map, "{ [i] -> [i] }");
8839 isl_map_free(map);
8840 if (equal < 0)
8841 return -1;
8843 str = "{ [i] -> [j] }";
8844 map = isl_map_read_from_str(ctx, str);
8845 map = isl_map_equate(map, isl_dim_in, 0, isl_dim_in, 0);
8846 equal = map_check_equal(map, "{ [i] -> [j] }");
8847 isl_map_free(map);
8848 if (equal < 0)
8849 return -1;
8851 str = "{ [i] -> [j] }";
8852 map = isl_map_read_from_str(ctx, str);
8853 map = isl_map_oppose(map, isl_dim_in, 0, isl_dim_out, 0);
8854 equal = map_check_equal(map, "{ [i] -> [-i] }");
8855 isl_map_free(map);
8856 if (equal < 0)
8857 return -1;
8859 str = "{ [i] -> [j] }";
8860 map = isl_map_read_from_str(ctx, str);
8861 map = isl_map_oppose(map, isl_dim_in, 0, isl_dim_in, 0);
8862 equal = map_check_equal(map, "{ [0] -> [j] }");
8863 isl_map_free(map);
8864 if (equal < 0)
8865 return -1;
8867 str = "{ [i] -> [j] }";
8868 map = isl_map_read_from_str(ctx, str);
8869 map = isl_map_order_gt(map, isl_dim_in, 0, isl_dim_out, 0);
8870 equal = map_check_equal(map, "{ [i] -> [j] : i > j }");
8871 isl_map_free(map);
8872 if (equal < 0)
8873 return -1;
8875 str = "{ [i] -> [j] }";
8876 map = isl_map_read_from_str(ctx, str);
8877 map = isl_map_order_gt(map, isl_dim_in, 0, isl_dim_in, 0);
8878 equal = map_check_equal(map, "{ [i] -> [j] : false }");
8879 isl_map_free(map);
8880 if (equal < 0)
8881 return -1;
8883 return 0;
8886 int test_eliminate(isl_ctx *ctx)
8888 const char *str;
8889 isl_map *map;
8890 int equal;
8892 str = "{ [i] -> [j] : i = 2j }";
8893 map = isl_map_read_from_str(ctx, str);
8894 map = isl_map_eliminate(map, isl_dim_out, 0, 1);
8895 equal = map_check_equal(map, "{ [i] -> [j] : exists a : i = 2a }");
8896 isl_map_free(map);
8897 if (equal < 0)
8898 return -1;
8900 return 0;
8903 /* Check basic functionality of isl_map_deltas_map.
8905 static int test_deltas_map(isl_ctx *ctx)
8907 const char *str;
8908 isl_map *map;
8909 int equal;
8911 str = "{ A[i] -> A[i + 1] }";
8912 map = isl_map_read_from_str(ctx, str);
8913 map = isl_map_deltas_map(map);
8914 equal = map_check_equal(map, "{ [A[i] -> A[i + 1]] -> A[1] }");
8915 isl_map_free(map);
8916 if (equal < 0)
8917 return -1;
8919 return 0;
8922 /* Check that isl_set_dim_residue_class detects that the values of j
8923 * in the set below are all odd and that it does not detect any spurious
8924 * strides.
8926 static int test_residue_class(isl_ctx *ctx)
8928 const char *str;
8929 isl_set *set;
8930 isl_int m, r;
8931 isl_stat res;
8933 str = "{ [i,j] : j = 4 i + 1 and 0 <= i <= 100; "
8934 "[i,j] : j = 4 i + 3 and 500 <= i <= 600 }";
8935 set = isl_set_read_from_str(ctx, str);
8936 isl_int_init(m);
8937 isl_int_init(r);
8938 res = isl_set_dim_residue_class(set, 1, &m, &r);
8939 if (res >= 0 &&
8940 (isl_int_cmp_si(m, 2) != 0 || isl_int_cmp_si(r, 1) != 0))
8941 isl_die(ctx, isl_error_unknown, "incorrect residue class",
8942 res = isl_stat_error);
8943 isl_int_clear(r);
8944 isl_int_clear(m);
8945 isl_set_free(set);
8947 return res;
8950 static int test_align_parameters_1(isl_ctx *ctx)
8952 const char *str;
8953 isl_space *space;
8954 isl_multi_aff *ma1, *ma2;
8955 int equal;
8957 str = "{ A[B[] -> C[]] -> D[E[] -> F[]] }";
8958 ma1 = isl_multi_aff_read_from_str(ctx, str);
8960 space = isl_space_params_alloc(ctx, 1);
8961 space = isl_space_set_dim_name(space, isl_dim_param, 0, "N");
8962 ma1 = isl_multi_aff_align_params(ma1, space);
8964 str = "[N] -> { A[B[] -> C[]] -> D[E[] -> F[]] }";
8965 ma2 = isl_multi_aff_read_from_str(ctx, str);
8967 equal = isl_multi_aff_plain_is_equal(ma1, ma2);
8969 isl_multi_aff_free(ma1);
8970 isl_multi_aff_free(ma2);
8972 if (equal < 0)
8973 return -1;
8974 if (!equal)
8975 isl_die(ctx, isl_error_unknown,
8976 "result not as expected", return -1);
8978 return 0;
8981 /* Check the isl_multi_*_from_*_list operation in case inputs
8982 * have unaligned parameters.
8983 * In particular, older versions of isl would simply fail
8984 * (without printing any error message).
8986 static isl_stat test_align_parameters_2(isl_ctx *ctx)
8988 isl_space *space;
8989 isl_map *map;
8990 isl_aff *aff;
8991 isl_multi_aff *ma;
8993 map = isl_map_read_from_str(ctx, "{ A[] -> M[x] }");
8994 space = isl_map_get_space(map);
8995 isl_map_free(map);
8997 aff = isl_aff_read_from_str(ctx, "[N] -> { A[] -> [N] }");
8998 ma = isl_multi_aff_from_aff_list(space, isl_aff_list_from_aff(aff));
8999 isl_multi_aff_free(ma);
9001 if (!ma)
9002 return isl_stat_error;
9003 return isl_stat_ok;
9006 /* Perform basic parameter alignment tests.
9008 static int test_align_parameters(isl_ctx *ctx)
9010 if (test_align_parameters_1(ctx) < 0)
9011 return -1;
9012 if (test_align_parameters_2(ctx) < 0)
9013 return -1;
9015 return 0;
9018 /* Check that isl_*_drop_unused_params actually drops the unused parameters
9019 * by comparing the result using isl_*_plain_is_equal.
9020 * Note that this assumes that isl_*_plain_is_equal does not consider
9021 * objects that only differ by unused parameters to be equal.
9023 int test_drop_unused_parameters(isl_ctx *ctx)
9025 const char *str_with, *str_without;
9026 isl_basic_set *bset1, *bset2;
9027 isl_set *set1, *set2;
9028 isl_pw_aff *pwa1, *pwa2;
9029 int equal;
9031 str_with = "[n, m, o] -> { [m] }";
9032 str_without = "[m] -> { [m] }";
9034 bset1 = isl_basic_set_read_from_str(ctx, str_with);
9035 bset2 = isl_basic_set_read_from_str(ctx, str_without);
9036 bset1 = isl_basic_set_drop_unused_params(bset1);
9037 equal = isl_basic_set_plain_is_equal(bset1, bset2);
9038 isl_basic_set_free(bset1);
9039 isl_basic_set_free(bset2);
9041 if (equal < 0)
9042 return -1;
9043 if (!equal)
9044 isl_die(ctx, isl_error_unknown,
9045 "result not as expected", return -1);
9047 set1 = isl_set_read_from_str(ctx, str_with);
9048 set2 = isl_set_read_from_str(ctx, str_without);
9049 set1 = isl_set_drop_unused_params(set1);
9050 equal = isl_set_plain_is_equal(set1, set2);
9051 isl_set_free(set1);
9052 isl_set_free(set2);
9054 if (equal < 0)
9055 return -1;
9056 if (!equal)
9057 isl_die(ctx, isl_error_unknown,
9058 "result not as expected", return -1);
9060 pwa1 = isl_pw_aff_read_from_str(ctx, str_with);
9061 pwa2 = isl_pw_aff_read_from_str(ctx, str_without);
9062 pwa1 = isl_pw_aff_drop_unused_params(pwa1);
9063 equal = isl_pw_aff_plain_is_equal(pwa1, pwa2);
9064 isl_pw_aff_free(pwa1);
9065 isl_pw_aff_free(pwa2);
9067 if (equal < 0)
9068 return -1;
9069 if (!equal)
9070 isl_die(ctx, isl_error_unknown,
9071 "result not as expected", return -1);
9073 return 0;
9076 static int test_list(isl_ctx *ctx)
9078 isl_id *a, *b, *c, *d, *id;
9079 isl_id_list *list;
9080 isl_size n;
9081 int ok;
9083 a = isl_id_alloc(ctx, "a", NULL);
9084 b = isl_id_alloc(ctx, "b", NULL);
9085 c = isl_id_alloc(ctx, "c", NULL);
9086 d = isl_id_alloc(ctx, "d", NULL);
9088 list = isl_id_list_alloc(ctx, 4);
9089 list = isl_id_list_add(list, b);
9090 list = isl_id_list_insert(list, 0, a);
9091 list = isl_id_list_add(list, c);
9092 list = isl_id_list_add(list, d);
9093 list = isl_id_list_drop(list, 1, 1);
9095 n = isl_id_list_n_id(list);
9096 if (n < 0)
9097 return -1;
9098 if (n != 3) {
9099 isl_id_list_free(list);
9100 isl_die(ctx, isl_error_unknown,
9101 "unexpected number of elements in list", return -1);
9104 id = isl_id_list_get_id(list, 0);
9105 ok = id == a;
9106 isl_id_free(id);
9107 id = isl_id_list_get_id(list, 1);
9108 ok = ok && id == c;
9109 isl_id_free(id);
9110 id = isl_id_list_get_id(list, 2);
9111 ok = ok && id == d;
9112 isl_id_free(id);
9114 isl_id_list_free(list);
9116 if (!ok)
9117 isl_die(ctx, isl_error_unknown,
9118 "unexpected elements in list", return -1);
9120 return 0;
9123 /* Check the conversion from an isl_multi_aff to an isl_basic_set.
9125 static isl_stat test_ma_conversion(isl_ctx *ctx)
9127 const char *str;
9128 isl_bool equal;
9129 isl_multi_aff *ma;
9130 isl_basic_set *bset1, *bset2;
9132 str = "[N] -> { A[0, N + 1] }";
9133 ma = isl_multi_aff_read_from_str(ctx, str);
9134 bset1 = isl_basic_set_read_from_str(ctx, str);
9135 bset2 = isl_basic_set_from_multi_aff(ma);
9136 equal = isl_basic_set_is_equal(bset1, bset2);
9137 isl_basic_set_free(bset1);
9138 isl_basic_set_free(bset2);
9139 if (equal < 0)
9140 return isl_stat_error;
9141 if (!equal)
9142 isl_die(ctx, isl_error_unknown, "bad conversion",
9143 return isl_stat_error);
9144 return isl_stat_ok;
9147 const char *set_conversion_tests[] = {
9148 "[N] -> { [i] : N - 1 <= 2 i <= N }",
9149 "[N] -> { [i] : exists a : i = 4 a and N - 1 <= i <= N }",
9150 "[N] -> { [i,j] : exists a : i = 4 a and N - 1 <= i, 2j <= N }",
9151 "[N] -> { [[i]->[j]] : exists a : i = 4 a and N - 1 <= i, 2j <= N }",
9152 "[N] -> { [3*floor(N/2) + 5*floor(N/3)] }",
9153 "[a, b] -> { [c, d] : (4*floor((-a + c)/4) = -a + c and "
9154 "32*floor((-b + d)/32) = -b + d and 5 <= c <= 8 and "
9155 "-3 + c <= d <= 28 + c) }",
9158 /* Check that converting from isl_set to isl_pw_multi_aff and back
9159 * to isl_set produces the original isl_set.
9161 static int test_set_conversion(isl_ctx *ctx)
9163 int i;
9164 const char *str;
9165 isl_set *set1, *set2;
9166 isl_pw_multi_aff *pma;
9167 int equal;
9169 for (i = 0; i < ARRAY_SIZE(set_conversion_tests); ++i) {
9170 str = set_conversion_tests[i];
9171 set1 = isl_set_read_from_str(ctx, str);
9172 pma = isl_pw_multi_aff_from_set(isl_set_copy(set1));
9173 set2 = isl_set_from_pw_multi_aff(pma);
9174 equal = isl_set_is_equal(set1, set2);
9175 isl_set_free(set1);
9176 isl_set_free(set2);
9178 if (equal < 0)
9179 return -1;
9180 if (!equal)
9181 isl_die(ctx, isl_error_unknown, "bad conversion",
9182 return -1);
9185 return 0;
9188 const char *conversion_tests[] = {
9189 "{ [a, b, c, d] -> s0[a, b, e, f] : "
9190 "exists (e0 = [(a - 2c)/3], e1 = [(-4 + b - 5d)/9], "
9191 "e2 = [(-d + f)/9]: 3e0 = a - 2c and 9e1 = -4 + b - 5d and "
9192 "9e2 = -d + f and f >= 0 and f <= 8 and 9e >= -5 - 2a and "
9193 "9e <= -2 - 2a) }",
9194 "{ [a, b] -> [c] : exists (e0 = floor((-a - b + c)/5): "
9195 "5e0 = -a - b + c and c >= -a and c <= 4 - a) }",
9196 "{ [a, b] -> [c] : exists d : 18 * d = -3 - a + 2c and 1 <= c <= 3 }",
9199 /* Check that converting from isl_map to isl_pw_multi_aff and back
9200 * to isl_map produces the original isl_map.
9202 static int test_map_conversion(isl_ctx *ctx)
9204 int i;
9205 isl_map *map1, *map2;
9206 isl_pw_multi_aff *pma;
9207 int equal;
9209 for (i = 0; i < ARRAY_SIZE(conversion_tests); ++i) {
9210 map1 = isl_map_read_from_str(ctx, conversion_tests[i]);
9211 pma = isl_pw_multi_aff_from_map(isl_map_copy(map1));
9212 map2 = isl_map_from_pw_multi_aff(pma);
9213 equal = isl_map_is_equal(map1, map2);
9214 isl_map_free(map1);
9215 isl_map_free(map2);
9217 if (equal < 0)
9218 return -1;
9219 if (!equal)
9220 isl_die(ctx, isl_error_unknown, "bad conversion",
9221 return -1);
9224 return 0;
9227 /* Descriptions of isl_pw_multi_aff objects for testing conversion
9228 * to isl_multi_pw_aff and back.
9230 const char *mpa_conversion_tests[] = {
9231 "{ [x] -> A[x] }",
9232 "{ [x] -> A[x] : x >= 0 }",
9233 "{ [x] -> A[x] : x >= 0; [x] -> A[-x] : x < 0 }",
9234 "{ [x] -> A[x, x + 1] }",
9235 "{ [x] -> A[] }",
9236 "{ [x] -> A[] : x >= 0 }",
9239 /* Check that conversion from isl_pw_multi_aff to isl_multi_pw_aff and
9240 * back to isl_pw_multi_aff preserves the original meaning.
9242 static int test_mpa_conversion(isl_ctx *ctx)
9244 int i;
9245 isl_pw_multi_aff *pma1, *pma2;
9246 isl_multi_pw_aff *mpa;
9247 int equal;
9249 for (i = 0; i < ARRAY_SIZE(mpa_conversion_tests); ++i) {
9250 const char *str;
9251 str = mpa_conversion_tests[i];
9252 pma1 = isl_pw_multi_aff_read_from_str(ctx, str);
9253 pma2 = isl_pw_multi_aff_copy(pma1);
9254 mpa = isl_multi_pw_aff_from_pw_multi_aff(pma1);
9255 pma1 = isl_pw_multi_aff_from_multi_pw_aff(mpa);
9256 equal = isl_pw_multi_aff_plain_is_equal(pma1, pma2);
9257 isl_pw_multi_aff_free(pma1);
9258 isl_pw_multi_aff_free(pma2);
9260 if (equal < 0)
9261 return -1;
9262 if (!equal)
9263 isl_die(ctx, isl_error_unknown, "bad conversion",
9264 return -1);
9267 return 0;
9270 /* Descriptions of union maps that should be convertible
9271 * to an isl_multi_union_pw_aff.
9273 const char *umap_mupa_conversion_tests[] = {
9274 "{ [a, b, c, d] -> s0[a, b, e, f] : "
9275 "exists (e0 = [(a - 2c)/3], e1 = [(-4 + b - 5d)/9], "
9276 "e2 = [(-d + f)/9]: 3e0 = a - 2c and 9e1 = -4 + b - 5d and "
9277 "9e2 = -d + f and f >= 0 and f <= 8 and 9e >= -5 - 2a and "
9278 "9e <= -2 - 2a) }",
9279 "{ [a, b] -> [c] : exists (e0 = floor((-a - b + c)/5): "
9280 "5e0 = -a - b + c and c >= -a and c <= 4 - a) }",
9281 "{ [a, b] -> [c] : exists d : 18 * d = -3 - a + 2c and 1 <= c <= 3 }",
9282 "{ A[] -> B[0]; C[] -> B[1] }",
9283 "{ A[] -> B[]; C[] -> B[] }",
9286 /* Check that converting from isl_union_map to isl_multi_union_pw_aff and back
9287 * to isl_union_map produces the original isl_union_map.
9289 static int test_union_map_mupa_conversion(isl_ctx *ctx)
9291 int i;
9292 isl_union_map *umap1, *umap2;
9293 isl_multi_union_pw_aff *mupa;
9294 int equal;
9296 for (i = 0; i < ARRAY_SIZE(umap_mupa_conversion_tests); ++i) {
9297 const char *str;
9298 str = umap_mupa_conversion_tests[i];
9299 umap1 = isl_union_map_read_from_str(ctx, str);
9300 umap2 = isl_union_map_copy(umap1);
9301 mupa = isl_multi_union_pw_aff_from_union_map(umap2);
9302 umap2 = isl_union_map_from_multi_union_pw_aff(mupa);
9303 equal = isl_union_map_is_equal(umap1, umap2);
9304 isl_union_map_free(umap1);
9305 isl_union_map_free(umap2);
9307 if (equal < 0)
9308 return -1;
9309 if (!equal)
9310 isl_die(ctx, isl_error_unknown, "bad conversion",
9311 return -1);
9314 return 0;
9317 static int test_conversion(isl_ctx *ctx)
9319 if (test_ma_conversion(ctx) < 0)
9320 return -1;
9321 if (test_set_conversion(ctx) < 0)
9322 return -1;
9323 if (test_map_conversion(ctx) < 0)
9324 return -1;
9325 if (test_mpa_conversion(ctx) < 0)
9326 return -1;
9327 if (test_union_map_mupa_conversion(ctx) < 0)
9328 return -1;
9329 return 0;
9332 /* Check that isl_basic_map_curry does not modify input.
9334 static int test_curry(isl_ctx *ctx)
9336 const char *str;
9337 isl_basic_map *bmap1, *bmap2;
9338 int equal;
9340 str = "{ [A[] -> B[]] -> C[] }";
9341 bmap1 = isl_basic_map_read_from_str(ctx, str);
9342 bmap2 = isl_basic_map_curry(isl_basic_map_copy(bmap1));
9343 equal = isl_basic_map_is_equal(bmap1, bmap2);
9344 isl_basic_map_free(bmap1);
9345 isl_basic_map_free(bmap2);
9347 if (equal < 0)
9348 return -1;
9349 if (equal)
9350 isl_die(ctx, isl_error_unknown,
9351 "curried map should not be equal to original",
9352 return -1);
9354 return 0;
9357 struct {
9358 const char *ma1;
9359 const char *ma;
9360 const char *res;
9361 } pullback_tests[] = {
9362 { "{ B[i,j] -> C[i + 2j] }" , "{ A[a,b] -> B[b,a] }",
9363 "{ A[a,b] -> C[b + 2a] }" },
9364 { "{ B[i] -> C[2i] }", "{ A[a] -> B[(a)/2] }", "{ A[a] -> C[a] }" },
9365 { "{ B[i] -> C[(i)/2] }", "{ A[a] -> B[2a] }", "{ A[a] -> C[a] }" },
9366 { "{ B[i] -> C[(i)/2] }", "{ A[a] -> B[(a)/3] }",
9367 "{ A[a] -> C[(a)/6] }" },
9368 { "{ B[i] -> C[2i] }", "{ A[a] -> B[5a] }", "{ A[a] -> C[10a] }" },
9369 { "{ B[i] -> C[2i] }", "{ A[a] -> B[(a)/3] }",
9370 "{ A[a] -> C[(2a)/3] }" },
9371 { "{ B[i,j] -> C[i + j] }", "{ A[a] -> B[a,a] }", "{ A[a] -> C[2a] }"},
9372 { "{ B[a] -> C[a,a] }", "{ A[i,j] -> B[i + j] }",
9373 "{ A[i,j] -> C[i + j, i + j] }"},
9374 { "{ B[i] -> C[([i/2])] }", "{ B[5] }", "{ C[2] }" },
9375 { "[n] -> { B[i,j] -> C[([i/2]) + 2j] }",
9376 "[n] -> { B[n,[n/3]] }", "[n] -> { C[([n/2]) + 2*[n/3]] }", },
9377 { "{ [i, j] -> [floor((i)/4) + floor((2*i+j)/5)] }",
9378 "{ [i, j] -> [floor((i)/3), j] }",
9379 "{ [i, j] -> [(floor((i)/12) + floor((j + 2*floor((i)/3))/5))] }" },
9382 static int test_pullback(isl_ctx *ctx)
9384 int i;
9385 isl_multi_aff *ma1, *ma2;
9386 isl_multi_aff *ma;
9387 int equal;
9389 for (i = 0; i < ARRAY_SIZE(pullback_tests); ++i) {
9390 ma1 = isl_multi_aff_read_from_str(ctx, pullback_tests[i].ma1);
9391 ma = isl_multi_aff_read_from_str(ctx, pullback_tests[i].ma);
9392 ma2 = isl_multi_aff_read_from_str(ctx, pullback_tests[i].res);
9393 ma1 = isl_multi_aff_pullback_multi_aff(ma1, ma);
9394 equal = isl_multi_aff_plain_is_equal(ma1, ma2);
9395 isl_multi_aff_free(ma1);
9396 isl_multi_aff_free(ma2);
9397 if (equal < 0)
9398 return -1;
9399 if (!equal)
9400 isl_die(ctx, isl_error_unknown, "bad pullback",
9401 return -1);
9404 return 0;
9407 /* Check that negation is printed correctly and that equal expressions
9408 * are correctly identified.
9410 static int test_ast(isl_ctx *ctx)
9412 isl_ast_expr *expr, *expr1, *expr2, *expr3;
9413 char *str;
9414 int ok, equal;
9416 expr1 = isl_ast_expr_from_id(isl_id_alloc(ctx, "A", NULL));
9417 expr2 = isl_ast_expr_from_id(isl_id_alloc(ctx, "B", NULL));
9418 expr = isl_ast_expr_add(expr1, expr2);
9419 expr2 = isl_ast_expr_copy(expr);
9420 expr = isl_ast_expr_neg(expr);
9421 expr2 = isl_ast_expr_neg(expr2);
9422 equal = isl_ast_expr_is_equal(expr, expr2);
9423 str = isl_ast_expr_to_C_str(expr);
9424 ok = str ? !strcmp(str, "-(A + B)") : -1;
9425 free(str);
9426 isl_ast_expr_free(expr);
9427 isl_ast_expr_free(expr2);
9429 if (ok < 0 || equal < 0)
9430 return -1;
9431 if (!equal)
9432 isl_die(ctx, isl_error_unknown,
9433 "equal expressions not considered equal", return -1);
9434 if (!ok)
9435 isl_die(ctx, isl_error_unknown,
9436 "isl_ast_expr printed incorrectly", return -1);
9438 expr1 = isl_ast_expr_from_id(isl_id_alloc(ctx, "A", NULL));
9439 expr2 = isl_ast_expr_from_id(isl_id_alloc(ctx, "B", NULL));
9440 expr = isl_ast_expr_add(expr1, expr2);
9441 expr3 = isl_ast_expr_from_id(isl_id_alloc(ctx, "C", NULL));
9442 expr = isl_ast_expr_sub(expr3, expr);
9443 str = isl_ast_expr_to_C_str(expr);
9444 ok = str ? !strcmp(str, "C - (A + B)") : -1;
9445 free(str);
9446 isl_ast_expr_free(expr);
9448 if (ok < 0)
9449 return -1;
9450 if (!ok)
9451 isl_die(ctx, isl_error_unknown,
9452 "isl_ast_expr printed incorrectly", return -1);
9454 return 0;
9457 /* Check that isl_ast_build_expr_from_set returns a valid expression
9458 * for an empty set. Note that isl_ast_build_expr_from_set getting
9459 * called on an empty set probably indicates a bug in the caller.
9461 static int test_ast_build(isl_ctx *ctx)
9463 isl_set *set;
9464 isl_ast_build *build;
9465 isl_ast_expr *expr;
9467 set = isl_set_universe(isl_space_params_alloc(ctx, 0));
9468 build = isl_ast_build_from_context(set);
9470 set = isl_set_empty(isl_space_params_alloc(ctx, 0));
9471 expr = isl_ast_build_expr_from_set(build, set);
9473 isl_ast_expr_free(expr);
9474 isl_ast_build_free(build);
9476 if (!expr)
9477 return -1;
9479 return 0;
9482 /* Internal data structure for before_for and after_for callbacks.
9484 * depth is the current depth
9485 * before is the number of times before_for has been called
9486 * after is the number of times after_for has been called
9488 struct isl_test_codegen_data {
9489 int depth;
9490 int before;
9491 int after;
9494 /* This function is called before each for loop in the AST generated
9495 * from test_ast_gen1.
9497 * Increment the number of calls and the depth.
9498 * Check that the space returned by isl_ast_build_get_schedule_space
9499 * matches the target space of the schedule returned by
9500 * isl_ast_build_get_schedule.
9501 * Return an isl_id that is checked by the corresponding call
9502 * to after_for.
9504 static __isl_give isl_id *before_for(__isl_keep isl_ast_build *build,
9505 void *user)
9507 struct isl_test_codegen_data *data = user;
9508 isl_ctx *ctx;
9509 isl_space *space;
9510 isl_union_map *schedule;
9511 isl_union_set *uset;
9512 isl_set *set;
9513 isl_bool empty;
9514 isl_size n;
9515 char name[] = "d0";
9517 ctx = isl_ast_build_get_ctx(build);
9519 if (data->before >= 3)
9520 isl_die(ctx, isl_error_unknown,
9521 "unexpected number of for nodes", return NULL);
9522 if (data->depth < 0 || data->depth >= 2)
9523 isl_die(ctx, isl_error_unknown,
9524 "unexpected depth", return NULL);
9526 snprintf(name, sizeof(name), "d%d", data->depth);
9527 data->before++;
9528 data->depth++;
9530 schedule = isl_ast_build_get_schedule(build);
9531 uset = isl_union_map_range(schedule);
9532 n = isl_union_set_n_set(uset);
9533 if (n != 1) {
9534 isl_union_set_free(uset);
9535 if (n < 0)
9536 return NULL;
9537 isl_die(ctx, isl_error_unknown,
9538 "expecting single range space", return NULL);
9541 space = isl_ast_build_get_schedule_space(build);
9542 set = isl_union_set_extract_set(uset, space);
9543 isl_union_set_free(uset);
9544 empty = isl_set_is_empty(set);
9545 isl_set_free(set);
9547 if (empty < 0)
9548 return NULL;
9549 if (empty)
9550 isl_die(ctx, isl_error_unknown,
9551 "spaces don't match", return NULL);
9553 return isl_id_alloc(ctx, name, NULL);
9556 /* This function is called after each for loop in the AST generated
9557 * from test_ast_gen1.
9559 * Increment the number of calls and decrement the depth.
9560 * Check that the annotation attached to the node matches
9561 * the isl_id returned by the corresponding call to before_for.
9563 static __isl_give isl_ast_node *after_for(__isl_take isl_ast_node *node,
9564 __isl_keep isl_ast_build *build, void *user)
9566 struct isl_test_codegen_data *data = user;
9567 isl_id *id;
9568 const char *name;
9569 int valid;
9571 data->after++;
9572 data->depth--;
9574 if (data->after > data->before)
9575 isl_die(isl_ast_node_get_ctx(node), isl_error_unknown,
9576 "mismatch in number of for nodes",
9577 return isl_ast_node_free(node));
9579 id = isl_ast_node_get_annotation(node);
9580 if (!id)
9581 isl_die(isl_ast_node_get_ctx(node), isl_error_unknown,
9582 "missing annotation", return isl_ast_node_free(node));
9584 name = isl_id_get_name(id);
9585 valid = name && atoi(name + 1) == data->depth;
9586 isl_id_free(id);
9588 if (!valid)
9589 isl_die(isl_ast_node_get_ctx(node), isl_error_unknown,
9590 "wrong annotation", return isl_ast_node_free(node));
9592 return node;
9595 /* Check that the before_each_for and after_each_for callbacks
9596 * are called for each for loop in the generated code,
9597 * that they are called in the right order and that the isl_id
9598 * returned from the before_each_for callback is attached to
9599 * the isl_ast_node passed to the corresponding after_each_for call.
9601 static int test_ast_gen1(isl_ctx *ctx)
9603 const char *str;
9604 isl_set *set;
9605 isl_union_map *schedule;
9606 isl_ast_build *build;
9607 isl_ast_node *tree;
9608 struct isl_test_codegen_data data;
9610 str = "[N] -> { : N >= 10 }";
9611 set = isl_set_read_from_str(ctx, str);
9612 str = "[N] -> { A[i,j] -> S[8,i,3,j] : 0 <= i,j <= N; "
9613 "B[i,j] -> S[8,j,9,i] : 0 <= i,j <= N }";
9614 schedule = isl_union_map_read_from_str(ctx, str);
9616 data.before = 0;
9617 data.after = 0;
9618 data.depth = 0;
9619 build = isl_ast_build_from_context(set);
9620 build = isl_ast_build_set_before_each_for(build,
9621 &before_for, &data);
9622 build = isl_ast_build_set_after_each_for(build,
9623 &after_for, &data);
9624 tree = isl_ast_build_node_from_schedule_map(build, schedule);
9625 isl_ast_build_free(build);
9626 if (!tree)
9627 return -1;
9629 isl_ast_node_free(tree);
9631 if (data.before != 3 || data.after != 3)
9632 isl_die(ctx, isl_error_unknown,
9633 "unexpected number of for nodes", return -1);
9635 return 0;
9638 /* Check that the AST generator handles domains that are integrally disjoint
9639 * but not rationally disjoint.
9641 static int test_ast_gen2(isl_ctx *ctx)
9643 const char *str;
9644 isl_set *set;
9645 isl_union_map *schedule;
9646 isl_union_map *options;
9647 isl_ast_build *build;
9648 isl_ast_node *tree;
9650 str = "{ A[i,j] -> [i,j] : 0 <= i,j <= 1 }";
9651 schedule = isl_union_map_read_from_str(ctx, str);
9652 set = isl_set_universe(isl_space_params_alloc(ctx, 0));
9653 build = isl_ast_build_from_context(set);
9655 str = "{ [i,j] -> atomic[1] : i + j = 1; [i,j] -> unroll[1] : i = j }";
9656 options = isl_union_map_read_from_str(ctx, str);
9657 build = isl_ast_build_set_options(build, options);
9658 tree = isl_ast_build_node_from_schedule_map(build, schedule);
9659 isl_ast_build_free(build);
9660 if (!tree)
9661 return -1;
9662 isl_ast_node_free(tree);
9664 return 0;
9667 /* Increment *user on each call.
9669 static __isl_give isl_ast_node *count_domains(__isl_take isl_ast_node *node,
9670 __isl_keep isl_ast_build *build, void *user)
9672 int *n = user;
9674 (*n)++;
9676 return node;
9679 /* Test that unrolling tries to minimize the number of instances.
9680 * In particular, for the schedule given below, make sure it generates
9681 * 3 nodes (rather than 101).
9683 static int test_ast_gen3(isl_ctx *ctx)
9685 const char *str;
9686 isl_set *set;
9687 isl_union_map *schedule;
9688 isl_union_map *options;
9689 isl_ast_build *build;
9690 isl_ast_node *tree;
9691 int n_domain = 0;
9693 str = "[n] -> { A[i] -> [i] : 0 <= i <= 100 and n <= i <= n + 2 }";
9694 schedule = isl_union_map_read_from_str(ctx, str);
9695 set = isl_set_universe(isl_space_params_alloc(ctx, 0));
9697 str = "{ [i] -> unroll[0] }";
9698 options = isl_union_map_read_from_str(ctx, str);
9700 build = isl_ast_build_from_context(set);
9701 build = isl_ast_build_set_options(build, options);
9702 build = isl_ast_build_set_at_each_domain(build,
9703 &count_domains, &n_domain);
9704 tree = isl_ast_build_node_from_schedule_map(build, schedule);
9705 isl_ast_build_free(build);
9706 if (!tree)
9707 return -1;
9709 isl_ast_node_free(tree);
9711 if (n_domain != 3)
9712 isl_die(ctx, isl_error_unknown,
9713 "unexpected number of for nodes", return -1);
9715 return 0;
9718 /* Check that if the ast_build_exploit_nested_bounds options is set,
9719 * we do not get an outer if node in the generated AST,
9720 * while we do get such an outer if node if the options is not set.
9722 static int test_ast_gen4(isl_ctx *ctx)
9724 const char *str;
9725 isl_set *set;
9726 isl_union_map *schedule;
9727 isl_ast_build *build;
9728 isl_ast_node *tree;
9729 enum isl_ast_node_type type;
9730 int enb;
9732 enb = isl_options_get_ast_build_exploit_nested_bounds(ctx);
9733 str = "[N,M] -> { A[i,j] -> [i,j] : 0 <= i <= N and 0 <= j <= M }";
9735 isl_options_set_ast_build_exploit_nested_bounds(ctx, 1);
9737 schedule = isl_union_map_read_from_str(ctx, str);
9738 set = isl_set_universe(isl_space_params_alloc(ctx, 0));
9739 build = isl_ast_build_from_context(set);
9740 tree = isl_ast_build_node_from_schedule_map(build, schedule);
9741 isl_ast_build_free(build);
9742 if (!tree)
9743 return -1;
9745 type = isl_ast_node_get_type(tree);
9746 isl_ast_node_free(tree);
9748 if (type == isl_ast_node_if)
9749 isl_die(ctx, isl_error_unknown,
9750 "not expecting if node", return -1);
9752 isl_options_set_ast_build_exploit_nested_bounds(ctx, 0);
9754 schedule = isl_union_map_read_from_str(ctx, str);
9755 set = isl_set_universe(isl_space_params_alloc(ctx, 0));
9756 build = isl_ast_build_from_context(set);
9757 tree = isl_ast_build_node_from_schedule_map(build, schedule);
9758 isl_ast_build_free(build);
9759 if (!tree)
9760 return -1;
9762 type = isl_ast_node_get_type(tree);
9763 isl_ast_node_free(tree);
9765 if (type != isl_ast_node_if)
9766 isl_die(ctx, isl_error_unknown,
9767 "expecting if node", return -1);
9769 isl_options_set_ast_build_exploit_nested_bounds(ctx, enb);
9771 return 0;
9774 /* This function is called for each leaf in the AST generated
9775 * from test_ast_gen5.
9777 * We finalize the AST generation by extending the outer schedule
9778 * with a zero-dimensional schedule. If this results in any for loops,
9779 * then this means that we did not pass along enough information
9780 * about the outer schedule to the inner AST generation.
9782 static __isl_give isl_ast_node *create_leaf(__isl_take isl_ast_build *build,
9783 void *user)
9785 isl_union_map *schedule, *extra;
9786 isl_ast_node *tree;
9788 schedule = isl_ast_build_get_schedule(build);
9789 extra = isl_union_map_copy(schedule);
9790 extra = isl_union_map_from_domain(isl_union_map_domain(extra));
9791 schedule = isl_union_map_range_product(schedule, extra);
9792 tree = isl_ast_build_node_from_schedule_map(build, schedule);
9793 isl_ast_build_free(build);
9795 if (!tree)
9796 return NULL;
9798 if (isl_ast_node_get_type(tree) == isl_ast_node_for)
9799 isl_die(isl_ast_node_get_ctx(tree), isl_error_unknown,
9800 "code should not contain any for loop",
9801 return isl_ast_node_free(tree));
9803 return tree;
9806 /* Check that we do not lose any information when going back and
9807 * forth between internal and external schedule.
9809 * In particular, we create an AST where we unroll the only
9810 * non-constant dimension in the schedule. We therefore do
9811 * not expect any for loops in the AST. However, older versions
9812 * of isl would not pass along enough information about the outer
9813 * schedule when performing an inner code generation from a create_leaf
9814 * callback, resulting in the inner code generation producing a for loop.
9816 static int test_ast_gen5(isl_ctx *ctx)
9818 const char *str;
9819 isl_set *set;
9820 isl_union_map *schedule, *options;
9821 isl_ast_build *build;
9822 isl_ast_node *tree;
9824 str = "{ A[] -> [1, 1, 2]; B[i] -> [1, i, 0] : i >= 1 and i <= 2 }";
9825 schedule = isl_union_map_read_from_str(ctx, str);
9827 str = "{ [a, b, c] -> unroll[1] : exists (e0 = [(a)/4]: "
9828 "4e0 >= -1 + a - b and 4e0 <= -2 + a + b) }";
9829 options = isl_union_map_read_from_str(ctx, str);
9831 set = isl_set_universe(isl_space_params_alloc(ctx, 0));
9832 build = isl_ast_build_from_context(set);
9833 build = isl_ast_build_set_options(build, options);
9834 build = isl_ast_build_set_create_leaf(build, &create_leaf, NULL);
9835 tree = isl_ast_build_node_from_schedule_map(build, schedule);
9836 isl_ast_build_free(build);
9837 isl_ast_node_free(tree);
9838 if (!tree)
9839 return -1;
9841 return 0;
9844 /* Check that the expression
9846 * [n] -> { [n/2] : n <= 0 and n % 2 = 0; [0] : n > 0 }
9848 * is not combined into
9850 * min(n/2, 0)
9852 * as this would result in n/2 being evaluated in parts of
9853 * the definition domain where n is not a multiple of 2.
9855 static int test_ast_expr(isl_ctx *ctx)
9857 const char *str;
9858 isl_pw_aff *pa;
9859 isl_ast_build *build;
9860 isl_ast_expr *expr;
9861 int min_max;
9862 int is_min;
9864 min_max = isl_options_get_ast_build_detect_min_max(ctx);
9865 isl_options_set_ast_build_detect_min_max(ctx, 1);
9867 str = "[n] -> { [n/2] : n <= 0 and n % 2 = 0; [0] : n > 0 }";
9868 pa = isl_pw_aff_read_from_str(ctx, str);
9869 build = isl_ast_build_alloc(ctx);
9870 expr = isl_ast_build_expr_from_pw_aff(build, pa);
9871 is_min = isl_ast_expr_get_type(expr) == isl_ast_expr_op &&
9872 isl_ast_expr_get_op_type(expr) == isl_ast_expr_op_min;
9873 isl_ast_build_free(build);
9874 isl_ast_expr_free(expr);
9876 isl_options_set_ast_build_detect_min_max(ctx, min_max);
9878 if (!expr)
9879 return -1;
9880 if (is_min)
9881 isl_die(ctx, isl_error_unknown,
9882 "expressions should not be combined", return -1);
9884 return 0;
9887 static int test_ast_gen(isl_ctx *ctx)
9889 if (test_ast_gen1(ctx) < 0)
9890 return -1;
9891 if (test_ast_gen2(ctx) < 0)
9892 return -1;
9893 if (test_ast_gen3(ctx) < 0)
9894 return -1;
9895 if (test_ast_gen4(ctx) < 0)
9896 return -1;
9897 if (test_ast_gen5(ctx) < 0)
9898 return -1;
9899 if (test_ast_expr(ctx) < 0)
9900 return -1;
9901 return 0;
9904 /* Check if dropping output dimensions from an isl_pw_multi_aff
9905 * works properly.
9907 static int test_pw_multi_aff(isl_ctx *ctx)
9909 const char *str;
9910 isl_pw_multi_aff *pma1, *pma2;
9911 int equal;
9913 str = "{ [i,j] -> [i+j, 4i-j] }";
9914 pma1 = isl_pw_multi_aff_read_from_str(ctx, str);
9915 str = "{ [i,j] -> [4i-j] }";
9916 pma2 = isl_pw_multi_aff_read_from_str(ctx, str);
9918 pma1 = isl_pw_multi_aff_drop_dims(pma1, isl_dim_out, 0, 1);
9920 equal = isl_pw_multi_aff_plain_is_equal(pma1, pma2);
9922 isl_pw_multi_aff_free(pma1);
9923 isl_pw_multi_aff_free(pma2);
9924 if (equal < 0)
9925 return -1;
9926 if (!equal)
9927 isl_die(ctx, isl_error_unknown,
9928 "expressions not equal", return -1);
9930 return 0;
9933 /* Check that we can properly parse multi piecewise affine expressions
9934 * where the piecewise affine expressions have different domains.
9936 static int test_multi_pw_aff_1(isl_ctx *ctx)
9938 const char *str;
9939 isl_set *dom, *dom2;
9940 isl_multi_pw_aff *mpa1, *mpa2;
9941 isl_pw_aff *pa;
9942 int equal;
9943 int equal_domain;
9945 mpa1 = isl_multi_pw_aff_read_from_str(ctx, "{ [i] -> [i] }");
9946 dom = isl_set_read_from_str(ctx, "{ [i] : i > 0 }");
9947 mpa1 = isl_multi_pw_aff_intersect_domain(mpa1, dom);
9948 mpa2 = isl_multi_pw_aff_read_from_str(ctx, "{ [i] -> [2i] }");
9949 mpa2 = isl_multi_pw_aff_flat_range_product(mpa1, mpa2);
9950 str = "{ [i] -> [(i : i > 0), 2i] }";
9951 mpa1 = isl_multi_pw_aff_read_from_str(ctx, str);
9953 equal = isl_multi_pw_aff_plain_is_equal(mpa1, mpa2);
9955 pa = isl_multi_pw_aff_get_pw_aff(mpa1, 0);
9956 dom = isl_pw_aff_domain(pa);
9957 pa = isl_multi_pw_aff_get_pw_aff(mpa1, 1);
9958 dom2 = isl_pw_aff_domain(pa);
9959 equal_domain = isl_set_is_equal(dom, dom2);
9961 isl_set_free(dom);
9962 isl_set_free(dom2);
9963 isl_multi_pw_aff_free(mpa1);
9964 isl_multi_pw_aff_free(mpa2);
9966 if (equal < 0)
9967 return -1;
9968 if (!equal)
9969 isl_die(ctx, isl_error_unknown,
9970 "expressions not equal", return -1);
9972 if (equal_domain < 0)
9973 return -1;
9974 if (equal_domain)
9975 isl_die(ctx, isl_error_unknown,
9976 "domains unexpectedly equal", return -1);
9978 return 0;
9981 /* Check that the dimensions in the explicit domain
9982 * of a multi piecewise affine expression are properly
9983 * taken into account.
9985 static int test_multi_pw_aff_2(isl_ctx *ctx)
9987 const char *str;
9988 isl_bool involves1, involves2, involves3, equal;
9989 isl_multi_pw_aff *mpa, *mpa1, *mpa2;
9991 str = "{ A[x,y] -> B[] : x >= y }";
9992 mpa = isl_multi_pw_aff_read_from_str(ctx, str);
9993 involves1 = isl_multi_pw_aff_involves_dims(mpa, isl_dim_in, 0, 2);
9994 mpa1 = isl_multi_pw_aff_copy(mpa);
9996 mpa = isl_multi_pw_aff_insert_dims(mpa, isl_dim_in, 0, 1);
9997 involves2 = isl_multi_pw_aff_involves_dims(mpa, isl_dim_in, 0, 1);
9998 involves3 = isl_multi_pw_aff_involves_dims(mpa, isl_dim_in, 1, 2);
9999 str = "{ [a,x,y] -> B[] : x >= y }";
10000 mpa2 = isl_multi_pw_aff_read_from_str(ctx, str);
10001 equal = isl_multi_pw_aff_plain_is_equal(mpa, mpa2);
10002 isl_multi_pw_aff_free(mpa2);
10004 mpa = isl_multi_pw_aff_drop_dims(mpa, isl_dim_in, 0, 1);
10005 mpa = isl_multi_pw_aff_set_tuple_name(mpa, isl_dim_in, "A");
10006 if (equal >= 0 && equal)
10007 equal = isl_multi_pw_aff_plain_is_equal(mpa, mpa1);
10008 isl_multi_pw_aff_free(mpa1);
10009 isl_multi_pw_aff_free(mpa);
10011 if (involves1 < 0 || involves2 < 0 || involves3 < 0 || equal < 0)
10012 return -1;
10013 if (!equal)
10014 isl_die(ctx, isl_error_unknown,
10015 "incorrect result of dimension insertion/removal",
10016 return isl_stat_error);
10017 if (!involves1 || involves2 || !involves3)
10018 isl_die(ctx, isl_error_unknown,
10019 "incorrect characterization of involved dimensions",
10020 return isl_stat_error);
10022 return 0;
10025 /* Check that isl_multi_union_pw_aff_multi_val_on_domain
10026 * sets the explicit domain of a zero-dimensional result,
10027 * such that it can be converted to an isl_union_map.
10029 static isl_stat test_multi_pw_aff_3(isl_ctx *ctx)
10031 isl_space *space;
10032 isl_union_set *dom;
10033 isl_multi_val *mv;
10034 isl_multi_union_pw_aff *mupa;
10035 isl_union_map *umap;
10037 dom = isl_union_set_read_from_str(ctx, "{ A[]; B[] }");
10038 space = isl_union_set_get_space(dom);
10039 mv = isl_multi_val_zero(isl_space_set_from_params(space));
10040 mupa = isl_multi_union_pw_aff_multi_val_on_domain(dom, mv);
10041 umap = isl_union_map_from_multi_union_pw_aff(mupa);
10042 isl_union_map_free(umap);
10043 if (!umap)
10044 return isl_stat_error;
10046 return isl_stat_ok;
10049 /* String descriptions of boxes that
10050 * are used for reconstructing box maps from their lower and upper bounds.
10052 static const char *multi_pw_aff_box_tests[] = {
10053 "{ A[x, y] -> [] : x + y >= 0 }",
10054 "[N] -> { A[x, y] -> [x] : x + y <= N }",
10055 "[N] -> { A[x, y] -> [x : y] : x + y <= N }",
10058 /* Check that map representations of boxes can be reconstructed
10059 * from their lower and upper bounds.
10061 static isl_stat test_multi_pw_aff_box(isl_ctx *ctx)
10063 int i;
10065 for (i = 0; i < ARRAY_SIZE(multi_pw_aff_box_tests); ++i) {
10066 const char *str;
10067 isl_bool equal;
10068 isl_map *map, *box;
10069 isl_multi_pw_aff *min, *max;
10071 str = multi_pw_aff_box_tests[i];
10072 map = isl_map_read_from_str(ctx, str);
10073 min = isl_map_min_multi_pw_aff(isl_map_copy(map));
10074 max = isl_map_max_multi_pw_aff(isl_map_copy(map));
10075 box = isl_map_universe(isl_map_get_space(map));
10076 box = isl_map_lower_bound_multi_pw_aff(box, min);
10077 box = isl_map_upper_bound_multi_pw_aff(box, max);
10078 equal = isl_map_is_equal(map, box);
10079 isl_map_free(map);
10080 isl_map_free(box);
10081 if (equal < 0)
10082 return isl_stat_error;
10083 if (!equal)
10084 isl_die(ctx, isl_error_unknown,
10085 "unexpected result", return isl_stat_error);
10088 return isl_stat_ok;
10091 /* Perform some tests on multi piecewise affine expressions.
10093 static int test_multi_pw_aff(isl_ctx *ctx)
10095 if (test_multi_pw_aff_1(ctx) < 0)
10096 return -1;
10097 if (test_multi_pw_aff_2(ctx) < 0)
10098 return -1;
10099 if (test_multi_pw_aff_3(ctx) < 0)
10100 return -1;
10101 if (test_multi_pw_aff_box(ctx) < 0)
10102 return -1;
10103 return 0;
10106 /* This is a regression test for a bug where isl_basic_map_simplify
10107 * would end up in an infinite loop. In particular, we construct
10108 * an empty basic set that is not obviously empty.
10109 * isl_basic_set_is_empty marks the basic set as empty.
10110 * After projecting out i3, the variable can be dropped completely,
10111 * but isl_basic_map_simplify refrains from doing so if the basic set
10112 * is empty and would end up in an infinite loop if it didn't test
10113 * explicitly for empty basic maps in the outer loop.
10115 static int test_simplify_1(isl_ctx *ctx)
10117 const char *str;
10118 isl_basic_set *bset;
10119 int empty;
10121 str = "{ [i0, i1, i2, i3] : i0 >= -2 and 6i2 <= 4 + i0 + 5i1 and "
10122 "i2 <= 22 and 75i2 <= 111 + 13i0 + 60i1 and "
10123 "25i2 >= 38 + 6i0 + 20i1 and i0 <= -1 and i2 >= 20 and "
10124 "i3 >= i2 }";
10125 bset = isl_basic_set_read_from_str(ctx, str);
10126 empty = isl_basic_set_is_empty(bset);
10127 bset = isl_basic_set_project_out(bset, isl_dim_set, 3, 1);
10128 isl_basic_set_free(bset);
10129 if (!bset)
10130 return -1;
10131 if (!empty)
10132 isl_die(ctx, isl_error_unknown,
10133 "basic set should be empty", return -1);
10135 return 0;
10138 /* Check that the equality in the set description below
10139 * is simplified away.
10141 static int test_simplify_2(isl_ctx *ctx)
10143 const char *str;
10144 isl_basic_set *bset;
10145 isl_bool universe;
10147 str = "{ [a] : exists e0, e1: 32e1 = 31 + 31a + 31e0 }";
10148 bset = isl_basic_set_read_from_str(ctx, str);
10149 universe = isl_basic_set_plain_is_universe(bset);
10150 isl_basic_set_free(bset);
10152 if (universe < 0)
10153 return -1;
10154 if (!universe)
10155 isl_die(ctx, isl_error_unknown,
10156 "equality not simplified away", return -1);
10157 return 0;
10160 /* Some simplification tests.
10162 static int test_simplify(isl_ctx *ctx)
10164 if (test_simplify_1(ctx) < 0)
10165 return -1;
10166 if (test_simplify_2(ctx) < 0)
10167 return -1;
10168 return 0;
10171 /* This is a regression test for a bug where isl_tab_basic_map_partial_lexopt
10172 * with gbr context would fail to disable the use of the shifted tableau
10173 * when transferring equalities for the input to the context, resulting
10174 * in invalid sample values.
10176 static int test_partial_lexmin(isl_ctx *ctx)
10178 const char *str;
10179 isl_basic_set *bset;
10180 isl_basic_map *bmap;
10181 isl_map *map;
10183 str = "{ [1, b, c, 1 - c] -> [e] : 2e <= -c and 2e >= -3 + c }";
10184 bmap = isl_basic_map_read_from_str(ctx, str);
10185 str = "{ [a, b, c, d] : c <= 1 and 2d >= 6 - 4b - c }";
10186 bset = isl_basic_set_read_from_str(ctx, str);
10187 map = isl_basic_map_partial_lexmin(bmap, bset, NULL);
10188 isl_map_free(map);
10190 if (!map)
10191 return -1;
10193 return 0;
10196 /* Check that the variable compression performed on the existentially
10197 * quantified variables inside isl_basic_set_compute_divs is not confused
10198 * by the implicit equalities among the parameters.
10200 static int test_compute_divs(isl_ctx *ctx)
10202 const char *str;
10203 isl_basic_set *bset;
10204 isl_set *set;
10206 str = "[a, b, c, d, e] -> { [] : exists (e0: 2d = b and a <= 124 and "
10207 "b <= 2046 and b >= 0 and b <= 60 + 64a and 2e >= b + 2c and "
10208 "2e >= b and 2e <= 1 + b and 2e <= 1 + b + 2c and "
10209 "32768e0 >= -124 + a and 2097152e0 <= 60 + 64a - b) }";
10210 bset = isl_basic_set_read_from_str(ctx, str);
10211 set = isl_basic_set_compute_divs(bset);
10212 isl_set_free(set);
10213 if (!set)
10214 return -1;
10216 return 0;
10219 /* Check that isl_schedule_get_map is not confused by a schedule tree
10220 * with divergent filter node parameters, as can result from a call
10221 * to isl_schedule_intersect_domain.
10223 static int test_schedule_tree(isl_ctx *ctx)
10225 const char *str;
10226 isl_union_set *uset;
10227 isl_schedule *sched1, *sched2;
10228 isl_union_map *umap;
10230 uset = isl_union_set_read_from_str(ctx, "{ A[i] }");
10231 sched1 = isl_schedule_from_domain(uset);
10232 uset = isl_union_set_read_from_str(ctx, "{ B[] }");
10233 sched2 = isl_schedule_from_domain(uset);
10235 sched1 = isl_schedule_sequence(sched1, sched2);
10236 str = "[n] -> { A[i] : 0 <= i < n; B[] }";
10237 uset = isl_union_set_read_from_str(ctx, str);
10238 sched1 = isl_schedule_intersect_domain(sched1, uset);
10239 umap = isl_schedule_get_map(sched1);
10240 isl_schedule_free(sched1);
10241 isl_union_map_free(umap);
10242 if (!umap)
10243 return -1;
10245 return 0;
10248 /* Check that a zero-dimensional prefix schedule keeps track
10249 * of the domain and outer filters.
10251 static int test_schedule_tree_prefix(isl_ctx *ctx)
10253 const char *str;
10254 isl_bool equal;
10255 isl_union_set *uset;
10256 isl_union_set_list *filters;
10257 isl_multi_union_pw_aff *mupa, *mupa2;
10258 isl_schedule_node *node;
10260 str = "{ S1[i,j] : 0 <= i,j < 10; S2[i,j] : 0 <= i,j < 10 }";
10261 uset = isl_union_set_read_from_str(ctx, str);
10262 node = isl_schedule_node_from_domain(uset);
10263 node = isl_schedule_node_child(node, 0);
10265 str = "{ S1[i,j] : i > j }";
10266 uset = isl_union_set_read_from_str(ctx, str);
10267 filters = isl_union_set_list_from_union_set(uset);
10268 str = "{ S1[i,j] : i <= j; S2[i,j] }";
10269 uset = isl_union_set_read_from_str(ctx, str);
10270 filters = isl_union_set_list_add(filters, uset);
10271 node = isl_schedule_node_insert_sequence(node, filters);
10273 node = isl_schedule_node_child(node, 0);
10274 node = isl_schedule_node_child(node, 0);
10275 mupa = isl_schedule_node_get_prefix_schedule_multi_union_pw_aff(node);
10276 str = "([] : { S1[i,j] : i > j })";
10277 mupa2 = isl_multi_union_pw_aff_read_from_str(ctx, str);
10278 equal = isl_multi_union_pw_aff_plain_is_equal(mupa, mupa2);
10279 isl_multi_union_pw_aff_free(mupa2);
10280 isl_multi_union_pw_aff_free(mupa);
10281 isl_schedule_node_free(node);
10283 if (equal < 0)
10284 return -1;
10285 if (!equal)
10286 isl_die(ctx, isl_error_unknown, "unexpected prefix schedule",
10287 return -1);
10289 return 0;
10292 /* Check that the reaching domain elements and the prefix schedule
10293 * at a leaf node are the same before and after grouping.
10295 static int test_schedule_tree_group_1(isl_ctx *ctx)
10297 int equal;
10298 const char *str;
10299 isl_id *id;
10300 isl_union_set *uset;
10301 isl_multi_union_pw_aff *mupa;
10302 isl_union_pw_multi_aff *upma1, *upma2;
10303 isl_union_set *domain1, *domain2;
10304 isl_union_map *umap1, *umap2;
10305 isl_schedule_node *node;
10307 str = "{ S1[i,j] : 0 <= i,j < 10; S2[i,j] : 0 <= i,j < 10 }";
10308 uset = isl_union_set_read_from_str(ctx, str);
10309 node = isl_schedule_node_from_domain(uset);
10310 node = isl_schedule_node_child(node, 0);
10311 str = "[{ S1[i,j] -> [i]; S2[i,j] -> [9 - i] }]";
10312 mupa = isl_multi_union_pw_aff_read_from_str(ctx, str);
10313 node = isl_schedule_node_insert_partial_schedule(node, mupa);
10314 node = isl_schedule_node_child(node, 0);
10315 str = "[{ S1[i,j] -> [j]; S2[i,j] -> [j] }]";
10316 mupa = isl_multi_union_pw_aff_read_from_str(ctx, str);
10317 node = isl_schedule_node_insert_partial_schedule(node, mupa);
10318 node = isl_schedule_node_child(node, 0);
10319 umap1 = isl_schedule_node_get_prefix_schedule_union_map(node);
10320 upma1 = isl_schedule_node_get_prefix_schedule_union_pw_multi_aff(node);
10321 domain1 = isl_schedule_node_get_domain(node);
10322 id = isl_id_alloc(ctx, "group", NULL);
10323 node = isl_schedule_node_parent(node);
10324 node = isl_schedule_node_group(node, id);
10325 node = isl_schedule_node_child(node, 0);
10326 umap2 = isl_schedule_node_get_prefix_schedule_union_map(node);
10327 upma2 = isl_schedule_node_get_prefix_schedule_union_pw_multi_aff(node);
10328 domain2 = isl_schedule_node_get_domain(node);
10329 equal = isl_union_pw_multi_aff_plain_is_equal(upma1, upma2);
10330 if (equal >= 0 && equal)
10331 equal = isl_union_set_is_equal(domain1, domain2);
10332 if (equal >= 0 && equal)
10333 equal = isl_union_map_is_equal(umap1, umap2);
10334 isl_union_map_free(umap1);
10335 isl_union_map_free(umap2);
10336 isl_union_set_free(domain1);
10337 isl_union_set_free(domain2);
10338 isl_union_pw_multi_aff_free(upma1);
10339 isl_union_pw_multi_aff_free(upma2);
10340 isl_schedule_node_free(node);
10342 if (equal < 0)
10343 return -1;
10344 if (!equal)
10345 isl_die(ctx, isl_error_unknown,
10346 "expressions not equal", return -1);
10348 return 0;
10351 /* Check that we can have nested groupings and that the union map
10352 * schedule representation is the same before and after the grouping.
10353 * Note that after the grouping, the union map representation contains
10354 * the domain constraints from the ranges of the expansion nodes,
10355 * while they are missing from the union map representation of
10356 * the tree without expansion nodes.
10358 * Also check that the global expansion is as expected.
10360 static int test_schedule_tree_group_2(isl_ctx *ctx)
10362 int equal, equal_expansion;
10363 const char *str;
10364 isl_id *id;
10365 isl_union_set *uset;
10366 isl_union_map *umap1, *umap2;
10367 isl_union_map *expansion1, *expansion2;
10368 isl_union_set_list *filters;
10369 isl_multi_union_pw_aff *mupa;
10370 isl_schedule *schedule;
10371 isl_schedule_node *node;
10373 str = "{ S1[i,j] : 0 <= i,j < 10; S2[i,j] : 0 <= i,j < 10; "
10374 "S3[i,j] : 0 <= i,j < 10 }";
10375 uset = isl_union_set_read_from_str(ctx, str);
10376 node = isl_schedule_node_from_domain(uset);
10377 node = isl_schedule_node_child(node, 0);
10378 str = "[{ S1[i,j] -> [i]; S2[i,j] -> [i]; S3[i,j] -> [i] }]";
10379 mupa = isl_multi_union_pw_aff_read_from_str(ctx, str);
10380 node = isl_schedule_node_insert_partial_schedule(node, mupa);
10381 node = isl_schedule_node_child(node, 0);
10382 str = "{ S1[i,j] }";
10383 uset = isl_union_set_read_from_str(ctx, str);
10384 filters = isl_union_set_list_from_union_set(uset);
10385 str = "{ S2[i,j]; S3[i,j] }";
10386 uset = isl_union_set_read_from_str(ctx, str);
10387 filters = isl_union_set_list_add(filters, uset);
10388 node = isl_schedule_node_insert_sequence(node, filters);
10389 node = isl_schedule_node_child(node, 1);
10390 node = isl_schedule_node_child(node, 0);
10391 str = "{ S2[i,j] }";
10392 uset = isl_union_set_read_from_str(ctx, str);
10393 filters = isl_union_set_list_from_union_set(uset);
10394 str = "{ S3[i,j] }";
10395 uset = isl_union_set_read_from_str(ctx, str);
10396 filters = isl_union_set_list_add(filters, uset);
10397 node = isl_schedule_node_insert_sequence(node, filters);
10399 schedule = isl_schedule_node_get_schedule(node);
10400 umap1 = isl_schedule_get_map(schedule);
10401 uset = isl_schedule_get_domain(schedule);
10402 umap1 = isl_union_map_intersect_domain(umap1, uset);
10403 isl_schedule_free(schedule);
10405 node = isl_schedule_node_parent(node);
10406 node = isl_schedule_node_parent(node);
10407 id = isl_id_alloc(ctx, "group1", NULL);
10408 node = isl_schedule_node_group(node, id);
10409 node = isl_schedule_node_child(node, 1);
10410 node = isl_schedule_node_child(node, 0);
10411 id = isl_id_alloc(ctx, "group2", NULL);
10412 node = isl_schedule_node_group(node, id);
10414 schedule = isl_schedule_node_get_schedule(node);
10415 umap2 = isl_schedule_get_map(schedule);
10416 isl_schedule_free(schedule);
10418 node = isl_schedule_node_root(node);
10419 node = isl_schedule_node_child(node, 0);
10420 expansion1 = isl_schedule_node_get_subtree_expansion(node);
10421 isl_schedule_node_free(node);
10423 str = "{ group1[i] -> S1[i,j] : 0 <= i,j < 10; "
10424 "group1[i] -> S2[i,j] : 0 <= i,j < 10; "
10425 "group1[i] -> S3[i,j] : 0 <= i,j < 10 }";
10427 expansion2 = isl_union_map_read_from_str(ctx, str);
10429 equal = isl_union_map_is_equal(umap1, umap2);
10430 equal_expansion = isl_union_map_is_equal(expansion1, expansion2);
10432 isl_union_map_free(umap1);
10433 isl_union_map_free(umap2);
10434 isl_union_map_free(expansion1);
10435 isl_union_map_free(expansion2);
10437 if (equal < 0 || equal_expansion < 0)
10438 return -1;
10439 if (!equal)
10440 isl_die(ctx, isl_error_unknown,
10441 "expressions not equal", return -1);
10442 if (!equal_expansion)
10443 isl_die(ctx, isl_error_unknown,
10444 "unexpected expansion", return -1);
10446 return 0;
10449 /* Some tests for the isl_schedule_node_group function.
10451 static int test_schedule_tree_group(isl_ctx *ctx)
10453 if (test_schedule_tree_group_1(ctx) < 0)
10454 return -1;
10455 if (test_schedule_tree_group_2(ctx) < 0)
10456 return -1;
10457 return 0;
10460 struct {
10461 const char *set;
10462 const char *dual;
10463 } coef_tests[] = {
10464 { "{ rat: [i] : 0 <= i <= 10 }",
10465 "{ rat: coefficients[[cst] -> [a]] : cst >= 0 and 10a + cst >= 0 }" },
10466 { "{ rat: [i] : FALSE }",
10467 "{ rat: coefficients[[cst] -> [a]] }" },
10468 { "{ rat: [i] : }",
10469 "{ rat: coefficients[[cst] -> [0]] : cst >= 0 }" },
10470 { "{ [0:,1,2:3] }",
10471 "{ rat: coefficients[[c_cst] -> [a, b, c]] : "
10472 "a >= 0 and 2c >= -c_cst - b and 3c >= -c_cst - b }" },
10473 { "[M, N] -> { [x = (1 - N):-1, -4x:(M - 4x)] }",
10474 "{ rat: coefficients[[c_cst, c_M = 0:, c_N = 0:] -> [a, b = -c_M:]] :"
10475 "4b >= -c_N + a and 4b >= -c_cst - 2c_N + a }" },
10476 { "{ rat : [x, y] : 1 <= 2x <= 9 and 2 <= 3y <= 16 }",
10477 "{ rat: coefficients[[c_cst] -> [c_x, c_y]] : "
10478 "4c_y >= -6c_cst - 3c_x and 4c_y >= -6c_cst - 27c_x and "
10479 "32c_y >= -6c_cst - 3c_x and 32c_y >= -6c_cst - 27c_x }" },
10480 { "{ [x, y, z] : 3y <= 2x - 2 and y >= -2 + 2x and 2y >= 2 - x }",
10481 "{ rat: coefficients[[cst] -> [a, b, c]] }" },
10484 struct {
10485 const char *set;
10486 const char *dual;
10487 } sol_tests[] = {
10488 { "{ rat: coefficients[[cst] -> [a]] : cst >= 0 and 10a + cst >= 0 }",
10489 "{ rat: [i] : 0 <= i <= 10 }" },
10490 { "{ rat: coefficients[[cst] -> [a]] : FALSE }",
10491 "{ rat: [i] }" },
10492 { "{ rat: coefficients[[cst] -> [a]] }",
10493 "{ rat: [i] : FALSE }" },
10496 /* Test the basic functionality of isl_basic_set_coefficients and
10497 * isl_basic_set_solutions.
10499 static int test_dual(isl_ctx *ctx)
10501 int i;
10503 for (i = 0; i < ARRAY_SIZE(coef_tests); ++i) {
10504 int equal;
10505 isl_basic_set *bset1, *bset2;
10507 bset1 = isl_basic_set_read_from_str(ctx, coef_tests[i].set);
10508 bset2 = isl_basic_set_read_from_str(ctx, coef_tests[i].dual);
10509 bset1 = isl_basic_set_coefficients(bset1);
10510 equal = isl_basic_set_is_equal(bset1, bset2);
10511 isl_basic_set_free(bset1);
10512 isl_basic_set_free(bset2);
10513 if (equal < 0)
10514 return -1;
10515 if (!equal)
10516 isl_die(ctx, isl_error_unknown,
10517 "incorrect dual", return -1);
10520 for (i = 0; i < ARRAY_SIZE(sol_tests); ++i) {
10521 int equal;
10522 isl_basic_set *bset1, *bset2;
10524 bset1 = isl_basic_set_read_from_str(ctx, sol_tests[i].set);
10525 bset2 = isl_basic_set_read_from_str(ctx, sol_tests[i].dual);
10526 bset1 = isl_basic_set_solutions(bset1);
10527 equal = isl_basic_set_is_equal(bset1, bset2);
10528 isl_basic_set_free(bset1);
10529 isl_basic_set_free(bset2);
10530 if (equal < 0)
10531 return -1;
10532 if (!equal)
10533 isl_die(ctx, isl_error_unknown,
10534 "incorrect dual", return -1);
10537 return 0;
10540 struct {
10541 int scale_tile;
10542 int shift_point;
10543 const char *domain;
10544 const char *schedule;
10545 const char *sizes;
10546 const char *tile;
10547 const char *point;
10548 } tile_tests[] = {
10549 { 0, 0, "[n] -> { S[i,j] : 0 <= i,j < n }",
10550 "[{ S[i,j] -> [i] }, { S[i,j] -> [j] }]",
10551 "{ [32,32] }",
10552 "[{ S[i,j] -> [floor(i/32)] }, { S[i,j] -> [floor(j/32)] }]",
10553 "[{ S[i,j] -> [i] }, { S[i,j] -> [j] }]",
10555 { 1, 0, "[n] -> { S[i,j] : 0 <= i,j < n }",
10556 "[{ S[i,j] -> [i] }, { S[i,j] -> [j] }]",
10557 "{ [32,32] }",
10558 "[{ S[i,j] -> [32*floor(i/32)] }, { S[i,j] -> [32*floor(j/32)] }]",
10559 "[{ S[i,j] -> [i] }, { S[i,j] -> [j] }]",
10561 { 0, 1, "[n] -> { S[i,j] : 0 <= i,j < n }",
10562 "[{ S[i,j] -> [i] }, { S[i,j] -> [j] }]",
10563 "{ [32,32] }",
10564 "[{ S[i,j] -> [floor(i/32)] }, { S[i,j] -> [floor(j/32)] }]",
10565 "[{ S[i,j] -> [i%32] }, { S[i,j] -> [j%32] }]",
10567 { 1, 1, "[n] -> { S[i,j] : 0 <= i,j < n }",
10568 "[{ S[i,j] -> [i] }, { S[i,j] -> [j] }]",
10569 "{ [32,32] }",
10570 "[{ S[i,j] -> [32*floor(i/32)] }, { S[i,j] -> [32*floor(j/32)] }]",
10571 "[{ S[i,j] -> [i%32] }, { S[i,j] -> [j%32] }]",
10575 /* Basic tiling tests. Create a schedule tree with a domain and a band node,
10576 * tile the band and then check if the tile and point bands have the
10577 * expected partial schedule.
10579 static int test_tile(isl_ctx *ctx)
10581 int i;
10582 int scale;
10583 int shift;
10585 scale = isl_options_get_tile_scale_tile_loops(ctx);
10586 shift = isl_options_get_tile_shift_point_loops(ctx);
10588 for (i = 0; i < ARRAY_SIZE(tile_tests); ++i) {
10589 int opt;
10590 int equal;
10591 const char *str;
10592 isl_union_set *domain;
10593 isl_multi_union_pw_aff *mupa, *mupa2;
10594 isl_schedule_node *node;
10595 isl_multi_val *sizes;
10597 opt = tile_tests[i].scale_tile;
10598 isl_options_set_tile_scale_tile_loops(ctx, opt);
10599 opt = tile_tests[i].shift_point;
10600 isl_options_set_tile_shift_point_loops(ctx, opt);
10602 str = tile_tests[i].domain;
10603 domain = isl_union_set_read_from_str(ctx, str);
10604 node = isl_schedule_node_from_domain(domain);
10605 node = isl_schedule_node_child(node, 0);
10606 str = tile_tests[i].schedule;
10607 mupa = isl_multi_union_pw_aff_read_from_str(ctx, str);
10608 node = isl_schedule_node_insert_partial_schedule(node, mupa);
10609 str = tile_tests[i].sizes;
10610 sizes = isl_multi_val_read_from_str(ctx, str);
10611 node = isl_schedule_node_band_tile(node, sizes);
10613 str = tile_tests[i].tile;
10614 mupa = isl_multi_union_pw_aff_read_from_str(ctx, str);
10615 mupa2 = isl_schedule_node_band_get_partial_schedule(node);
10616 equal = isl_multi_union_pw_aff_plain_is_equal(mupa, mupa2);
10617 isl_multi_union_pw_aff_free(mupa);
10618 isl_multi_union_pw_aff_free(mupa2);
10620 node = isl_schedule_node_child(node, 0);
10622 str = tile_tests[i].point;
10623 mupa = isl_multi_union_pw_aff_read_from_str(ctx, str);
10624 mupa2 = isl_schedule_node_band_get_partial_schedule(node);
10625 if (equal >= 0 && equal)
10626 equal = isl_multi_union_pw_aff_plain_is_equal(mupa,
10627 mupa2);
10628 isl_multi_union_pw_aff_free(mupa);
10629 isl_multi_union_pw_aff_free(mupa2);
10631 isl_schedule_node_free(node);
10633 if (equal < 0)
10634 return -1;
10635 if (!equal)
10636 isl_die(ctx, isl_error_unknown,
10637 "unexpected result", return -1);
10640 isl_options_set_tile_scale_tile_loops(ctx, scale);
10641 isl_options_set_tile_shift_point_loops(ctx, shift);
10643 return 0;
10646 /* Check that the domain hash of a space is equal to the hash
10647 * of the domain of the space, both ignoring parameters.
10649 static int test_domain_hash(isl_ctx *ctx)
10651 isl_map *map;
10652 isl_space *space;
10653 uint32_t hash1, hash2;
10655 map = isl_map_read_from_str(ctx, "[n] -> { A[B[x] -> C[]] -> D[] }");
10656 space = isl_map_get_space(map);
10657 isl_map_free(map);
10658 hash1 = isl_space_get_tuple_domain_hash(space);
10659 space = isl_space_domain(space);
10660 hash2 = isl_space_get_tuple_hash(space);
10661 isl_space_free(space);
10663 if (!space)
10664 return -1;
10665 if (hash1 != hash2)
10666 isl_die(ctx, isl_error_unknown,
10667 "domain hash not equal to hash of domain", return -1);
10669 return 0;
10672 /* Check that a universe basic set that is not obviously equal to the universe
10673 * is still recognized as being equal to the universe.
10675 static int test_universe(isl_ctx *ctx)
10677 const char *s;
10678 isl_basic_set *bset;
10679 isl_bool is_univ;
10681 s = "{ [] : exists x, y : 3y <= 2x and y >= -3 + 2x and 2y >= 2 - x }";
10682 bset = isl_basic_set_read_from_str(ctx, s);
10683 is_univ = isl_basic_set_is_universe(bset);
10684 isl_basic_set_free(bset);
10686 if (is_univ < 0)
10687 return -1;
10688 if (!is_univ)
10689 isl_die(ctx, isl_error_unknown,
10690 "not recognized as universe set", return -1);
10692 return 0;
10695 /* Sets for which chambers are computed and checked.
10697 const char *chambers_tests[] = {
10698 "[A, B, C] -> { [x, y, z] : x >= 0 and y >= 0 and y <= A - x and "
10699 "z >= 0 and z <= C - y and z <= B - x - y }",
10702 /* Add the domain of "cell" to "cells".
10704 static isl_stat add_cell(__isl_take isl_cell *cell, void *user)
10706 isl_basic_set_list **cells = user;
10707 isl_basic_set *dom;
10709 dom = isl_cell_get_domain(cell);
10710 isl_cell_free(cell);
10711 *cells = isl_basic_set_list_add(*cells, dom);
10713 return *cells ? isl_stat_ok : isl_stat_error;
10716 /* Check that the elements of "list" are pairwise disjoint.
10718 static isl_stat check_pairwise_disjoint(__isl_keep isl_basic_set_list *list)
10720 int i, j;
10721 isl_size n;
10723 n = isl_basic_set_list_n_basic_set(list);
10724 if (n < 0)
10725 return isl_stat_error;
10727 for (i = 0; i < n; ++i) {
10728 isl_basic_set *bset_i;
10730 bset_i = isl_basic_set_list_get_basic_set(list, i);
10731 for (j = i + 1; j < n; ++j) {
10732 isl_basic_set *bset_j;
10733 isl_bool disjoint;
10735 bset_j = isl_basic_set_list_get_basic_set(list, j);
10736 disjoint = isl_basic_set_is_disjoint(bset_i, bset_j);
10737 isl_basic_set_free(bset_j);
10738 if (!disjoint)
10739 isl_die(isl_basic_set_list_get_ctx(list),
10740 isl_error_unknown, "not disjoint",
10741 break);
10742 if (disjoint < 0 || !disjoint)
10743 break;
10745 isl_basic_set_free(bset_i);
10746 if (j < n)
10747 return isl_stat_error;
10750 return isl_stat_ok;
10753 /* Check that the chambers computed by isl_vertices_foreach_disjoint_cell
10754 * are pairwise disjoint.
10756 static int test_chambers(isl_ctx *ctx)
10758 int i;
10760 for (i = 0; i < ARRAY_SIZE(chambers_tests); ++i) {
10761 isl_basic_set *bset;
10762 isl_vertices *vertices;
10763 isl_basic_set_list *cells;
10764 isl_stat ok;
10766 bset = isl_basic_set_read_from_str(ctx, chambers_tests[i]);
10767 vertices = isl_basic_set_compute_vertices(bset);
10768 cells = isl_basic_set_list_alloc(ctx, 0);
10769 if (isl_vertices_foreach_disjoint_cell(vertices, &add_cell,
10770 &cells) < 0)
10771 cells = isl_basic_set_list_free(cells);
10772 ok = check_pairwise_disjoint(cells);
10773 isl_basic_set_list_free(cells);
10774 isl_vertices_free(vertices);
10775 isl_basic_set_free(bset);
10777 if (ok < 0)
10778 return -1;
10781 return 0;
10784 struct {
10785 const char *name;
10786 int (*fn)(isl_ctx *ctx);
10787 } tests [] = {
10788 { "universe", &test_universe },
10789 { "domain hash", &test_domain_hash },
10790 { "dual", &test_dual },
10791 { "dependence analysis", &test_flow },
10792 { "val", &test_val },
10793 { "compute divs", &test_compute_divs },
10794 { "partial lexmin", &test_partial_lexmin },
10795 { "simplify", &test_simplify },
10796 { "curry", &test_curry },
10797 { "piecewise multi affine expressions", &test_pw_multi_aff },
10798 { "multi piecewise affine expressions", &test_multi_pw_aff },
10799 { "conversion", &test_conversion },
10800 { "list", &test_list },
10801 { "align parameters", &test_align_parameters },
10802 { "drop unused parameters", &test_drop_unused_parameters },
10803 { "pullback", &test_pullback },
10804 { "AST", &test_ast },
10805 { "AST build", &test_ast_build },
10806 { "AST generation", &test_ast_gen },
10807 { "eliminate", &test_eliminate },
10808 { "deltas_map", &test_deltas_map },
10809 { "residue class", &test_residue_class },
10810 { "div", &test_div },
10811 { "slice", &test_slice },
10812 { "fixed power", &test_fixed_power },
10813 { "sample", &test_sample },
10814 { "empty projection", &test_empty_projection },
10815 { "output", &test_output },
10816 { "vertices", &test_vertices },
10817 { "chambers", &test_chambers },
10818 { "fixed", &test_fixed },
10819 { "equal", &test_equal },
10820 { "disjoint", &test_disjoint },
10821 { "product", &test_product },
10822 { "dim_max", &test_dim_max },
10823 { "affine", &test_aff },
10824 { "injective", &test_injective },
10825 { "schedule (whole component)", &test_schedule_whole },
10826 { "schedule (incremental)", &test_schedule_incremental },
10827 { "schedule tree", &test_schedule_tree },
10828 { "schedule tree prefix", &test_schedule_tree_prefix },
10829 { "schedule tree grouping", &test_schedule_tree_group },
10830 { "tile", &test_tile },
10831 { "union map", &test_union_map },
10832 { "union_pw", &test_union_pw },
10833 { "locus", &test_locus },
10834 { "eval", &test_eval },
10835 { "parse", &test_parse },
10836 { "single-valued", &test_sv },
10837 { "recession cone", &test_recession_cone },
10838 { "affine hull", &test_affine_hull },
10839 { "simple_hull", &test_simple_hull },
10840 { "box hull", &test_box_hull },
10841 { "coalesce", &test_coalesce },
10842 { "factorize", &test_factorize },
10843 { "subset", &test_subset },
10844 { "subtract", &test_subtract },
10845 { "intersect", &test_intersect },
10846 { "lexmin", &test_lexmin },
10847 { "min", &test_min },
10848 { "set lower bounds", &test_min_mpa },
10849 { "gist", &test_gist },
10850 { "piecewise quasi-polynomials", &test_pwqp },
10851 { "lift", &test_lift },
10852 { "bind parameters", &test_bind },
10853 { "unbind parameters", &test_unbind },
10854 { "bound", &test_bound },
10855 { "get lists", &test_get_list },
10856 { "union", &test_union },
10857 { "split periods", &test_split_periods },
10858 { "lexicographic order", &test_lex },
10859 { "bijectivity", &test_bijective },
10860 { "dataflow analysis", &test_dep },
10861 { "reading", &test_read },
10862 { "bounded", &test_bounded },
10863 { "construction", &test_construction },
10864 { "dimension manipulation", &test_dim },
10865 { "map application", &test_application },
10866 { "convex hull", &test_convex_hull },
10867 { "transitive closure", &test_closure },
10868 { "isl_bool", &test_isl_bool},
10871 int main(int argc, char **argv)
10873 int i;
10874 struct isl_ctx *ctx;
10875 struct isl_options *options;
10877 options = isl_options_new_with_defaults();
10878 assert(options);
10879 argc = isl_options_parse(options, argc, argv, ISL_ARG_ALL);
10881 ctx = isl_ctx_alloc_with_options(&isl_options_args, options);
10882 for (i = 0; i < ARRAY_SIZE(tests); ++i) {
10883 printf("%s\n", tests[i].name);
10884 if (tests[i].fn(ctx) < 0)
10885 goto error;
10887 isl_ctx_free(ctx);
10888 return 0;
10889 error:
10890 isl_ctx_free(ctx);
10891 return -1;