isl_local_space_substitute_equalities: improve error message
[platform/upstream/isl.git] / isl_test.c
1 /*
2  * Copyright 2008-2009 Katholieke Universiteit Leuven
3  *
4  * Use of this software is governed by the MIT license
5  *
6  * Written by Sven Verdoolaege, K.U.Leuven, Departement
7  * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
8  */
9
10 #include <assert.h>
11 #include <stdio.h>
12 #include <limits.h>
13 #include <isl_ctx_private.h>
14 #include <isl_map_private.h>
15 #include <isl_aff_private.h>
16 #include <isl/set.h>
17 #include <isl/flow.h>
18 #include <isl/constraint.h>
19 #include <isl/polynomial.h>
20 #include <isl/union_map.h>
21 #include <isl_factorization.h>
22 #include <isl/schedule.h>
23 #include <isl_options_private.h>
24 #include <isl/vertices.h>
25 #include <isl/ast_build.h>
26 #include <isl/val.h>
27
28 #define ARRAY_SIZE(array) (sizeof(array)/sizeof(*array))
29
30 static char *srcdir;
31
32 static char *get_filename(isl_ctx *ctx, const char *name, const char *suffix) {
33         char *filename;
34         int length;
35         char *pattern = "%s/test_inputs/%s.%s";
36
37         length = strlen(pattern) - 6 + strlen(srcdir) + strlen(name)
38                 + strlen(suffix) + 1;
39         filename = isl_alloc_array(ctx, char, length);
40
41         if (!filename)
42                 return NULL;
43
44         sprintf(filename, pattern, srcdir, name, suffix);
45
46         return filename;
47 }
48
49 void test_parse_map(isl_ctx *ctx, const char *str)
50 {
51         isl_map *map;
52
53         map = isl_map_read_from_str(ctx, str);
54         assert(map);
55         isl_map_free(map);
56 }
57
58 int test_parse_map_equal(isl_ctx *ctx, const char *str, const char *str2)
59 {
60         isl_map *map, *map2;
61         int equal;
62
63         map = isl_map_read_from_str(ctx, str);
64         map2 = isl_map_read_from_str(ctx, str2);
65         equal = isl_map_is_equal(map, map2);
66         isl_map_free(map);
67         isl_map_free(map2);
68
69         if (equal < 0)
70                 return -1;
71         if (!equal)
72                 isl_die(ctx, isl_error_unknown, "maps not equal",
73                         return -1);
74
75         return 0;
76 }
77
78 void test_parse_pwqp(isl_ctx *ctx, const char *str)
79 {
80         isl_pw_qpolynomial *pwqp;
81
82         pwqp = isl_pw_qpolynomial_read_from_str(ctx, str);
83         assert(pwqp);
84         isl_pw_qpolynomial_free(pwqp);
85 }
86
87 static void test_parse_pwaff(isl_ctx *ctx, const char *str)
88 {
89         isl_pw_aff *pwaff;
90
91         pwaff = isl_pw_aff_read_from_str(ctx, str);
92         assert(pwaff);
93         isl_pw_aff_free(pwaff);
94 }
95
96 int test_parse(struct isl_ctx *ctx)
97 {
98         isl_map *map, *map2;
99         const char *str, *str2;
100
101         str = "{ [i] -> [-i] }";
102         map = isl_map_read_from_str(ctx, str);
103         assert(map);
104         isl_map_free(map);
105
106         str = "{ A[i] -> L[([i/3])] }";
107         map = isl_map_read_from_str(ctx, str);
108         assert(map);
109         isl_map_free(map);
110
111         test_parse_map(ctx, "{[[s] -> A[i]] -> [[s+1] -> A[i]]}");
112         test_parse_map(ctx, "{ [p1, y1, y2] -> [2, y1, y2] : "
113                                 "p1 = 1 && (y1 <= y2 || y2 = 0) }");
114
115         str = "{ [x,y]  : [([x/2]+y)/3] >= 1 }";
116         str2 = "{ [x, y] : 2y >= 6 - x }";
117         if (test_parse_map_equal(ctx, str, str2) < 0)
118                 return -1;
119
120         if (test_parse_map_equal(ctx, "{ [x,y] : x <= min(y, 2*y+3) }",
121                                       "{ [x,y] : x <= y, 2*y + 3 }") < 0)
122                 return -1;
123         str = "{ [x, y] : (y <= x and y >= -3) or (2y <= -3 + x and y <= -4) }";
124         if (test_parse_map_equal(ctx, "{ [x,y] : x >= min(y, 2*y+3) }",
125                                         str) < 0)
126                 return -1;
127
128         str = "{[new,old] -> [new+1-2*[(new+1)/2],old+1-2*[(old+1)/2]]}";
129         map = isl_map_read_from_str(ctx, str);
130         str = "{ [new, old] -> [o0, o1] : "
131                "exists (e0 = [(-1 - new + o0)/2], e1 = [(-1 - old + o1)/2]: "
132                "2e0 = -1 - new + o0 and 2e1 = -1 - old + o1 and o0 >= 0 and "
133                "o0 <= 1 and o1 >= 0 and o1 <= 1) }";
134         map2 = isl_map_read_from_str(ctx, str);
135         assert(isl_map_is_equal(map, map2));
136         isl_map_free(map);
137         isl_map_free(map2);
138
139         str = "{[new,old] -> [new+1-2*[(new+1)/2],old+1-2*[(old+1)/2]]}";
140         map = isl_map_read_from_str(ctx, str);
141         str = "{[new,old] -> [(new+1)%2,(old+1)%2]}";
142         map2 = isl_map_read_from_str(ctx, str);
143         assert(isl_map_is_equal(map, map2));
144         isl_map_free(map);
145         isl_map_free(map2);
146
147         str = "[n] -> { [c1] : c1>=0 and c1<=floord(n-4,3) }";
148         str2 = "[n] -> { [c1] : c1 >= 0 and 3c1 <= -4 + n }";
149         if (test_parse_map_equal(ctx, str, str2) < 0)
150                 return -1;
151
152         str = "{ [i,j] -> [i] : i < j; [i,j] -> [j] : j <= i }";
153         str2 = "{ [i,j] -> [min(i,j)] }";
154         if (test_parse_map_equal(ctx, str, str2) < 0)
155                 return -1;
156
157         str = "{ [i,j] : i != j }";
158         str2 = "{ [i,j] : i < j or i > j }";
159         if (test_parse_map_equal(ctx, str, str2) < 0)
160                 return -1;
161
162         str = "{ [i,j] : (i+1)*2 >= j }";
163         str2 = "{ [i, j] : j <= 2 + 2i }";
164         if (test_parse_map_equal(ctx, str, str2) < 0)
165                 return -1;
166
167         str = "{ [i] -> [i > 0 ? 4 : 5] }";
168         str2 = "{ [i] -> [5] : i <= 0; [i] -> [4] : i >= 1 }";
169         if (test_parse_map_equal(ctx, str, str2) < 0)
170                 return -1;
171
172         str = "[N=2,M] -> { [i=[(M+N)/4]] }";
173         str2 = "[N, M] -> { [i] : N = 2 and 4i <= 2 + M and 4i >= -1 + M }";
174         if (test_parse_map_equal(ctx, str, str2) < 0)
175                 return -1;
176
177         str = "{ [x] : x >= 0 }";
178         str2 = "{ [x] : x-0 >= 0 }";
179         if (test_parse_map_equal(ctx, str, str2) < 0)
180                 return -1;
181
182         str = "{ [i] : ((i > 10)) }";
183         str2 = "{ [i] : i >= 11 }";
184         if (test_parse_map_equal(ctx, str, str2) < 0)
185                 return -1;
186
187         str = "{ [i] -> [0] }";
188         str2 = "{ [i] -> [0 * i] }";
189         if (test_parse_map_equal(ctx, str, str2) < 0)
190                 return -1;
191
192         test_parse_pwqp(ctx, "{ [i] -> i + [ (i + [i/3])/2 ] }");
193         test_parse_map(ctx, "{ S1[i] -> [([i/10]),i%10] : 0 <= i <= 45 }");
194         test_parse_pwaff(ctx, "{ [i] -> [i + 1] : i > 0; [a] -> [a] : a < 0 }");
195         test_parse_pwqp(ctx, "{ [x] -> ([(x)/2] * [(x)/3]) }");
196
197         if (test_parse_map_equal(ctx, "{ [a] -> [b] : (not false) }",
198                                       "{ [a] -> [b] : true }") < 0)
199                 return -1;
200
201         if (test_parse_map_equal(ctx, "{ [i] : i/2 <= 5 }",
202                                       "{ [i] : i <= 10 }") < 0)
203                 return -1;
204
205         if (test_parse_map_equal(ctx, "{Sym=[n] [i] : i <= n }",
206                                       "[n] -> { [i] : i <= n }") < 0)
207                 return -1;
208
209         if (test_parse_map_equal(ctx, "{ [*] }", "{ [a] }") < 0)
210                 return -1;
211
212         if (test_parse_map_equal(ctx, "{ [i] : 2*floor(i/2) = i }",
213                                       "{ [i] : exists a : i = 2 a }") < 0)
214                 return -1;
215
216         if (test_parse_map_equal(ctx, "{ [a] -> [b] : a = 5 implies b = 5 }",
217                                       "{ [a] -> [b] : a != 5 or b = 5 }") < 0)
218                 return -1;
219
220         return 0;
221 }
222
223 void test_read(struct isl_ctx *ctx)
224 {
225         char *filename;
226         FILE *input;
227         struct isl_basic_set *bset1, *bset2;
228         const char *str = "{[y]: Exists ( alpha : 2alpha = y)}";
229
230         filename = get_filename(ctx, "set", "omega");
231         assert(filename);
232         input = fopen(filename, "r");
233         assert(input);
234
235         bset1 = isl_basic_set_read_from_file(ctx, input);
236         bset2 = isl_basic_set_read_from_str(ctx, str);
237
238         assert(isl_basic_set_is_equal(bset1, bset2) == 1);
239
240         isl_basic_set_free(bset1);
241         isl_basic_set_free(bset2);
242         free(filename);
243
244         fclose(input);
245 }
246
247 void test_bounded(struct isl_ctx *ctx)
248 {
249         isl_set *set;
250         int bounded;
251
252         set = isl_set_read_from_str(ctx, "[n] -> {[i] : 0 <= i <= n }");
253         bounded = isl_set_is_bounded(set);
254         assert(bounded);
255         isl_set_free(set);
256
257         set = isl_set_read_from_str(ctx, "{[n, i] : 0 <= i <= n }");
258         bounded = isl_set_is_bounded(set);
259         assert(!bounded);
260         isl_set_free(set);
261
262         set = isl_set_read_from_str(ctx, "[n] -> {[i] : i <= n }");
263         bounded = isl_set_is_bounded(set);
264         assert(!bounded);
265         isl_set_free(set);
266 }
267
268 /* Construct the basic set { [i] : 5 <= i <= N } */
269 void test_construction(struct isl_ctx *ctx)
270 {
271         isl_int v;
272         isl_space *dim;
273         isl_local_space *ls;
274         struct isl_basic_set *bset;
275         struct isl_constraint *c;
276
277         isl_int_init(v);
278
279         dim = isl_space_set_alloc(ctx, 1, 1);
280         bset = isl_basic_set_universe(isl_space_copy(dim));
281         ls = isl_local_space_from_space(dim);
282
283         c = isl_inequality_alloc(isl_local_space_copy(ls));
284         isl_int_set_si(v, -1);
285         isl_constraint_set_coefficient(c, isl_dim_set, 0, v);
286         isl_int_set_si(v, 1);
287         isl_constraint_set_coefficient(c, isl_dim_param, 0, v);
288         bset = isl_basic_set_add_constraint(bset, c);
289
290         c = isl_inequality_alloc(isl_local_space_copy(ls));
291         isl_int_set_si(v, 1);
292         isl_constraint_set_coefficient(c, isl_dim_set, 0, v);
293         isl_int_set_si(v, -5);
294         isl_constraint_set_constant(c, v);
295         bset = isl_basic_set_add_constraint(bset, c);
296
297         isl_local_space_free(ls);
298         isl_basic_set_free(bset);
299
300         isl_int_clear(v);
301 }
302
303 void test_dim(struct isl_ctx *ctx)
304 {
305         const char *str;
306         isl_map *map1, *map2;
307
308         map1 = isl_map_read_from_str(ctx,
309             "[n] -> { [i] -> [j] : exists (a = [i/10] : i - 10a <= n ) }");
310         map1 = isl_map_add_dims(map1, isl_dim_in, 1);
311         map2 = isl_map_read_from_str(ctx,
312             "[n] -> { [i,k] -> [j] : exists (a = [i/10] : i - 10a <= n ) }");
313         assert(isl_map_is_equal(map1, map2));
314         isl_map_free(map2);
315
316         map1 = isl_map_project_out(map1, isl_dim_in, 0, 1);
317         map2 = isl_map_read_from_str(ctx, "[n] -> { [i] -> [j] : n >= 0 }");
318         assert(isl_map_is_equal(map1, map2));
319
320         isl_map_free(map1);
321         isl_map_free(map2);
322
323         str = "[n] -> { [i] -> [] : exists a : 0 <= i <= n and i = 2 a }";
324         map1 = isl_map_read_from_str(ctx, str);
325         str = "{ [i] -> [j] : exists a : 0 <= i <= j and i = 2 a }";
326         map2 = isl_map_read_from_str(ctx, str);
327         map1 = isl_map_move_dims(map1, isl_dim_out, 0, isl_dim_param, 0, 1);
328         assert(isl_map_is_equal(map1, map2));
329
330         isl_map_free(map1);
331         isl_map_free(map2);
332 }
333
334 struct {
335         __isl_give isl_val *(*op)(__isl_take isl_val *v);
336         const char *arg;
337         const char *res;
338 } val_un_tests[] = {
339         { &isl_val_neg, "0", "0" },
340         { &isl_val_abs, "0", "0" },
341         { &isl_val_2exp, "0", "1" },
342         { &isl_val_floor, "0", "0" },
343         { &isl_val_ceil, "0", "0" },
344         { &isl_val_neg, "1", "-1" },
345         { &isl_val_neg, "-1", "1" },
346         { &isl_val_neg, "1/2", "-1/2" },
347         { &isl_val_neg, "-1/2", "1/2" },
348         { &isl_val_neg, "infty", "-infty" },
349         { &isl_val_neg, "-infty", "infty" },
350         { &isl_val_neg, "NaN", "NaN" },
351         { &isl_val_abs, "1", "1" },
352         { &isl_val_abs, "-1", "1" },
353         { &isl_val_abs, "1/2", "1/2" },
354         { &isl_val_abs, "-1/2", "1/2" },
355         { &isl_val_abs, "infty", "infty" },
356         { &isl_val_abs, "-infty", "infty" },
357         { &isl_val_abs, "NaN", "NaN" },
358         { &isl_val_floor, "1", "1" },
359         { &isl_val_floor, "-1", "-1" },
360         { &isl_val_floor, "1/2", "0" },
361         { &isl_val_floor, "-1/2", "-1" },
362         { &isl_val_floor, "infty", "infty" },
363         { &isl_val_floor, "-infty", "-infty" },
364         { &isl_val_floor, "NaN", "NaN" },
365         { &isl_val_ceil, "1", "1" },
366         { &isl_val_ceil, "-1", "-1" },
367         { &isl_val_ceil, "1/2", "1" },
368         { &isl_val_ceil, "-1/2", "0" },
369         { &isl_val_ceil, "infty", "infty" },
370         { &isl_val_ceil, "-infty", "-infty" },
371         { &isl_val_ceil, "NaN", "NaN" },
372         { &isl_val_2exp, "-3", "1/8" },
373         { &isl_val_2exp, "-1", "1/2" },
374         { &isl_val_2exp, "1", "2" },
375         { &isl_val_2exp, "2", "4" },
376         { &isl_val_2exp, "3", "8" },
377 };
378
379 /* Perform some basic tests of unary operations on isl_val objects.
380  */
381 static int test_un_val(isl_ctx *ctx)
382 {
383         int i;
384         isl_val *v, *res;
385         __isl_give isl_val *(*fn)(__isl_take isl_val *v);
386         int ok;
387
388         for (i = 0; i < ARRAY_SIZE(val_un_tests); ++i) {
389                 v = isl_val_read_from_str(ctx, val_un_tests[i].arg);
390                 res = isl_val_read_from_str(ctx, val_un_tests[i].res);
391                 fn = val_un_tests[i].op;
392                 v = fn(v);
393                 if (isl_val_is_nan(res))
394                         ok = isl_val_is_nan(v);
395                 else
396                         ok = isl_val_eq(v, res);
397                 isl_val_free(v);
398                 isl_val_free(res);
399                 if (ok < 0)
400                         return -1;
401                 if (!ok)
402                         isl_die(ctx, isl_error_unknown,
403                                 "unexpected result", return -1);
404         }
405
406         return 0;
407 }
408
409 struct {
410         __isl_give isl_val *(*fn)(__isl_take isl_val *v1,
411                                 __isl_take isl_val *v2);
412 } val_bin_op[] = {
413         ['+'] = { &isl_val_add },
414         ['-'] = { &isl_val_sub },
415         ['*'] = { &isl_val_mul },
416         ['/'] = { &isl_val_div },
417         ['g'] = { &isl_val_gcd },
418         ['m'] = { &isl_val_min },
419         ['M'] = { &isl_val_max },
420 };
421
422 struct {
423         const char *arg1;
424         unsigned char op;
425         const char *arg2;
426         const char *res;
427 } val_bin_tests[] = {
428         { "0", '+', "0", "0" },
429         { "1", '+', "0", "1" },
430         { "1", '+', "1", "2" },
431         { "1", '-', "1", "0" },
432         { "1", '*', "1", "1" },
433         { "1", '/', "1", "1" },
434         { "2", '*', "3", "6" },
435         { "2", '*', "1/2", "1" },
436         { "2", '*', "1/3", "2/3" },
437         { "2/3", '*', "3/5", "2/5" },
438         { "2/3", '*', "7/5", "14/15" },
439         { "2", '/', "1/2", "4" },
440         { "-2", '/', "-1/2", "4" },
441         { "-2", '/', "1/2", "-4" },
442         { "2", '/', "-1/2", "-4" },
443         { "2", '/', "2", "1" },
444         { "2", '/', "3", "2/3" },
445         { "2/3", '/', "5/3", "2/5" },
446         { "2/3", '/', "5/7", "14/15" },
447         { "0", '/', "0", "NaN" },
448         { "42", '/', "0", "NaN" },
449         { "-42", '/', "0", "NaN" },
450         { "infty", '/', "0", "NaN" },
451         { "-infty", '/', "0", "NaN" },
452         { "NaN", '/', "0", "NaN" },
453         { "0", '/', "NaN", "NaN" },
454         { "42", '/', "NaN", "NaN" },
455         { "-42", '/', "NaN", "NaN" },
456         { "infty", '/', "NaN", "NaN" },
457         { "-infty", '/', "NaN", "NaN" },
458         { "NaN", '/', "NaN", "NaN" },
459         { "0", '/', "infty", "0" },
460         { "42", '/', "infty", "0" },
461         { "-42", '/', "infty", "0" },
462         { "infty", '/', "infty", "NaN" },
463         { "-infty", '/', "infty", "NaN" },
464         { "NaN", '/', "infty", "NaN" },
465         { "0", '/', "-infty", "0" },
466         { "42", '/', "-infty", "0" },
467         { "-42", '/', "-infty", "0" },
468         { "infty", '/', "-infty", "NaN" },
469         { "-infty", '/', "-infty", "NaN" },
470         { "NaN", '/', "-infty", "NaN" },
471         { "1", '-', "1/3", "2/3" },
472         { "1/3", '+', "1/2", "5/6" },
473         { "1/2", '+', "1/2", "1" },
474         { "3/4", '-', "1/4", "1/2" },
475         { "1/2", '-', "1/3", "1/6" },
476         { "infty", '+', "42", "infty" },
477         { "infty", '+', "infty", "infty" },
478         { "42", '+', "infty", "infty" },
479         { "infty", '-', "infty", "NaN" },
480         { "infty", '*', "infty", "infty" },
481         { "infty", '*', "-infty", "-infty" },
482         { "-infty", '*', "infty", "-infty" },
483         { "-infty", '*', "-infty", "infty" },
484         { "0", '*', "infty", "NaN" },
485         { "1", '*', "infty", "infty" },
486         { "infty", '*', "0", "NaN" },
487         { "infty", '*', "42", "infty" },
488         { "42", '-', "infty", "-infty" },
489         { "infty", '+', "-infty", "NaN" },
490         { "4", 'g', "6", "2" },
491         { "5", 'g', "6", "1" },
492         { "42", 'm', "3", "3" },
493         { "42", 'M', "3", "42" },
494         { "3", 'm', "42", "3" },
495         { "3", 'M', "42", "42" },
496         { "42", 'm', "infty", "42" },
497         { "42", 'M', "infty", "infty" },
498         { "42", 'm', "-infty", "-infty" },
499         { "42", 'M', "-infty", "42" },
500         { "42", 'm', "NaN", "NaN" },
501         { "42", 'M', "NaN", "NaN" },
502         { "infty", 'm', "-infty", "-infty" },
503         { "infty", 'M', "-infty", "infty" },
504 };
505
506 /* Perform some basic tests of binary operations on isl_val objects.
507  */
508 static int test_bin_val(isl_ctx *ctx)
509 {
510         int i;
511         isl_val *v1, *v2, *res;
512         __isl_give isl_val *(*fn)(__isl_take isl_val *v1,
513                                 __isl_take isl_val *v2);
514         int ok;
515
516         for (i = 0; i < ARRAY_SIZE(val_bin_tests); ++i) {
517                 v1 = isl_val_read_from_str(ctx, val_bin_tests[i].arg1);
518                 v2 = isl_val_read_from_str(ctx, val_bin_tests[i].arg2);
519                 res = isl_val_read_from_str(ctx, val_bin_tests[i].res);
520                 fn = val_bin_op[val_bin_tests[i].op].fn;
521                 v1 = fn(v1, v2);
522                 if (isl_val_is_nan(res))
523                         ok = isl_val_is_nan(v1);
524                 else
525                         ok = isl_val_eq(v1, res);
526                 isl_val_free(v1);
527                 isl_val_free(res);
528                 if (ok < 0)
529                         return -1;
530                 if (!ok)
531                         isl_die(ctx, isl_error_unknown,
532                                 "unexpected result", return -1);
533         }
534
535         return 0;
536 }
537
538 /* Perform some basic tests on isl_val objects.
539  */
540 static int test_val(isl_ctx *ctx)
541 {
542         if (test_un_val(ctx) < 0)
543                 return -1;
544         if (test_bin_val(ctx) < 0)
545                 return -1;
546         return 0;
547 }
548
549 static int test_div(isl_ctx *ctx)
550 {
551         unsigned n;
552         const char *str;
553         int empty;
554         isl_int v;
555         isl_space *dim;
556         isl_set *set;
557         isl_local_space *ls;
558         struct isl_basic_set *bset;
559         struct isl_constraint *c;
560
561         isl_int_init(v);
562
563         /* test 1 */
564         dim = isl_space_set_alloc(ctx, 0, 3);
565         bset = isl_basic_set_universe(isl_space_copy(dim));
566         ls = isl_local_space_from_space(dim);
567
568         c = isl_equality_alloc(isl_local_space_copy(ls));
569         isl_int_set_si(v, -1);
570         isl_constraint_set_constant(c, v);
571         isl_int_set_si(v, 1);
572         isl_constraint_set_coefficient(c, isl_dim_set, 0, v);
573         isl_int_set_si(v, 3);
574         isl_constraint_set_coefficient(c, isl_dim_set, 1, v);
575         bset = isl_basic_set_add_constraint(bset, c);
576
577         c = isl_equality_alloc(isl_local_space_copy(ls));
578         isl_int_set_si(v, 1);
579         isl_constraint_set_constant(c, v);
580         isl_int_set_si(v, -1);
581         isl_constraint_set_coefficient(c, isl_dim_set, 0, v);
582         isl_int_set_si(v, 3);
583         isl_constraint_set_coefficient(c, isl_dim_set, 2, v);
584         bset = isl_basic_set_add_constraint(bset, c);
585
586         bset = isl_basic_set_project_out(bset, isl_dim_set, 1, 2);
587
588         assert(bset && bset->n_div == 1);
589         isl_local_space_free(ls);
590         isl_basic_set_free(bset);
591
592         /* test 2 */
593         dim = isl_space_set_alloc(ctx, 0, 3);
594         bset = isl_basic_set_universe(isl_space_copy(dim));
595         ls = isl_local_space_from_space(dim);
596
597         c = isl_equality_alloc(isl_local_space_copy(ls));
598         isl_int_set_si(v, 1);
599         isl_constraint_set_constant(c, v);
600         isl_int_set_si(v, -1);
601         isl_constraint_set_coefficient(c, isl_dim_set, 0, v);
602         isl_int_set_si(v, 3);
603         isl_constraint_set_coefficient(c, isl_dim_set, 1, v);
604         bset = isl_basic_set_add_constraint(bset, c);
605
606         c = isl_equality_alloc(isl_local_space_copy(ls));
607         isl_int_set_si(v, -1);
608         isl_constraint_set_constant(c, v);
609         isl_int_set_si(v, 1);
610         isl_constraint_set_coefficient(c, isl_dim_set, 0, v);
611         isl_int_set_si(v, 3);
612         isl_constraint_set_coefficient(c, isl_dim_set, 2, v);
613         bset = isl_basic_set_add_constraint(bset, c);
614
615         bset = isl_basic_set_project_out(bset, isl_dim_set, 1, 2);
616
617         assert(bset && bset->n_div == 1);
618         isl_local_space_free(ls);
619         isl_basic_set_free(bset);
620
621         /* test 3 */
622         dim = isl_space_set_alloc(ctx, 0, 3);
623         bset = isl_basic_set_universe(isl_space_copy(dim));
624         ls = isl_local_space_from_space(dim);
625
626         c = isl_equality_alloc(isl_local_space_copy(ls));
627         isl_int_set_si(v, 1);
628         isl_constraint_set_constant(c, v);
629         isl_int_set_si(v, -1);
630         isl_constraint_set_coefficient(c, isl_dim_set, 0, v);
631         isl_int_set_si(v, 3);
632         isl_constraint_set_coefficient(c, isl_dim_set, 1, v);
633         bset = isl_basic_set_add_constraint(bset, c);
634
635         c = isl_equality_alloc(isl_local_space_copy(ls));
636         isl_int_set_si(v, -3);
637         isl_constraint_set_constant(c, v);
638         isl_int_set_si(v, 1);
639         isl_constraint_set_coefficient(c, isl_dim_set, 0, v);
640         isl_int_set_si(v, 4);
641         isl_constraint_set_coefficient(c, isl_dim_set, 2, v);
642         bset = isl_basic_set_add_constraint(bset, c);
643
644         bset = isl_basic_set_project_out(bset, isl_dim_set, 1, 2);
645
646         assert(bset && bset->n_div == 1);
647         isl_local_space_free(ls);
648         isl_basic_set_free(bset);
649
650         /* test 4 */
651         dim = isl_space_set_alloc(ctx, 0, 3);
652         bset = isl_basic_set_universe(isl_space_copy(dim));
653         ls = isl_local_space_from_space(dim);
654
655         c = isl_equality_alloc(isl_local_space_copy(ls));
656         isl_int_set_si(v, 2);
657         isl_constraint_set_constant(c, v);
658         isl_int_set_si(v, -1);
659         isl_constraint_set_coefficient(c, isl_dim_set, 0, v);
660         isl_int_set_si(v, 3);
661         isl_constraint_set_coefficient(c, isl_dim_set, 1, v);
662         bset = isl_basic_set_add_constraint(bset, c);
663
664         c = isl_equality_alloc(isl_local_space_copy(ls));
665         isl_int_set_si(v, -1);
666         isl_constraint_set_constant(c, v);
667         isl_int_set_si(v, 1);
668         isl_constraint_set_coefficient(c, isl_dim_set, 0, v);
669         isl_int_set_si(v, 6);
670         isl_constraint_set_coefficient(c, isl_dim_set, 2, v);
671         bset = isl_basic_set_add_constraint(bset, c);
672
673         bset = isl_basic_set_project_out(bset, isl_dim_set, 1, 2);
674
675         assert(isl_basic_set_is_empty(bset));
676         isl_local_space_free(ls);
677         isl_basic_set_free(bset);
678
679         /* test 5 */
680         dim = isl_space_set_alloc(ctx, 0, 3);
681         bset = isl_basic_set_universe(isl_space_copy(dim));
682         ls = isl_local_space_from_space(dim);
683
684         c = isl_equality_alloc(isl_local_space_copy(ls));
685         isl_int_set_si(v, -1);
686         isl_constraint_set_coefficient(c, isl_dim_set, 0, v);
687         isl_int_set_si(v, 3);
688         isl_constraint_set_coefficient(c, isl_dim_set, 2, v);
689         bset = isl_basic_set_add_constraint(bset, c);
690
691         c = isl_equality_alloc(isl_local_space_copy(ls));
692         isl_int_set_si(v, 1);
693         isl_constraint_set_coefficient(c, isl_dim_set, 0, v);
694         isl_int_set_si(v, -3);
695         isl_constraint_set_coefficient(c, isl_dim_set, 1, v);
696         bset = isl_basic_set_add_constraint(bset, c);
697
698         bset = isl_basic_set_project_out(bset, isl_dim_set, 2, 1);
699
700         assert(bset && bset->n_div == 0);
701         isl_basic_set_free(bset);
702         isl_local_space_free(ls);
703
704         /* test 6 */
705         dim = isl_space_set_alloc(ctx, 0, 3);
706         bset = isl_basic_set_universe(isl_space_copy(dim));
707         ls = isl_local_space_from_space(dim);
708
709         c = isl_equality_alloc(isl_local_space_copy(ls));
710         isl_int_set_si(v, -1);
711         isl_constraint_set_coefficient(c, isl_dim_set, 0, v);
712         isl_int_set_si(v, 6);
713         isl_constraint_set_coefficient(c, isl_dim_set, 2, v);
714         bset = isl_basic_set_add_constraint(bset, c);
715
716         c = isl_equality_alloc(isl_local_space_copy(ls));
717         isl_int_set_si(v, 1);
718         isl_constraint_set_coefficient(c, isl_dim_set, 0, v);
719         isl_int_set_si(v, -3);
720         isl_constraint_set_coefficient(c, isl_dim_set, 1, v);
721         bset = isl_basic_set_add_constraint(bset, c);
722
723         bset = isl_basic_set_project_out(bset, isl_dim_set, 2, 1);
724
725         assert(bset && bset->n_div == 1);
726         isl_basic_set_free(bset);
727         isl_local_space_free(ls);
728
729         /* test 7 */
730         /* This test is a bit tricky.  We set up an equality
731          *              a + 3b + 3c = 6 e0
732          * Normalization of divs creates _two_ divs
733          *              a = 3 e0
734          *              c - b - e0 = 2 e1
735          * Afterwards e0 is removed again because it has coefficient -1
736          * and we end up with the original equality and div again.
737          * Perhaps we can avoid the introduction of this temporary div.
738          */
739         dim = isl_space_set_alloc(ctx, 0, 4);
740         bset = isl_basic_set_universe(isl_space_copy(dim));
741         ls = isl_local_space_from_space(dim);
742
743         c = isl_equality_alloc(isl_local_space_copy(ls));
744         isl_int_set_si(v, -1);
745         isl_constraint_set_coefficient(c, isl_dim_set, 0, v);
746         isl_int_set_si(v, -3);
747         isl_constraint_set_coefficient(c, isl_dim_set, 1, v);
748         isl_int_set_si(v, -3);
749         isl_constraint_set_coefficient(c, isl_dim_set, 2, v);
750         isl_int_set_si(v, 6);
751         isl_constraint_set_coefficient(c, isl_dim_set, 3, v);
752         bset = isl_basic_set_add_constraint(bset, c);
753
754         bset = isl_basic_set_project_out(bset, isl_dim_set, 3, 1);
755
756         /* Test disabled for now */
757         /*
758         assert(bset && bset->n_div == 1);
759         */
760         isl_local_space_free(ls);
761         isl_basic_set_free(bset);
762
763         /* test 8 */
764         dim = isl_space_set_alloc(ctx, 0, 5);
765         bset = isl_basic_set_universe(isl_space_copy(dim));
766         ls = isl_local_space_from_space(dim);
767
768         c = isl_equality_alloc(isl_local_space_copy(ls));
769         isl_int_set_si(v, -1);
770         isl_constraint_set_coefficient(c, isl_dim_set, 0, v);
771         isl_int_set_si(v, -3);
772         isl_constraint_set_coefficient(c, isl_dim_set, 1, v);
773         isl_int_set_si(v, -3);
774         isl_constraint_set_coefficient(c, isl_dim_set, 3, v);
775         isl_int_set_si(v, 6);
776         isl_constraint_set_coefficient(c, isl_dim_set, 4, v);
777         bset = isl_basic_set_add_constraint(bset, c);
778
779         c = isl_equality_alloc(isl_local_space_copy(ls));
780         isl_int_set_si(v, -1);
781         isl_constraint_set_coefficient(c, isl_dim_set, 0, v);
782         isl_int_set_si(v, 1);
783         isl_constraint_set_coefficient(c, isl_dim_set, 2, v);
784         isl_int_set_si(v, 1);
785         isl_constraint_set_constant(c, v);
786         bset = isl_basic_set_add_constraint(bset, c);
787
788         bset = isl_basic_set_project_out(bset, isl_dim_set, 4, 1);
789
790         /* Test disabled for now */
791         /*
792         assert(bset && bset->n_div == 1);
793         */
794         isl_local_space_free(ls);
795         isl_basic_set_free(bset);
796
797         /* test 9 */
798         dim = isl_space_set_alloc(ctx, 0, 4);
799         bset = isl_basic_set_universe(isl_space_copy(dim));
800         ls = isl_local_space_from_space(dim);
801
802         c = isl_equality_alloc(isl_local_space_copy(ls));
803         isl_int_set_si(v, 1);
804         isl_constraint_set_coefficient(c, isl_dim_set, 0, v);
805         isl_int_set_si(v, -1);
806         isl_constraint_set_coefficient(c, isl_dim_set, 1, v);
807         isl_int_set_si(v, -2);
808         isl_constraint_set_coefficient(c, isl_dim_set, 2, v);
809         bset = isl_basic_set_add_constraint(bset, c);
810
811         c = isl_equality_alloc(isl_local_space_copy(ls));
812         isl_int_set_si(v, -1);
813         isl_constraint_set_coefficient(c, isl_dim_set, 0, v);
814         isl_int_set_si(v, 3);
815         isl_constraint_set_coefficient(c, isl_dim_set, 3, v);
816         isl_int_set_si(v, 2);
817         isl_constraint_set_constant(c, v);
818         bset = isl_basic_set_add_constraint(bset, c);
819
820         bset = isl_basic_set_project_out(bset, isl_dim_set, 2, 2);
821
822         bset = isl_basic_set_fix_si(bset, isl_dim_set, 0, 2);
823
824         assert(!isl_basic_set_is_empty(bset));
825
826         isl_local_space_free(ls);
827         isl_basic_set_free(bset);
828
829         /* test 10 */
830         dim = isl_space_set_alloc(ctx, 0, 3);
831         bset = isl_basic_set_universe(isl_space_copy(dim));
832         ls = isl_local_space_from_space(dim);
833
834         c = isl_equality_alloc(isl_local_space_copy(ls));
835         isl_int_set_si(v, 1);
836         isl_constraint_set_coefficient(c, isl_dim_set, 0, v);
837         isl_int_set_si(v, -2);
838         isl_constraint_set_coefficient(c, isl_dim_set, 2, v);
839         bset = isl_basic_set_add_constraint(bset, c);
840
841         bset = isl_basic_set_project_out(bset, isl_dim_set, 2, 1);
842
843         bset = isl_basic_set_fix_si(bset, isl_dim_set, 0, 2);
844
845         isl_local_space_free(ls);
846         isl_basic_set_free(bset);
847
848         isl_int_clear(v);
849
850         str = "{ [i] : exists (e0, e1: 3e1 >= 1 + 2e0 and "
851             "8e1 <= -1 + 5i - 5e0 and 2e1 >= 1 + 2i - 5e0) }";
852         set = isl_set_read_from_str(ctx, str);
853         set = isl_set_compute_divs(set);
854         isl_set_free(set);
855         if (!set)
856                 return -1;
857
858         str = "{ [i,j] : 2*[i/2] + 3 * [j/4] <= 10 and 2 i = j }";
859         bset = isl_basic_set_read_from_str(ctx, str);
860         n = isl_basic_set_dim(bset, isl_dim_div);
861         isl_basic_set_free(bset);
862         if (!bset)
863                 return -1;
864         if (n != 0)
865                 isl_die(ctx, isl_error_unknown,
866                         "expecting no existentials", return -1);
867
868         str = "{ [i,j,k] : 3 + i + 2j >= 0 and 2 * [(i+2j)/4] <= k }";
869         set = isl_set_read_from_str(ctx, str);
870         set = isl_set_remove_divs_involving_dims(set, isl_dim_set, 0, 2);
871         set = isl_set_fix_si(set, isl_dim_set, 2, -3);
872         empty = isl_set_is_empty(set);
873         isl_set_free(set);
874         if (empty < 0)
875                 return -1;
876         if (!empty)
877                 isl_die(ctx, isl_error_unknown,
878                         "result not as accurate as expected", return -1);
879
880         return 0;
881 }
882
883 void test_application_case(struct isl_ctx *ctx, const char *name)
884 {
885         char *filename;
886         FILE *input;
887         struct isl_basic_set *bset1, *bset2;
888         struct isl_basic_map *bmap;
889
890         filename = get_filename(ctx, name, "omega");
891         assert(filename);
892         input = fopen(filename, "r");
893         assert(input);
894
895         bset1 = isl_basic_set_read_from_file(ctx, input);
896         bmap = isl_basic_map_read_from_file(ctx, input);
897
898         bset1 = isl_basic_set_apply(bset1, bmap);
899
900         bset2 = isl_basic_set_read_from_file(ctx, input);
901
902         assert(isl_basic_set_is_equal(bset1, bset2) == 1);
903
904         isl_basic_set_free(bset1);
905         isl_basic_set_free(bset2);
906         free(filename);
907
908         fclose(input);
909 }
910
911 void test_application(struct isl_ctx *ctx)
912 {
913         test_application_case(ctx, "application");
914         test_application_case(ctx, "application2");
915 }
916
917 void test_affine_hull_case(struct isl_ctx *ctx, const char *name)
918 {
919         char *filename;
920         FILE *input;
921         struct isl_basic_set *bset1, *bset2;
922
923         filename = get_filename(ctx, name, "polylib");
924         assert(filename);
925         input = fopen(filename, "r");
926         assert(input);
927
928         bset1 = isl_basic_set_read_from_file(ctx, input);
929         bset2 = isl_basic_set_read_from_file(ctx, input);
930
931         bset1 = isl_basic_set_affine_hull(bset1);
932
933         assert(isl_basic_set_is_equal(bset1, bset2) == 1);
934
935         isl_basic_set_free(bset1);
936         isl_basic_set_free(bset2);
937         free(filename);
938
939         fclose(input);
940 }
941
942 int test_affine_hull(struct isl_ctx *ctx)
943 {
944         const char *str;
945         isl_set *set;
946         isl_basic_set *bset, *bset2;
947         int n;
948         int subset;
949
950         test_affine_hull_case(ctx, "affine2");
951         test_affine_hull_case(ctx, "affine");
952         test_affine_hull_case(ctx, "affine3");
953
954         str = "[m] -> { [i0] : exists (e0, e1: e1 <= 1 + i0 and "
955                         "m >= 3 and 4i0 <= 2 + m and e1 >= i0 and "
956                         "e1 >= 0 and e1 <= 2 and e1 >= 1 + 2e0 and "
957                         "2e1 <= 1 + m + 4e0 and 2e1 >= 2 - m + 4i0 - 4e0) }";
958         set = isl_set_read_from_str(ctx, str);
959         bset = isl_set_affine_hull(set);
960         n = isl_basic_set_dim(bset, isl_dim_div);
961         isl_basic_set_free(bset);
962         if (n != 0)
963                 isl_die(ctx, isl_error_unknown, "not expecting any divs",
964                         return -1);
965
966         /* Check that isl_map_affine_hull is not confused by
967          * the reordering of divs in isl_map_align_divs.
968          */
969         str = "{ [a, b, c, 0] : exists (e0 = [(b)/32], e1 = [(c)/32]: "
970                                 "32e0 = b and 32e1 = c); "
971                 "[a, 0, c, 0] : exists (e0 = [(c)/32]: 32e0 = c) }";
972         set = isl_set_read_from_str(ctx, str);
973         bset = isl_set_affine_hull(set);
974         isl_basic_set_free(bset);
975         if (!bset)
976                 return -1;
977
978         str = "{ [a] : exists e0, e1, e2: 32e1 = 31 + 31a + 31e0 and "
979                         "32e2 = 31 + 31e0 }";
980         set = isl_set_read_from_str(ctx, str);
981         bset = isl_set_affine_hull(set);
982         str = "{ [a] : exists e : a = 32 e }";
983         bset2 = isl_basic_set_read_from_str(ctx, str);
984         subset = isl_basic_set_is_subset(bset, bset2);
985         isl_basic_set_free(bset);
986         isl_basic_set_free(bset2);
987         if (subset < 0)
988                 return -1;
989         if (!subset)
990                 isl_die(ctx, isl_error_unknown, "not as accurate as expected",
991                         return -1);
992
993         return 0;
994 }
995
996 void test_convex_hull_case(struct isl_ctx *ctx, const char *name)
997 {
998         char *filename;
999         FILE *input;
1000         struct isl_basic_set *bset1, *bset2;
1001         struct isl_set *set;
1002
1003         filename = get_filename(ctx, name, "polylib");
1004         assert(filename);
1005         input = fopen(filename, "r");
1006         assert(input);
1007
1008         bset1 = isl_basic_set_read_from_file(ctx, input);
1009         bset2 = isl_basic_set_read_from_file(ctx, input);
1010
1011         set = isl_basic_set_union(bset1, bset2);
1012         bset1 = isl_set_convex_hull(set);
1013
1014         bset2 = isl_basic_set_read_from_file(ctx, input);
1015
1016         assert(isl_basic_set_is_equal(bset1, bset2) == 1);
1017
1018         isl_basic_set_free(bset1);
1019         isl_basic_set_free(bset2);
1020         free(filename);
1021
1022         fclose(input);
1023 }
1024
1025 void test_convex_hull_algo(struct isl_ctx *ctx, int convex)
1026 {
1027         const char *str1, *str2;
1028         isl_set *set1, *set2;
1029         int orig_convex = ctx->opt->convex;
1030         ctx->opt->convex = convex;
1031
1032         test_convex_hull_case(ctx, "convex0");
1033         test_convex_hull_case(ctx, "convex1");
1034         test_convex_hull_case(ctx, "convex2");
1035         test_convex_hull_case(ctx, "convex3");
1036         test_convex_hull_case(ctx, "convex4");
1037         test_convex_hull_case(ctx, "convex5");
1038         test_convex_hull_case(ctx, "convex6");
1039         test_convex_hull_case(ctx, "convex7");
1040         test_convex_hull_case(ctx, "convex8");
1041         test_convex_hull_case(ctx, "convex9");
1042         test_convex_hull_case(ctx, "convex10");
1043         test_convex_hull_case(ctx, "convex11");
1044         test_convex_hull_case(ctx, "convex12");
1045         test_convex_hull_case(ctx, "convex13");
1046         test_convex_hull_case(ctx, "convex14");
1047         test_convex_hull_case(ctx, "convex15");
1048
1049         str1 = "{ [i0, i1, i2] : (i2 = 1 and i0 = 0 and i1 >= 0) or "
1050                "(i0 = 1 and i1 = 0 and i2 = 1) or "
1051                "(i0 = 0 and i1 = 0 and i2 = 0) }";
1052         str2 = "{ [i0, i1, i2] : i0 >= 0 and i2 >= i0 and i2 <= 1 and i1 >= 0 }";
1053         set1 = isl_set_read_from_str(ctx, str1);
1054         set2 = isl_set_read_from_str(ctx, str2);
1055         set1 = isl_set_from_basic_set(isl_set_convex_hull(set1));
1056         assert(isl_set_is_equal(set1, set2));
1057         isl_set_free(set1);
1058         isl_set_free(set2);
1059
1060         ctx->opt->convex = orig_convex;
1061 }
1062
1063 void test_convex_hull(struct isl_ctx *ctx)
1064 {
1065         test_convex_hull_algo(ctx, ISL_CONVEX_HULL_FM);
1066         test_convex_hull_algo(ctx, ISL_CONVEX_HULL_WRAP);
1067 }
1068
1069 void test_gist_case(struct isl_ctx *ctx, const char *name)
1070 {
1071         char *filename;
1072         FILE *input;
1073         struct isl_basic_set *bset1, *bset2;
1074
1075         filename = get_filename(ctx, name, "polylib");
1076         assert(filename);
1077         input = fopen(filename, "r");
1078         assert(input);
1079
1080         bset1 = isl_basic_set_read_from_file(ctx, input);
1081         bset2 = isl_basic_set_read_from_file(ctx, input);
1082
1083         bset1 = isl_basic_set_gist(bset1, bset2);
1084
1085         bset2 = isl_basic_set_read_from_file(ctx, input);
1086
1087         assert(isl_basic_set_is_equal(bset1, bset2) == 1);
1088
1089         isl_basic_set_free(bset1);
1090         isl_basic_set_free(bset2);
1091         free(filename);
1092
1093         fclose(input);
1094 }
1095
1096 void test_gist(struct isl_ctx *ctx)
1097 {
1098         const char *str;
1099         isl_basic_set *bset1, *bset2;
1100
1101         test_gist_case(ctx, "gist1");
1102
1103         str = "[p0, p2, p3, p5, p6, p10] -> { [] : "
1104             "exists (e0 = [(15 + p0 + 15p6 + 15p10)/16], e1 = [(p5)/8], "
1105             "e2 = [(p6)/128], e3 = [(8p2 - p5)/128], "
1106             "e4 = [(128p3 - p6)/4096]: 8e1 = p5 and 128e2 = p6 and "
1107             "128e3 = 8p2 - p5 and 4096e4 = 128p3 - p6 and p2 >= 0 and "
1108             "16e0 >= 16 + 16p6 + 15p10 and  p2 <= 15 and p3 >= 0 and "
1109             "p3 <= 31 and  p6 >= 128p3 and p5 >= 8p2 and p10 >= 0 and "
1110             "16e0 <= 15 + p0 + 15p6 + 15p10 and 16e0 >= p0 + 15p6 + 15p10 and "
1111             "p10 <= 15 and p10 <= -1 + p0 - p6) }";
1112         bset1 = isl_basic_set_read_from_str(ctx, str);
1113         str = "[p0, p2, p3, p5, p6, p10] -> { [] : exists (e0 = [(p5)/8], "
1114             "e1 = [(p6)/128], e2 = [(8p2 - p5)/128], "
1115             "e3 = [(128p3 - p6)/4096]: 8e0 = p5 and 128e1 = p6 and "
1116             "128e2 = 8p2 - p5 and 4096e3 = 128p3 - p6 and p5 >= -7 and "
1117             "p2 >= 0 and 8p2 <= -1 + p0 and p2 <= 15 and p3 >= 0 and "
1118             "p3 <= 31 and 128p3 <= -1 + p0 and p6 >= -127 and "
1119             "p5 <= -1 + p0 and p6 <= -1 + p0 and p6 >= 128p3 and "
1120             "p0 >= 1 and p5 >= 8p2 and p10 >= 0 and p10 <= 15 ) }";
1121         bset2 = isl_basic_set_read_from_str(ctx, str);
1122         bset1 = isl_basic_set_gist(bset1, bset2);
1123         assert(bset1 && bset1->n_div == 0);
1124         isl_basic_set_free(bset1);
1125 }
1126
1127 int test_coalesce_set(isl_ctx *ctx, const char *str, int check_one)
1128 {
1129         isl_set *set, *set2;
1130         int equal;
1131         int one;
1132
1133         set = isl_set_read_from_str(ctx, str);
1134         set = isl_set_coalesce(set);
1135         set2 = isl_set_read_from_str(ctx, str);
1136         equal = isl_set_is_equal(set, set2);
1137         one = set && set->n == 1;
1138         isl_set_free(set);
1139         isl_set_free(set2);
1140
1141         if (equal < 0)
1142                 return -1;
1143         if (!equal)
1144                 isl_die(ctx, isl_error_unknown,
1145                         "coalesced set not equal to input", return -1);
1146         if (check_one && !one)
1147                 isl_die(ctx, isl_error_unknown,
1148                         "coalesced set should not be a union", return -1);
1149
1150         return 0;
1151 }
1152
1153 int test_coalesce_unbounded_wrapping(isl_ctx *ctx)
1154 {
1155         int r = 0;
1156         int bounded;
1157
1158         bounded = isl_options_get_coalesce_bounded_wrapping(ctx);
1159         isl_options_set_coalesce_bounded_wrapping(ctx, 0);
1160
1161         if (test_coalesce_set(ctx,
1162                 "{[x,y,z] : y + 2 >= 0 and x - y + 1 >= 0 and "
1163                         "-x - y + 1 >= 0 and -3 <= z <= 3;"
1164                 "[x,y,z] : -x+z + 20 >= 0 and -x-z + 20 >= 0 and "
1165                         "x-z + 20 >= 0 and x+z + 20 >= 0 and "
1166                         "-10 <= y <= 0}", 1) < 0)
1167                 goto error;
1168         if (test_coalesce_set(ctx,
1169                 "{[x,y] : 0 <= x,y <= 10; [5,y]: 4 <=y <= 11}", 1) < 0)
1170                 goto error;
1171         if (test_coalesce_set(ctx,
1172                 "{[x,0,0] : -5 <= x <= 5; [0,y,1] : -5 <= y <= 5 }", 1) < 0)
1173                 goto error;
1174
1175         if (0) {
1176 error:
1177                 r = -1;
1178         }
1179
1180         isl_options_set_coalesce_bounded_wrapping(ctx, bounded);
1181
1182         return r;
1183 }
1184
1185 /* Inputs for coalescing tests.
1186  * "str" is a string representation of the input set.
1187  * "single_disjunct" is set if we expect the result to consist of
1188  *      a single disjunct.
1189  */
1190 struct {
1191         int single_disjunct;
1192         const char *str;
1193 } coalesce_tests[] = {
1194         { 1, "{[x,y]: x >= 0 & x <= 10 & y >= 0 & y <= 10 or "
1195                        "y >= x & x >= 2 & 5 >= y }" },
1196         { 1, "{[x,y]: y >= 0 & 2x + y <= 30 & y <= 10 & x >= 0 or "
1197                        "x + y >= 10 & y <= x & x + y <= 20 & y >= 0}" },
1198         { 0, "{[x,y]: y >= 0 & 2x + y <= 30 & y <= 10 & x >= 0 or "
1199                        "x + y >= 10 & y <= x & x + y <= 19 & y >= 0}" },
1200         { 1, "{[x,y]: y >= 0 & x <= 5 & y <= x or "
1201                        "y >= 0 & x >= 6 & x <= 10 & y <= x}" },
1202         { 0, "{[x,y]: y >= 0 & x <= 5 & y <= x or "
1203                        "y >= 0 & x >= 7 & x <= 10 & y <= x}" },
1204         { 0, "{[x,y]: y >= 0 & x <= 5 & y <= x or "
1205                        "y >= 0 & x >= 6 & x <= 10 & y + 1 <= x}" },
1206         { 1, "{[x,y]: y >= 0 & x <= 5 & y <= x or y >= 0 & x = 6 & y <= 6}" },
1207         { 0, "{[x,y]: y >= 0 & x <= 5 & y <= x or y >= 0 & x = 7 & y <= 6}" },
1208         { 1, "{[x,y]: y >= 0 & x <= 5 & y <= x or y >= 0 & x = 6 & y <= 5}" },
1209         { 0, "{[x,y]: y >= 0 & x <= 5 & y <= x or y >= 0 & x = 6 & y <= 7}" },
1210         { 1, "[n] -> { [i] : i = 1 and n >= 2 or 2 <= i and i <= n }" },
1211         { 0, "{[x,y] : x >= 0 and y >= 0 or 0 <= y and y <= 5 and x = -1}" },
1212         { 1, "[n] -> { [i] : 1 <= i and i <= n - 1 or 2 <= i and i <= n }" },
1213         { 0, "[n] -> { [[i0] -> [o0]] : exists (e0 = [(i0)/4], e1 = [(o0)/4], "
1214                 "e2 = [(n)/2], e3 = [(-2 + i0)/4], e4 = [(-2 + o0)/4], "
1215                 "e5 = [(-2n + i0)/4]: 2e2 = n and 4e3 = -2 + i0 and "
1216                 "4e4 = -2 + o0 and i0 >= 8 + 2n and o0 >= 2 + i0 and "
1217                 "o0 <= 56 + 2n and o0 <= -12 + 4n and i0 <= 57 + 2n and "
1218                 "i0 <= -11 + 4n and o0 >= 6 + 2n and 4e0 <= i0 and "
1219                 "4e0 >= -3 + i0 and 4e1 <= o0 and 4e1 >= -3 + o0 and "
1220                 "4e5 <= -2n + i0 and 4e5 >= -3 - 2n + i0);"
1221                 "[[i0] -> [o0]] : exists (e0 = [(i0)/4], e1 = [(o0)/4], "
1222                 "e2 = [(n)/2], e3 = [(-2 + i0)/4], e4 = [(-2 + o0)/4], "
1223                 "e5 = [(-2n + i0)/4]: 2e2 = n and 4e3 = -2 + i0 and "
1224                 "4e4 = -2 + o0 and 2e0 >= 3 + n and e0 <= -4 + n and "
1225                 "2e0 <= 27 + n and e1 <= -4 + n and 2e1 <= 27 + n and "
1226                 "2e1 >= 2 + n and e1 >= 1 + e0 and i0 >= 7 + 2n and "
1227                 "i0 <= -11 + 4n and i0 <= 57 + 2n and 4e0 <= -2 + i0 and "
1228                 "4e0 >= -3 + i0 and o0 >= 6 + 2n and o0 <= -11 + 4n and "
1229                 "o0 <= 57 + 2n and 4e1 <= -2 + o0 and 4e1 >= -3 + o0 and "
1230                 "4e5 <= -2n + i0 and 4e5 >= -3 - 2n + i0 ) }" },
1231         { 0, "[n, m] -> { [o0, o2, o3] : (o3 = 1 and o0 >= 1 + m and "
1232               "o0 <= n + m and o2 <= m and o0 >= 2 + n and o2 >= 3) or "
1233               "(o0 >= 2 + n and o0 >= 1 + m and o0 <= n + m and n >= 1 and "
1234               "o3 <= -1 + o2 and o3 >= 1 - m + o2 and o3 >= 2 and o3 <= n) }" },
1235         { 0, "[M, N] -> { [[i0, i1, i2, i3, i4, i5, i6] -> "
1236           "[o0, o1, o2, o3, o4, o5, o6]] : "
1237           "(o6 <= -4 + 2M - 2N + i0 + i1 - i2 + i6 - o0 - o1 + o2 and "
1238           "o3 <= -2 + i3 and o6 >= 2 + i0 + i3 + i6 - o0 - o3 and "
1239           "o6 >= 2 - M + N + i3 + i4 + i6 - o3 - o4 and o0 <= -1 + i0 and "
1240           "o4 >= 4 - 3M + 3N - i0 - i1 + i2 + 2i3 + i4 + o0 + o1 - o2 - 2o3 "
1241           "and o6 <= -3 + 2M - 2N + i3 + i4 - i5 + i6 - o3 - o4 + o5 and "
1242           "2o6 <= -5 + 5M - 5N + 2i0 + i1 - i2 - i5 + 2i6 - 2o0 - o1 + o2 + o5 "
1243           "and o6 >= 2i0 + i1 + i6 - 2o0 - o1 and "
1244           "3o6 <= -5 + 4M - 4N + 2i0 + i1 - i2 + 2i3 + i4 - i5 + 3i6 "
1245           "- 2o0 - o1 + o2 - 2o3 - o4 + o5) or "
1246           "(N >= 2 and o3 <= -1 + i3 and o0 <= -1 + i0 and "
1247           "o6 >= i3 + i6 - o3 and M >= 0 and "
1248           "2o6 >= 1 + i0 + i3 + 2i6 - o0 - o3 and "
1249           "o6 >= 1 - M + i0 + i6 - o0 and N >= 2M and o6 >= i0 + i6 - o0) }" },
1250         { 0, "[M, N] -> { [o0] : (o0 = 0 and M >= 1 and N >= 2) or "
1251                 "(o0 = 0 and M >= 1 and N >= 2M and N >= 2 + M) or "
1252                 "(o0 = 0 and M >= 2 and N >= 3) or "
1253                 "(M = 0 and o0 = 0 and N >= 3) }" },
1254         { 0, "{ [i0, i1, i2, i3] : (i1 = 10i0 and i0 >= 1 and 10i0 <= 100 and "
1255             "i3 <= 9 + 10 i2 and i3 >= 1 + 10i2 and i3 >= 0) or "
1256             "(i1 <= 9 + 10i0 and i1 >= 1 + 10i0 and i2 >= 0 and "
1257             "i0 >= 0 and i1 <= 100 and i3 <= 9 + 10i2 and i3 >= 1 + 10i2) }" },
1258         { 0, "[M] -> { [i1] : (i1 >= 2 and i1 <= M) or (i1 = M and M >= 1) }" },
1259         { 0, "{[x,y] : x,y >= 0; [x,y] : 10 <= x <= 20 and y >= -1 }" },
1260         { 1, "{ [x, y] : (x >= 1 and y >= 1 and x <= 2 and y <= 2) or "
1261                 "(y = 3 and x = 1) }" },
1262         { 1, "[M] -> { [i0, i1, i2, i3, i4] : (i1 >= 3 and i4 >= 2 + i2 and "
1263                 "i2 >= 2 and i0 >= 2 and i3 >= 1 + i2 and i0 <= M and "
1264                 "i1 <= M and i3 <= M and i4 <= M) or "
1265                 "(i1 >= 2 and i4 >= 1 + i2 and i2 >= 2 and i0 >= 2 and "
1266                 "i3 >= 1 + i2 and i0 <= M and i1 <= -1 + M and i3 <= M and "
1267                 "i4 <= -1 + M) }" },
1268         { 1, "{ [x, y] : (x >= 0 and y >= 0 and x <= 10 and y <= 10) or "
1269                 "(x >= 1 and y >= 1 and x <= 11 and y <= 11) }" },
1270         { 0, "{[x,0] : x >= 0; [x,1] : x <= 20}" },
1271         { 1, "{ [x, 1 - x] : 0 <= x <= 1; [0,0] }" },
1272         { 1, "{ [0,0]; [i,i] : 1 <= i <= 10 }" },
1273         { 0, "{ [0,0]; [i,j] : 1 <= i,j <= 10 }" },
1274         { 1, "{ [0,0]; [i,2i] : 1 <= i <= 10 }" },
1275         { 0, "{ [0,0]; [i,2i] : 2 <= i <= 10 }" },
1276         { 0, "{ [1,0]; [i,2i] : 1 <= i <= 10 }" },
1277         { 0, "{ [0,1]; [i,2i] : 1 <= i <= 10 }" },
1278         { 0, "{ [a, b] : exists e : 2e = a and "
1279                     "a >= 0 and (a <= 3 or (b <= 0 and b >= -4 + a)) }" },
1280         { 0, "{ [i, j, i', j'] : i <= 2 and j <= 2 and "
1281                         "j' >= -1 + 2i + j - 2i' and i' <= -1 + i and "
1282                         "j >= 1 and j' <= i + j - i' and i >= 1; "
1283                 "[1, 1, 1, 1] }" },
1284         { 1, "{ [i,j] : exists a,b : i = 2a and j = 3b; "
1285                  "[i,j] : exists a : j = 3a }" },
1286         { 1, "{ [a, b, c] : (c <= 7 - b and b <= 1 and b >= 0 and "
1287                         "c >= 3 + b and b <= 3 + 8a and b >= -26 + 8a and "
1288                         "a >= 3) or "
1289                     "(b <= 1 and c <= 7 and b >= 0 and c >= 4 + b and "
1290                         "b <= 3 + 8a and b >= -26 + 8a and a >= 3) }" },
1291         { 1, "{ [a, 0, c] : c >= 1 and c <= 29 and c >= -1 + 8a and "
1292                                 "c <= 6 + 8a and a >= 3; "
1293                 "[a, -1, c] : c >= 1 and c <= 30 and c >= 8a and "
1294                                 "c <= 7 + 8a and a >= 3 and a <= 4 }" },
1295         { 1, "{ [x,y] : 0 <= x <= 2 and y >= 0 and x + 2y <= 4; "
1296                 "[x,0] : 3 <= x <= 4 }" },
1297         { 1, "{ [x,y] : 0 <= x <= 3 and y >= 0 and x + 3y <= 6; "
1298                 "[x,0] : 4 <= x <= 5 }" },
1299         { 0, "{ [x,y] : 0 <= x <= 2 and y >= 0 and x + 2y <= 4; "
1300                 "[x,0] : 3 <= x <= 5 }" },
1301         { 0, "{ [x,y] : 0 <= x <= 2 and y >= 0 and x + y <= 4; "
1302                 "[x,0] : 3 <= x <= 4 }" },
1303         { 1 , "{ [i0, i1] : i0 <= 122 and i0 >= 1 and 128i1 >= -249 + i0 and "
1304                         "i1 <= 0; "
1305                 "[i0, 0] : i0 >= 123 and i0 <= 124 }" },
1306 };
1307
1308 /* Test the functionality of isl_set_coalesce.
1309  * That is, check that the output is always equal to the input
1310  * and in some cases that the result consists of a single disjunct.
1311  */
1312 static int test_coalesce(struct isl_ctx *ctx)
1313 {
1314         int i;
1315
1316         for (i = 0; i < ARRAY_SIZE(coalesce_tests); ++i) {
1317                 const char *str = coalesce_tests[i].str;
1318                 int check_one = coalesce_tests[i].single_disjunct;
1319                 if (test_coalesce_set(ctx, str, check_one) < 0)
1320                         return -1;
1321         }
1322
1323         if (test_coalesce_unbounded_wrapping(ctx) < 0)
1324                 return -1;
1325
1326         return 0;
1327 }
1328
1329 void test_closure(struct isl_ctx *ctx)
1330 {
1331         const char *str;
1332         isl_set *dom;
1333         isl_map *up, *right;
1334         isl_map *map, *map2;
1335         int exact;
1336
1337         /* COCOA example 1 */
1338         map = isl_map_read_from_str(ctx,
1339                 "[n] -> { [i,j] -> [i2,j2] : i2 = i + 1 and j2 = j + 1 and "
1340                         "1 <= i and i < n and 1 <= j and j < n or "
1341                         "i2 = i + 1 and j2 = j - 1 and "
1342                         "1 <= i and i < n and 2 <= j and j <= n }");
1343         map = isl_map_power(map, &exact);
1344         assert(exact);
1345         isl_map_free(map);
1346
1347         /* COCOA example 1 */
1348         map = isl_map_read_from_str(ctx,
1349                 "[n] -> { [i,j] -> [i2,j2] : i2 = i + 1 and j2 = j + 1 and "
1350                         "1 <= i and i < n and 1 <= j and j < n or "
1351                         "i2 = i + 1 and j2 = j - 1 and "
1352                         "1 <= i and i < n and 2 <= j and j <= n }");
1353         map = isl_map_transitive_closure(map, &exact);
1354         assert(exact);
1355         map2 = isl_map_read_from_str(ctx,
1356                 "[n] -> { [i,j] -> [i2,j2] : exists (k1,k2,k : "
1357                         "1 <= i and i < n and 1 <= j and j <= n and "
1358                         "2 <= i2 and i2 <= n and 1 <= j2 and j2 <= n and "
1359                         "i2 = i + k1 + k2 and j2 = j + k1 - k2 and "
1360                         "k1 >= 0 and k2 >= 0 and k1 + k2 = k and k >= 1 )}");
1361         assert(isl_map_is_equal(map, map2));
1362         isl_map_free(map2);
1363         isl_map_free(map);
1364
1365         map = isl_map_read_from_str(ctx,
1366                 "[n] -> { [x] -> [y] : y = x + 1 and 0 <= x and x <= n and "
1367                                      " 0 <= y and y <= n }");
1368         map = isl_map_transitive_closure(map, &exact);
1369         map2 = isl_map_read_from_str(ctx,
1370                 "[n] -> { [x] -> [y] : y > x and 0 <= x and x <= n and "
1371                                      " 0 <= y and y <= n }");
1372         assert(isl_map_is_equal(map, map2));
1373         isl_map_free(map2);
1374         isl_map_free(map);
1375
1376         /* COCOA example 2 */
1377         map = isl_map_read_from_str(ctx,
1378                 "[n] -> { [i,j] -> [i2,j2] : i2 = i + 2 and j2 = j + 2 and "
1379                         "1 <= i and i < n - 1 and 1 <= j and j < n - 1 or "
1380                         "i2 = i + 2 and j2 = j - 2 and "
1381                         "1 <= i and i < n - 1 and 3 <= j and j <= n }");
1382         map = isl_map_transitive_closure(map, &exact);
1383         assert(exact);
1384         map2 = isl_map_read_from_str(ctx,
1385                 "[n] -> { [i,j] -> [i2,j2] : exists (k1,k2,k : "
1386                         "1 <= i and i < n - 1 and 1 <= j and j <= n and "
1387                         "3 <= i2 and i2 <= n and 1 <= j2 and j2 <= n and "
1388                         "i2 = i + 2 k1 + 2 k2 and j2 = j + 2 k1 - 2 k2 and "
1389                         "k1 >= 0 and k2 >= 0 and k1 + k2 = k and k >= 1) }");
1390         assert(isl_map_is_equal(map, map2));
1391         isl_map_free(map);
1392         isl_map_free(map2);
1393
1394         /* COCOA Fig.2 left */
1395         map = isl_map_read_from_str(ctx,
1396                 "[n] -> { [i,j] -> [i2,j2] : i2 = i + 2 and j2 = j and "
1397                         "i <= 2 j - 3 and i <= n - 2 and j <= 2 i - 1 and "
1398                         "j <= n or "
1399                         "i2 = i and j2 = j + 2 and i <= 2 j - 1 and i <= n and "
1400                         "j <= 2 i - 3 and j <= n - 2 or "
1401                         "i2 = i + 1 and j2 = j + 1 and i <= 2 j - 1 and "
1402                         "i <= n - 1 and j <= 2 i - 1 and j <= n - 1 }");
1403         map = isl_map_transitive_closure(map, &exact);
1404         assert(exact);
1405         isl_map_free(map);
1406
1407         /* COCOA Fig.2 right */
1408         map = isl_map_read_from_str(ctx,
1409                 "[n] -> { [i,j] -> [i2,j2] : i2 = i + 3 and j2 = j and "
1410                         "i <= 2 j - 4 and i <= n - 3 and j <= 2 i - 1 and "
1411                         "j <= n or "
1412                         "i2 = i and j2 = j + 3 and i <= 2 j - 1 and i <= n and "
1413                         "j <= 2 i - 4 and j <= n - 3 or "
1414                         "i2 = i + 1 and j2 = j + 1 and i <= 2 j - 1 and "
1415                         "i <= n - 1 and j <= 2 i - 1 and j <= n - 1 }");
1416         map = isl_map_power(map, &exact);
1417         assert(exact);
1418         isl_map_free(map);
1419
1420         /* COCOA Fig.2 right */
1421         map = isl_map_read_from_str(ctx,
1422                 "[n] -> { [i,j] -> [i2,j2] : i2 = i + 3 and j2 = j and "
1423                         "i <= 2 j - 4 and i <= n - 3 and j <= 2 i - 1 and "
1424                         "j <= n or "
1425                         "i2 = i and j2 = j + 3 and i <= 2 j - 1 and i <= n and "
1426                         "j <= 2 i - 4 and j <= n - 3 or "
1427                         "i2 = i + 1 and j2 = j + 1 and i <= 2 j - 1 and "
1428                         "i <= n - 1 and j <= 2 i - 1 and j <= n - 1 }");
1429         map = isl_map_transitive_closure(map, &exact);
1430         assert(exact);
1431         map2 = isl_map_read_from_str(ctx,
1432                 "[n] -> { [i,j] -> [i2,j2] : exists (k1,k2,k3,k : "
1433                         "i <= 2 j - 1 and i <= n and j <= 2 i - 1 and "
1434                         "j <= n and 3 + i + 2 j <= 3 n and "
1435                         "3 + 2 i + j <= 3n and i2 <= 2 j2 -1 and i2 <= n and "
1436                         "i2 <= 3 j2 - 4 and j2 <= 2 i2 -1 and j2 <= n and "
1437                         "13 + 4 j2 <= 11 i2 and i2 = i + 3 k1 + k3 and "
1438                         "j2 = j + 3 k2 + k3 and k1 >= 0 and k2 >= 0 and "
1439                         "k3 >= 0 and k1 + k2 + k3 = k and k > 0) }");
1440         assert(isl_map_is_equal(map, map2));
1441         isl_map_free(map2);
1442         isl_map_free(map);
1443
1444         /* COCOA Fig.1 right */
1445         dom = isl_set_read_from_str(ctx,
1446                 "{ [x,y] : x >= 0 and -2 x + 3 y >= 0 and x <= 3 and "
1447                         "2 x - 3 y + 3 >= 0 }");
1448         right = isl_map_read_from_str(ctx,
1449                 "{ [x,y] -> [x2,y2] : x2 = x + 1 and y2 = y }");
1450         up = isl_map_read_from_str(ctx,
1451                 "{ [x,y] -> [x2,y2] : x2 = x and y2 = y + 1 }");
1452         right = isl_map_intersect_domain(right, isl_set_copy(dom));
1453         right = isl_map_intersect_range(right, isl_set_copy(dom));
1454         up = isl_map_intersect_domain(up, isl_set_copy(dom));
1455         up = isl_map_intersect_range(up, dom);
1456         map = isl_map_union(up, right);
1457         map = isl_map_transitive_closure(map, &exact);
1458         assert(exact);
1459         map2 = isl_map_read_from_str(ctx,
1460                 "{ [0,0] -> [0,1]; [0,0] -> [1,1]; [0,1] -> [1,1]; "
1461                 "  [2,2] -> [3,2]; [2,2] -> [3,3]; [3,2] -> [3,3] }");
1462         assert(isl_map_is_equal(map, map2));
1463         isl_map_free(map2);
1464         isl_map_free(map);
1465
1466         /* COCOA Theorem 1 counter example */
1467         map = isl_map_read_from_str(ctx,
1468                 "{ [i,j] -> [i2,j2] : i = 0 and 0 <= j and j <= 1 and "
1469                         "i2 = 1 and j2 = j or "
1470                         "i = 0 and j = 0 and i2 = 0 and j2 = 1 }");
1471         map = isl_map_transitive_closure(map, &exact);
1472         assert(exact);
1473         isl_map_free(map);
1474
1475         map = isl_map_read_from_str(ctx,
1476                 "[m,n] -> { [i,j] -> [i2,j2] : i2 = i and j2 = j + 2 and "
1477                         "1 <= i,i2 <= n and 1 <= j,j2 <= m or "
1478                         "i2 = i + 1 and 3 <= j2 - j <= 4 and "
1479                         "1 <= i,i2 <= n and 1 <= j,j2 <= m }");
1480         map = isl_map_transitive_closure(map, &exact);
1481         assert(exact);
1482         isl_map_free(map);
1483
1484         /* Kelly et al 1996, fig 12 */
1485         map = isl_map_read_from_str(ctx,
1486                 "[n] -> { [i,j] -> [i2,j2] : i2 = i and j2 = j + 1 and "
1487                         "1 <= i,j,j+1 <= n or "
1488                         "j = n and j2 = 1 and i2 = i + 1 and "
1489                         "1 <= i,i+1 <= n }");
1490         map = isl_map_transitive_closure(map, &exact);
1491         assert(exact);
1492         map2 = isl_map_read_from_str(ctx,
1493                 "[n] -> { [i,j] -> [i2,j2] : 1 <= j < j2 <= n and "
1494                         "1 <= i <= n and i = i2 or "
1495                         "1 <= i < i2 <= n and 1 <= j <= n and "
1496                         "1 <= j2 <= n }");
1497         assert(isl_map_is_equal(map, map2));
1498         isl_map_free(map2);
1499         isl_map_free(map);
1500
1501         /* Omega's closure4 */
1502         map = isl_map_read_from_str(ctx,
1503                 "[m,n] -> { [x,y] -> [x2,y2] : x2 = x and y2 = y + 1 and "
1504                         "1 <= x,y <= 10 or "
1505                         "x2 = x + 1 and y2 = y and "
1506                         "1 <= x <= 20 && 5 <= y <= 15 }");
1507         map = isl_map_transitive_closure(map, &exact);
1508         assert(exact);
1509         isl_map_free(map);
1510
1511         map = isl_map_read_from_str(ctx,
1512                 "[n] -> { [x] -> [y]: 1 <= n <= y - x <= 10 }");
1513         map = isl_map_transitive_closure(map, &exact);
1514         assert(!exact);
1515         map2 = isl_map_read_from_str(ctx,
1516                 "[n] -> { [x] -> [y] : 1 <= n <= 10 and y >= n + x }");
1517         assert(isl_map_is_equal(map, map2));
1518         isl_map_free(map);
1519         isl_map_free(map2);
1520
1521         str = "[n, m] -> { [i0, i1, i2, i3] -> [o0, o1, o2, o3] : "
1522             "i3 = 1 and o0 = i0 and o1 = -1 + i1 and o2 = -1 + i2 and "
1523             "o3 = -2 + i2 and i1 <= -1 + i0 and i1 >= 1 - m + i0 and "
1524             "i1 >= 2 and i1 <= n and i2 >= 3 and i2 <= 1 + n and i2 <= m }";
1525         map = isl_map_read_from_str(ctx, str);
1526         map = isl_map_transitive_closure(map, &exact);
1527         assert(exact);
1528         map2 = isl_map_read_from_str(ctx, str);
1529         assert(isl_map_is_equal(map, map2));
1530         isl_map_free(map);
1531         isl_map_free(map2);
1532
1533         str = "{[0] -> [1]; [2] -> [3]}";
1534         map = isl_map_read_from_str(ctx, str);
1535         map = isl_map_transitive_closure(map, &exact);
1536         assert(exact);
1537         map2 = isl_map_read_from_str(ctx, str);
1538         assert(isl_map_is_equal(map, map2));
1539         isl_map_free(map);
1540         isl_map_free(map2);
1541
1542         str = "[n] -> { [[i0, i1, 1, 0, i0] -> [i5, 1]] -> "
1543             "[[i0, -1 + i1, 2, 0, i0] -> [-1 + i5, 2]] : "
1544             "exists (e0 = [(3 - n)/3]: i5 >= 2 and i1 >= 2 and "
1545             "3i0 <= -1 + n and i1 <= -1 + n and i5 <= -1 + n and "
1546             "3e0 >= 1 - n and 3e0 <= 2 - n and 3i0 >= -2 + n); "
1547             "[[i0, i1, 2, 0, i0] -> [i5, 1]] -> "
1548             "[[i0, i1, 1, 0, i0] -> [-1 + i5, 2]] : "
1549             "exists (e0 = [(3 - n)/3]: i5 >= 2 and i1 >= 1 and "
1550             "3i0 <= -1 + n and i1 <= -1 + n and i5 <= -1 + n and "
1551             "3e0 >= 1 - n and 3e0 <= 2 - n and 3i0 >= -2 + n); "
1552             "[[i0, i1, 1, 0, i0] -> [i5, 2]] -> "
1553             "[[i0, -1 + i1, 2, 0, i0] -> [i5, 1]] : "
1554             "exists (e0 = [(3 - n)/3]: i1 >= 2 and i5 >= 1 and "
1555             "3i0 <= -1 + n and i1 <= -1 + n and i5 <= -1 + n and "
1556             "3e0 >= 1 - n and 3e0 <= 2 - n and 3i0 >= -2 + n); "
1557             "[[i0, i1, 2, 0, i0] -> [i5, 2]] -> "
1558             "[[i0, i1, 1, 0, i0] -> [i5, 1]] : "
1559             "exists (e0 = [(3 - n)/3]: i5 >= 1 and i1 >= 1 and "
1560             "3i0 <= -1 + n and i1 <= -1 + n and i5 <= -1 + n and "
1561             "3e0 >= 1 - n and 3e0 <= 2 - n and 3i0 >= -2 + n) }";
1562         map = isl_map_read_from_str(ctx, str);
1563         map = isl_map_transitive_closure(map, NULL);
1564         assert(map);
1565         isl_map_free(map);
1566 }
1567
1568 void test_lex(struct isl_ctx *ctx)
1569 {
1570         isl_space *dim;
1571         isl_map *map;
1572
1573         dim = isl_space_set_alloc(ctx, 0, 0);
1574         map = isl_map_lex_le(dim);
1575         assert(!isl_map_is_empty(map));
1576         isl_map_free(map);
1577 }
1578
1579 static int test_lexmin(struct isl_ctx *ctx)
1580 {
1581         int equal;
1582         const char *str;
1583         isl_basic_map *bmap;
1584         isl_map *map, *map2;
1585         isl_set *set;
1586         isl_set *set2;
1587         isl_pw_multi_aff *pma;
1588
1589         str = "[p0, p1] -> { [] -> [] : "
1590             "exists (e0 = [(2p1)/3], e1, e2, e3 = [(3 - p1 + 3e0)/3], "
1591             "e4 = [(p1)/3], e5 = [(p1 + 3e4)/3]: "
1592             "3e0 >= -2 + 2p1 and 3e0 >= p1 and 3e3 >= 1 - p1 + 3e0 and "
1593             "3e0 <= 2p1 and 3e3 >= -2 + p1 and 3e3 <= -1 + p1 and p1 >= 3 and "
1594             "3e5 >= -2 + 2p1 and 3e5 >= p1 and 3e5 <= -1 + p1 + 3e4 and "
1595             "3e4 <= p1 and 3e4 >= -2 + p1 and e3 <= -1 + e0 and "
1596             "3e4 >= 6 - p1 + 3e1 and 3e1 >= p1 and 3e5 >= -2 + p1 + 3e4 and "
1597             "2e4 >= 3 - p1 + 2e1 and e4 <= e1 and 3e3 <= 2 - p1 + 3e0 and "
1598             "e5 >= 1 + e1 and 3e4 >= 6 - 2p1 + 3e1 and "
1599             "p0 >= 2 and p1 >= p0 and 3e2 >= p1 and 3e4 >= 6 - p1 + 3e2 and "
1600             "e2 <= e1 and e3 >= 1 and e4 <= e2) }";
1601         map = isl_map_read_from_str(ctx, str);
1602         map = isl_map_lexmin(map);
1603         isl_map_free(map);
1604
1605         str = "[C] -> { [obj,a,b,c] : obj <= 38 a + 7 b + 10 c and "
1606             "a + b <= 1 and c <= 10 b and c <= C and a,b,c,C >= 0 }";
1607         set = isl_set_read_from_str(ctx, str);
1608         set = isl_set_lexmax(set);
1609         str = "[C] -> { [obj,a,b,c] : C = 8 }";
1610         set2 = isl_set_read_from_str(ctx, str);
1611         set = isl_set_intersect(set, set2);
1612         assert(!isl_set_is_empty(set));
1613         isl_set_free(set);
1614
1615         str = "{ [x] -> [y] : x <= y <= 10; [x] -> [5] : -8 <= x <= 8 }";
1616         map = isl_map_read_from_str(ctx, str);
1617         map = isl_map_lexmin(map);
1618         str = "{ [x] -> [5] : 6 <= x <= 8; "
1619                 "[x] -> [x] : x <= 5 or (9 <= x <= 10) }";
1620         map2 = isl_map_read_from_str(ctx, str);
1621         assert(isl_map_is_equal(map, map2));
1622         isl_map_free(map);
1623         isl_map_free(map2);
1624
1625         str = "{ [x] -> [y] : 4y = x or 4y = -1 + x or 4y = -2 + x }";
1626         map = isl_map_read_from_str(ctx, str);
1627         map2 = isl_map_copy(map);
1628         map = isl_map_lexmin(map);
1629         assert(isl_map_is_equal(map, map2));
1630         isl_map_free(map);
1631         isl_map_free(map2);
1632
1633         str = "{ [x] -> [y] : x = 4y; [x] -> [y] : x = 2y }";
1634         map = isl_map_read_from_str(ctx, str);
1635         map = isl_map_lexmin(map);
1636         str = "{ [x] -> [y] : (4y = x and x >= 0) or "
1637                 "(exists (e0 = [(x)/4], e1 = [(-2 + x)/4]: 2y = x and "
1638                 "4e1 = -2 + x and 4e0 <= -1 + x and 4e0 >= -3 + x)) or "
1639                 "(exists (e0 = [(x)/4]: 2y = x and 4e0 = x and x <= -4)) }";
1640         map2 = isl_map_read_from_str(ctx, str);
1641         assert(isl_map_is_equal(map, map2));
1642         isl_map_free(map);
1643         isl_map_free(map2);
1644
1645         str = "{ [i] -> [i', j] : j = i - 8i' and i' >= 0 and i' <= 7 and "
1646                                 " 8i' <= i and 8i' >= -7 + i }";
1647         bmap = isl_basic_map_read_from_str(ctx, str);
1648         pma = isl_basic_map_lexmin_pw_multi_aff(isl_basic_map_copy(bmap));
1649         map2 = isl_map_from_pw_multi_aff(pma);
1650         map = isl_map_from_basic_map(bmap);
1651         assert(isl_map_is_equal(map, map2));
1652         isl_map_free(map);
1653         isl_map_free(map2);
1654
1655         str = "{ T[a] -> S[b, c] : a = 4b-2c and c >= b }";
1656         map = isl_map_read_from_str(ctx, str);
1657         map = isl_map_lexmin(map);
1658         str = "{ T[a] -> S[b, c] : 2b = a and 2c = a }";
1659         map2 = isl_map_read_from_str(ctx, str);
1660         assert(isl_map_is_equal(map, map2));
1661         isl_map_free(map);
1662         isl_map_free(map2);
1663
1664         /* Check that empty pieces are properly combined. */
1665         str = "[K, N] -> { [x, y] -> [a, b] : K+2<=N<=K+4 and x>=4 and "
1666                 "2N-6<=x<K+N and N-1<=a<=K+N-1 and N+b-6<=a<=2N-4 and "
1667                 "b<=2N-3K+a and 3b<=4N-K+1 and b>=N and a>=x+1 }";
1668         map = isl_map_read_from_str(ctx, str);
1669         map = isl_map_lexmin(map);
1670         str = "[K, N] -> { [x, y] -> [1 + x, N] : x >= -6 + 2N and "
1671                 "x <= -5 + 2N and x >= -1 + 3K - N and x <= -2 + K + N and "
1672                 "x >= 4 }";
1673         map2 = isl_map_read_from_str(ctx, str);
1674         assert(isl_map_is_equal(map, map2));
1675         isl_map_free(map);
1676         isl_map_free(map2);
1677
1678         str = "[i] -> { [i', j] : j = i - 8i' and i' >= 0 and i' <= 7 and "
1679                                 " 8i' <= i and 8i' >= -7 + i }";
1680         set = isl_set_read_from_str(ctx, str);
1681         pma = isl_set_lexmin_pw_multi_aff(isl_set_copy(set));
1682         set2 = isl_set_from_pw_multi_aff(pma);
1683         equal = isl_set_is_equal(set, set2);
1684         isl_set_free(set);
1685         isl_set_free(set2);
1686         if (equal < 0)
1687                 return -1;
1688         if (!equal)
1689                 isl_die(ctx, isl_error_unknown,
1690                         "unexpected difference between set and "
1691                         "piecewise affine expression", return -1);
1692
1693         return 0;
1694 }
1695
1696 struct must_may {
1697         isl_map *must;
1698         isl_map *may;
1699 };
1700
1701 static int collect_must_may(__isl_take isl_map *dep, int must,
1702         void *dep_user, void *user)
1703 {
1704         struct must_may *mm = (struct must_may *)user;
1705
1706         if (must)
1707                 mm->must = isl_map_union(mm->must, dep);
1708         else
1709                 mm->may = isl_map_union(mm->may, dep);
1710
1711         return 0;
1712 }
1713
1714 static int common_space(void *first, void *second)
1715 {
1716         int depth = *(int *)first;
1717         return 2 * depth;
1718 }
1719
1720 static int map_is_equal(__isl_keep isl_map *map, const char *str)
1721 {
1722         isl_map *map2;
1723         int equal;
1724
1725         if (!map)
1726                 return -1;
1727
1728         map2 = isl_map_read_from_str(map->ctx, str);
1729         equal = isl_map_is_equal(map, map2);
1730         isl_map_free(map2);
1731
1732         return equal;
1733 }
1734
1735 static int map_check_equal(__isl_keep isl_map *map, const char *str)
1736 {
1737         int equal;
1738
1739         equal = map_is_equal(map, str);
1740         if (equal < 0)
1741                 return -1;
1742         if (!equal)
1743                 isl_die(isl_map_get_ctx(map), isl_error_unknown,
1744                         "result not as expected", return -1);
1745         return 0;
1746 }
1747
1748 void test_dep(struct isl_ctx *ctx)
1749 {
1750         const char *str;
1751         isl_space *dim;
1752         isl_map *map;
1753         isl_access_info *ai;
1754         isl_flow *flow;
1755         int depth;
1756         struct must_may mm;
1757
1758         depth = 3;
1759
1760         str = "{ [2,i,0] -> [i] : 0 <= i <= 10 }";
1761         map = isl_map_read_from_str(ctx, str);
1762         ai = isl_access_info_alloc(map, &depth, &common_space, 2);
1763
1764         str = "{ [0,i,0] -> [i] : 0 <= i <= 10 }";
1765         map = isl_map_read_from_str(ctx, str);
1766         ai = isl_access_info_add_source(ai, map, 1, &depth);
1767
1768         str = "{ [1,i,0] -> [5] : 0 <= i <= 10 }";
1769         map = isl_map_read_from_str(ctx, str);
1770         ai = isl_access_info_add_source(ai, map, 1, &depth);
1771
1772         flow = isl_access_info_compute_flow(ai);
1773         dim = isl_space_alloc(ctx, 0, 3, 3);
1774         mm.must = isl_map_empty(isl_space_copy(dim));
1775         mm.may = isl_map_empty(dim);
1776
1777         isl_flow_foreach(flow, collect_must_may, &mm);
1778
1779         str = "{ [0,i,0] -> [2,i,0] : (0 <= i <= 4) or (6 <= i <= 10); "
1780               "  [1,10,0] -> [2,5,0] }";
1781         assert(map_is_equal(mm.must, str));
1782         str = "{ [i,j,k] -> [l,m,n] : 1 = 0 }";
1783         assert(map_is_equal(mm.may, str));
1784
1785         isl_map_free(mm.must);
1786         isl_map_free(mm.may);
1787         isl_flow_free(flow);
1788
1789
1790         str = "{ [2,i,0] -> [i] : 0 <= i <= 10 }";
1791         map = isl_map_read_from_str(ctx, str);
1792         ai = isl_access_info_alloc(map, &depth, &common_space, 2);
1793
1794         str = "{ [0,i,0] -> [i] : 0 <= i <= 10 }";
1795         map = isl_map_read_from_str(ctx, str);
1796         ai = isl_access_info_add_source(ai, map, 1, &depth);
1797
1798         str = "{ [1,i,0] -> [5] : 0 <= i <= 10 }";
1799         map = isl_map_read_from_str(ctx, str);
1800         ai = isl_access_info_add_source(ai, map, 0, &depth);
1801
1802         flow = isl_access_info_compute_flow(ai);
1803         dim = isl_space_alloc(ctx, 0, 3, 3);
1804         mm.must = isl_map_empty(isl_space_copy(dim));
1805         mm.may = isl_map_empty(dim);
1806
1807         isl_flow_foreach(flow, collect_must_may, &mm);
1808
1809         str = "{ [0,i,0] -> [2,i,0] : (0 <= i <= 4) or (6 <= i <= 10) }";
1810         assert(map_is_equal(mm.must, str));
1811         str = "{ [0,5,0] -> [2,5,0]; [1,i,0] -> [2,5,0] : 0 <= i <= 10 }";
1812         assert(map_is_equal(mm.may, str));
1813
1814         isl_map_free(mm.must);
1815         isl_map_free(mm.may);
1816         isl_flow_free(flow);
1817
1818
1819         str = "{ [2,i,0] -> [i] : 0 <= i <= 10 }";
1820         map = isl_map_read_from_str(ctx, str);
1821         ai = isl_access_info_alloc(map, &depth, &common_space, 2);
1822
1823         str = "{ [0,i,0] -> [i] : 0 <= i <= 10 }";
1824         map = isl_map_read_from_str(ctx, str);
1825         ai = isl_access_info_add_source(ai, map, 0, &depth);
1826
1827         str = "{ [1,i,0] -> [5] : 0 <= i <= 10 }";
1828         map = isl_map_read_from_str(ctx, str);
1829         ai = isl_access_info_add_source(ai, map, 0, &depth);
1830
1831         flow = isl_access_info_compute_flow(ai);
1832         dim = isl_space_alloc(ctx, 0, 3, 3);
1833         mm.must = isl_map_empty(isl_space_copy(dim));
1834         mm.may = isl_map_empty(dim);
1835
1836         isl_flow_foreach(flow, collect_must_may, &mm);
1837
1838         str = "{ [0,i,0] -> [2,i,0] : 0 <= i <= 10; "
1839               "  [1,i,0] -> [2,5,0] : 0 <= i <= 10 }";
1840         assert(map_is_equal(mm.may, str));
1841         str = "{ [i,j,k] -> [l,m,n] : 1 = 0 }";
1842         assert(map_is_equal(mm.must, str));
1843
1844         isl_map_free(mm.must);
1845         isl_map_free(mm.may);
1846         isl_flow_free(flow);
1847
1848
1849         str = "{ [0,i,2] -> [i] : 0 <= i <= 10 }";
1850         map = isl_map_read_from_str(ctx, str);
1851         ai = isl_access_info_alloc(map, &depth, &common_space, 2);
1852
1853         str = "{ [0,i,0] -> [i] : 0 <= i <= 10 }";
1854         map = isl_map_read_from_str(ctx, str);
1855         ai = isl_access_info_add_source(ai, map, 0, &depth);
1856
1857         str = "{ [0,i,1] -> [5] : 0 <= i <= 10 }";
1858         map = isl_map_read_from_str(ctx, str);
1859         ai = isl_access_info_add_source(ai, map, 0, &depth);
1860
1861         flow = isl_access_info_compute_flow(ai);
1862         dim = isl_space_alloc(ctx, 0, 3, 3);
1863         mm.must = isl_map_empty(isl_space_copy(dim));
1864         mm.may = isl_map_empty(dim);
1865
1866         isl_flow_foreach(flow, collect_must_may, &mm);
1867
1868         str = "{ [0,i,0] -> [0,i,2] : 0 <= i <= 10; "
1869               "  [0,i,1] -> [0,5,2] : 0 <= i <= 5 }";
1870         assert(map_is_equal(mm.may, str));
1871         str = "{ [i,j,k] -> [l,m,n] : 1 = 0 }";
1872         assert(map_is_equal(mm.must, str));
1873
1874         isl_map_free(mm.must);
1875         isl_map_free(mm.may);
1876         isl_flow_free(flow);
1877
1878
1879         str = "{ [0,i,1] -> [i] : 0 <= i <= 10 }";
1880         map = isl_map_read_from_str(ctx, str);
1881         ai = isl_access_info_alloc(map, &depth, &common_space, 2);
1882
1883         str = "{ [0,i,0] -> [i] : 0 <= i <= 10 }";
1884         map = isl_map_read_from_str(ctx, str);
1885         ai = isl_access_info_add_source(ai, map, 0, &depth);
1886
1887         str = "{ [0,i,2] -> [5] : 0 <= i <= 10 }";
1888         map = isl_map_read_from_str(ctx, str);
1889         ai = isl_access_info_add_source(ai, map, 0, &depth);
1890
1891         flow = isl_access_info_compute_flow(ai);
1892         dim = isl_space_alloc(ctx, 0, 3, 3);
1893         mm.must = isl_map_empty(isl_space_copy(dim));
1894         mm.may = isl_map_empty(dim);
1895
1896         isl_flow_foreach(flow, collect_must_may, &mm);
1897
1898         str = "{ [0,i,0] -> [0,i,1] : 0 <= i <= 10; "
1899               "  [0,i,2] -> [0,5,1] : 0 <= i <= 4 }";
1900         assert(map_is_equal(mm.may, str));
1901         str = "{ [i,j,k] -> [l,m,n] : 1 = 0 }";
1902         assert(map_is_equal(mm.must, str));
1903
1904         isl_map_free(mm.must);
1905         isl_map_free(mm.may);
1906         isl_flow_free(flow);
1907
1908
1909         depth = 5;
1910
1911         str = "{ [1,i,0,0,0] -> [i,j] : 0 <= i <= 10 and 0 <= j <= 10 }";
1912         map = isl_map_read_from_str(ctx, str);
1913         ai = isl_access_info_alloc(map, &depth, &common_space, 1);
1914
1915         str = "{ [0,i,0,j,0] -> [i,j] : 0 <= i <= 10 and 0 <= j <= 10 }";
1916         map = isl_map_read_from_str(ctx, str);
1917         ai = isl_access_info_add_source(ai, map, 1, &depth);
1918
1919         flow = isl_access_info_compute_flow(ai);
1920         dim = isl_space_alloc(ctx, 0, 5, 5);
1921         mm.must = isl_map_empty(isl_space_copy(dim));
1922         mm.may = isl_map_empty(dim);
1923
1924         isl_flow_foreach(flow, collect_must_may, &mm);
1925
1926         str = "{ [0,i,0,j,0] -> [1,i,0,0,0] : 0 <= i,j <= 10 }";
1927         assert(map_is_equal(mm.must, str));
1928         str = "{ [0,0,0,0,0] -> [0,0,0,0,0] : 1 = 0 }";
1929         assert(map_is_equal(mm.may, str));
1930
1931         isl_map_free(mm.must);
1932         isl_map_free(mm.may);
1933         isl_flow_free(flow);
1934 }
1935
1936 int test_sv(isl_ctx *ctx)
1937 {
1938         const char *str;
1939         isl_map *map;
1940         isl_union_map *umap;
1941         int sv;
1942
1943         str = "[N] -> { [i] -> [f] : 0 <= i <= N and 0 <= i - 10 f <= 9 }";
1944         map = isl_map_read_from_str(ctx, str);
1945         sv = isl_map_is_single_valued(map);
1946         isl_map_free(map);
1947         if (sv < 0)
1948                 return -1;
1949         if (!sv)
1950                 isl_die(ctx, isl_error_internal,
1951                         "map not detected as single valued", return -1);
1952
1953         str = "[N] -> { [i] -> [f] : 0 <= i <= N and 0 <= i - 10 f <= 10 }";
1954         map = isl_map_read_from_str(ctx, str);
1955         sv = isl_map_is_single_valued(map);
1956         isl_map_free(map);
1957         if (sv < 0)
1958                 return -1;
1959         if (sv)
1960                 isl_die(ctx, isl_error_internal,
1961                         "map detected as single valued", return -1);
1962
1963         str = "{ S1[i] -> [i] : 0 <= i <= 9; S2[i] -> [i] : 0 <= i <= 9 }";
1964         umap = isl_union_map_read_from_str(ctx, str);
1965         sv = isl_union_map_is_single_valued(umap);
1966         isl_union_map_free(umap);
1967         if (sv < 0)
1968                 return -1;
1969         if (!sv)
1970                 isl_die(ctx, isl_error_internal,
1971                         "map not detected as single valued", return -1);
1972
1973         str = "{ [i] -> S1[i] : 0 <= i <= 9; [i] -> S2[i] : 0 <= i <= 9 }";
1974         umap = isl_union_map_read_from_str(ctx, str);
1975         sv = isl_union_map_is_single_valued(umap);
1976         isl_union_map_free(umap);
1977         if (sv < 0)
1978                 return -1;
1979         if (sv)
1980                 isl_die(ctx, isl_error_internal,
1981                         "map detected as single valued", return -1);
1982
1983         return 0;
1984 }
1985
1986 void test_bijective_case(struct isl_ctx *ctx, const char *str, int bijective)
1987 {
1988         isl_map *map;
1989
1990         map = isl_map_read_from_str(ctx, str);
1991         if (bijective)
1992                 assert(isl_map_is_bijective(map));
1993         else
1994                 assert(!isl_map_is_bijective(map));
1995         isl_map_free(map);
1996 }
1997
1998 void test_bijective(struct isl_ctx *ctx)
1999 {
2000         test_bijective_case(ctx, "[N,M]->{[i,j] -> [i]}", 0);
2001         test_bijective_case(ctx, "[N,M]->{[i,j] -> [i] : j=i}", 1);
2002         test_bijective_case(ctx, "[N,M]->{[i,j] -> [i] : j=0}", 1);
2003         test_bijective_case(ctx, "[N,M]->{[i,j] -> [i] : j=N}", 1);
2004         test_bijective_case(ctx, "[N,M]->{[i,j] -> [j,i]}", 1);
2005         test_bijective_case(ctx, "[N,M]->{[i,j] -> [i+j]}", 0);
2006         test_bijective_case(ctx, "[N,M]->{[i,j] -> []}", 0);
2007         test_bijective_case(ctx, "[N,M]->{[i,j] -> [i,j,N]}", 1);
2008         test_bijective_case(ctx, "[N,M]->{[i,j] -> [2i]}", 0);
2009         test_bijective_case(ctx, "[N,M]->{[i,j] -> [i,i]}", 0);
2010         test_bijective_case(ctx, "[N,M]->{[i,j] -> [2i,i]}", 0);
2011         test_bijective_case(ctx, "[N,M]->{[i,j] -> [2i,j]}", 1);
2012         test_bijective_case(ctx, "[N,M]->{[i,j] -> [x,y] : 2x=i & y =j}", 1);
2013 }
2014
2015 static int test_pwqp(struct isl_ctx *ctx)
2016 {
2017         const char *str;
2018         isl_set *set;
2019         isl_pw_qpolynomial *pwqp1, *pwqp2;
2020         int equal;
2021
2022         str = "{ [i,j,k] -> 1 + 9 * [i/5] + 7 * [j/11] + 4 * [k/13] }";
2023         pwqp1 = isl_pw_qpolynomial_read_from_str(ctx, str);
2024
2025         pwqp1 = isl_pw_qpolynomial_move_dims(pwqp1, isl_dim_param, 0,
2026                                                 isl_dim_in, 1, 1);
2027
2028         str = "[j] -> { [i,k] -> 1 + 9 * [i/5] + 7 * [j/11] + 4 * [k/13] }";
2029         pwqp2 = isl_pw_qpolynomial_read_from_str(ctx, str);
2030
2031         pwqp1 = isl_pw_qpolynomial_sub(pwqp1, pwqp2);
2032
2033         assert(isl_pw_qpolynomial_is_zero(pwqp1));
2034
2035         isl_pw_qpolynomial_free(pwqp1);
2036
2037         str = "{ [i] -> i }";
2038         pwqp1 = isl_pw_qpolynomial_read_from_str(ctx, str);
2039         str = "{ [k] : exists a : k = 2a }";
2040         set = isl_set_read_from_str(ctx, str);
2041         pwqp1 = isl_pw_qpolynomial_gist(pwqp1, set);
2042         str = "{ [i] -> i }";
2043         pwqp2 = isl_pw_qpolynomial_read_from_str(ctx, str);
2044
2045         pwqp1 = isl_pw_qpolynomial_sub(pwqp1, pwqp2);
2046
2047         assert(isl_pw_qpolynomial_is_zero(pwqp1));
2048
2049         isl_pw_qpolynomial_free(pwqp1);
2050
2051         str = "{ [i] -> i + [ (i + [i/3])/2 ] }";
2052         pwqp1 = isl_pw_qpolynomial_read_from_str(ctx, str);
2053         str = "{ [10] }";
2054         set = isl_set_read_from_str(ctx, str);
2055         pwqp1 = isl_pw_qpolynomial_gist(pwqp1, set);
2056         str = "{ [i] -> 16 }";
2057         pwqp2 = isl_pw_qpolynomial_read_from_str(ctx, str);
2058
2059         pwqp1 = isl_pw_qpolynomial_sub(pwqp1, pwqp2);
2060
2061         assert(isl_pw_qpolynomial_is_zero(pwqp1));
2062
2063         isl_pw_qpolynomial_free(pwqp1);
2064
2065         str = "{ [i] -> ([(i)/2]) }";
2066         pwqp1 = isl_pw_qpolynomial_read_from_str(ctx, str);
2067         str = "{ [k] : exists a : k = 2a+1 }";
2068         set = isl_set_read_from_str(ctx, str);
2069         pwqp1 = isl_pw_qpolynomial_gist(pwqp1, set);
2070         str = "{ [i] -> -1/2 + 1/2 * i }";
2071         pwqp2 = isl_pw_qpolynomial_read_from_str(ctx, str);
2072
2073         pwqp1 = isl_pw_qpolynomial_sub(pwqp1, pwqp2);
2074
2075         assert(isl_pw_qpolynomial_is_zero(pwqp1));
2076
2077         isl_pw_qpolynomial_free(pwqp1);
2078
2079         str = "{ [i] -> ([([i/2] + [i/2])/5]) }";
2080         pwqp1 = isl_pw_qpolynomial_read_from_str(ctx, str);
2081         str = "{ [i] -> ([(2 * [i/2])/5]) }";
2082         pwqp2 = isl_pw_qpolynomial_read_from_str(ctx, str);
2083
2084         pwqp1 = isl_pw_qpolynomial_sub(pwqp1, pwqp2);
2085
2086         assert(isl_pw_qpolynomial_is_zero(pwqp1));
2087
2088         isl_pw_qpolynomial_free(pwqp1);
2089
2090         str = "{ [x] -> ([x/2] + [(x+1)/2]) }";
2091         pwqp1 = isl_pw_qpolynomial_read_from_str(ctx, str);
2092         str = "{ [x] -> x }";
2093         pwqp2 = isl_pw_qpolynomial_read_from_str(ctx, str);
2094
2095         pwqp1 = isl_pw_qpolynomial_sub(pwqp1, pwqp2);
2096
2097         assert(isl_pw_qpolynomial_is_zero(pwqp1));
2098
2099         isl_pw_qpolynomial_free(pwqp1);
2100
2101         str = "{ [i] -> ([i/2]) : i >= 0; [i] -> ([i/3]) : i < 0 }";
2102         pwqp1 = isl_pw_qpolynomial_read_from_str(ctx, str);
2103         pwqp2 = isl_pw_qpolynomial_read_from_str(ctx, str);
2104         pwqp1 = isl_pw_qpolynomial_coalesce(pwqp1);
2105         pwqp1 = isl_pw_qpolynomial_sub(pwqp1, pwqp2);
2106         assert(isl_pw_qpolynomial_is_zero(pwqp1));
2107         isl_pw_qpolynomial_free(pwqp1);
2108
2109         str = "{ [a,b,a] -> (([(2*[a/3]+b)/5]) * ([(2*[a/3]+b)/5])) }";
2110         pwqp2 = isl_pw_qpolynomial_read_from_str(ctx, str);
2111         str = "{ [a,b,c] -> (([(2*[a/3]+b)/5]) * ([(2*[c/3]+b)/5])) }";
2112         pwqp1 = isl_pw_qpolynomial_read_from_str(ctx, str);
2113         set = isl_set_read_from_str(ctx, "{ [a,b,a] }");
2114         pwqp1 = isl_pw_qpolynomial_intersect_domain(pwqp1, set);
2115         equal = isl_pw_qpolynomial_plain_is_equal(pwqp1, pwqp2);
2116         isl_pw_qpolynomial_free(pwqp1);
2117         isl_pw_qpolynomial_free(pwqp2);
2118         if (equal < 0)
2119                 return -1;
2120         if (!equal)
2121                 isl_die(ctx, isl_error_unknown, "unexpected result", return -1);
2122
2123         str = "{ [a,b,c] -> (([(2*[a/3]+1)/5]) * ([(2*[c/3]+1)/5])) : b = 1 }";
2124         pwqp2 = isl_pw_qpolynomial_read_from_str(ctx, str);
2125         str = "{ [a,b,c] -> (([(2*[a/3]+b)/5]) * ([(2*[c/3]+b)/5])) }";
2126         pwqp1 = isl_pw_qpolynomial_read_from_str(ctx, str);
2127         pwqp1 = isl_pw_qpolynomial_fix_val(pwqp1, isl_dim_set, 1,
2128                                                 isl_val_one(ctx));
2129         equal = isl_pw_qpolynomial_plain_is_equal(pwqp1, pwqp2);
2130         isl_pw_qpolynomial_free(pwqp1);
2131         isl_pw_qpolynomial_free(pwqp2);
2132         if (equal < 0)
2133                 return -1;
2134         if (!equal)
2135                 isl_die(ctx, isl_error_unknown, "unexpected result", return -1);
2136
2137         return 0;
2138 }
2139
2140 void test_split_periods(isl_ctx *ctx)
2141 {
2142         const char *str;
2143         isl_pw_qpolynomial *pwqp;
2144
2145         str = "{ [U,V] -> 1/3 * U + 2/3 * V - [(U + 2V)/3] + [U/2] : "
2146                 "U + 2V + 3 >= 0 and - U -2V  >= 0 and - U + 10 >= 0 and "
2147                 "U  >= 0; [U,V] -> U^2 : U >= 100 }";
2148         pwqp = isl_pw_qpolynomial_read_from_str(ctx, str);
2149
2150         pwqp = isl_pw_qpolynomial_split_periods(pwqp, 2);
2151         assert(pwqp);
2152
2153         isl_pw_qpolynomial_free(pwqp);
2154 }
2155
2156 void test_union(isl_ctx *ctx)
2157 {
2158         const char *str;
2159         isl_union_set *uset1, *uset2;
2160         isl_union_map *umap1, *umap2;
2161
2162         str = "{ [i] : 0 <= i <= 1 }";
2163         uset1 = isl_union_set_read_from_str(ctx, str);
2164         str = "{ [1] -> [0] }";
2165         umap1 = isl_union_map_read_from_str(ctx, str);
2166
2167         umap2 = isl_union_set_lex_gt_union_set(isl_union_set_copy(uset1), uset1);
2168         assert(isl_union_map_is_equal(umap1, umap2));
2169
2170         isl_union_map_free(umap1);
2171         isl_union_map_free(umap2);
2172
2173         str = "{ A[i] -> B[i]; B[i] -> C[i]; A[0] -> C[1] }";
2174         umap1 = isl_union_map_read_from_str(ctx, str);
2175         str = "{ A[i]; B[i] }";
2176         uset1 = isl_union_set_read_from_str(ctx, str);
2177
2178         uset2 = isl_union_map_domain(umap1);
2179
2180         assert(isl_union_set_is_equal(uset1, uset2));
2181
2182         isl_union_set_free(uset1);
2183         isl_union_set_free(uset2);
2184 }
2185
2186 void test_bound(isl_ctx *ctx)
2187 {
2188         const char *str;
2189         isl_pw_qpolynomial *pwqp;
2190         isl_pw_qpolynomial_fold *pwf;
2191
2192         str = "{ [[a, b, c, d] -> [e]] -> 0 }";
2193         pwqp = isl_pw_qpolynomial_read_from_str(ctx, str);
2194         pwf = isl_pw_qpolynomial_bound(pwqp, isl_fold_max, NULL);
2195         assert(isl_pw_qpolynomial_fold_dim(pwf, isl_dim_in) == 4);
2196         isl_pw_qpolynomial_fold_free(pwf);
2197
2198         str = "{ [[x]->[x]] -> 1 : exists a : x = 2 a }";
2199         pwqp = isl_pw_qpolynomial_read_from_str(ctx, str);
2200         pwf = isl_pw_qpolynomial_bound(pwqp, isl_fold_max, NULL);
2201         assert(isl_pw_qpolynomial_fold_dim(pwf, isl_dim_in) == 1);
2202         isl_pw_qpolynomial_fold_free(pwf);
2203 }
2204
2205 void test_lift(isl_ctx *ctx)
2206 {
2207         const char *str;
2208         isl_basic_map *bmap;
2209         isl_basic_set *bset;
2210
2211         str = "{ [i0] : exists e0 : i0 = 4e0 }";
2212         bset = isl_basic_set_read_from_str(ctx, str);
2213         bset = isl_basic_set_lift(bset);
2214         bmap = isl_basic_map_from_range(bset);
2215         bset = isl_basic_map_domain(bmap);
2216         isl_basic_set_free(bset);
2217 }
2218
2219 struct {
2220         const char *set1;
2221         const char *set2;
2222         int subset;
2223 } subset_tests[] = {
2224         { "{ [112, 0] }",
2225           "{ [i0, i1] : exists (e0 = [(i0 - i1)/16], e1: "
2226                 "16e0 <= i0 - i1 and 16e0 >= -15 + i0 - i1 and "
2227                 "16e1 <= i1 and 16e0 >= -i1 and 16e1 >= -i0 + i1) }", 1 },
2228         { "{ [65] }",
2229           "{ [i] : exists (e0 = [(255i)/256], e1 = [(127i + 65e0)/191], "
2230                 "e2 = [(3i + 61e1)/65], e3 = [(52i + 12e2)/61], "
2231                 "e4 = [(2i + e3)/3], e5 = [(4i + e3)/4], e6 = [(8i + e3)/12]: "
2232                     "3e4 = 2i + e3 and 4e5 = 4i + e3 and 12e6 = 8i + e3 and "
2233                     "i <= 255 and 64e3 >= -45 + 67i and i >= 0 and "
2234                     "256e0 <= 255i and 256e0 >= -255 + 255i and "
2235                     "191e1 <= 127i + 65e0 and 191e1 >= -190 + 127i + 65e0 and "
2236                     "65e2 <= 3i + 61e1 and 65e2 >= -64 + 3i + 61e1 and "
2237                     "61e3 <= 52i + 12e2 and 61e3 >= -60 + 52i + 12e2) }", 1 },
2238         { "{ [i] : 0 <= i <= 10 }", "{ rat: [i] : 0 <= i <= 10 }", 1 },
2239         { "{ rat: [i] : 0 <= i <= 10 }", "{ [i] : 0 <= i <= 10 }", 0 },
2240         { "{ rat: [0] }", "{ [i] : 0 <= i <= 10 }", 1 },
2241         { "{ rat: [(1)/2] }", "{ [i] : 0 <= i <= 10 }", 0 },
2242 };
2243
2244 static int test_subset(isl_ctx *ctx)
2245 {
2246         int i;
2247         isl_set *set1, *set2;
2248         int subset;
2249
2250         for (i = 0; i < ARRAY_SIZE(subset_tests); ++i) {
2251                 set1 = isl_set_read_from_str(ctx, subset_tests[i].set1);
2252                 set2 = isl_set_read_from_str(ctx, subset_tests[i].set2);
2253                 subset = isl_set_is_subset(set1, set2);
2254                 isl_set_free(set1);
2255                 isl_set_free(set2);
2256                 if (subset < 0)
2257                         return -1;
2258                 if (subset != subset_tests[i].subset)
2259                         isl_die(ctx, isl_error_unknown,
2260                                 "incorrect subset result", return -1);
2261         }
2262
2263         return 0;
2264 }
2265
2266 struct {
2267         const char *minuend;
2268         const char *subtrahend;
2269         const char *difference;
2270 } subtract_domain_tests[] = {
2271         { "{ A[i] -> B[i] }", "{ A[i] }", "{ }" },
2272         { "{ A[i] -> B[i] }", "{ B[i] }", "{ A[i] -> B[i] }" },
2273         { "{ A[i] -> B[i] }", "{ A[i] : i > 0 }", "{ A[i] -> B[i] : i <= 0 }" },
2274 };
2275
2276 static int test_subtract(isl_ctx *ctx)
2277 {
2278         int i;
2279         isl_union_map *umap1, *umap2;
2280         isl_union_set *uset;
2281         int equal;
2282
2283         for (i = 0; i < ARRAY_SIZE(subtract_domain_tests); ++i) {
2284                 umap1 = isl_union_map_read_from_str(ctx,
2285                                 subtract_domain_tests[i].minuend);
2286                 uset = isl_union_set_read_from_str(ctx,
2287                                 subtract_domain_tests[i].subtrahend);
2288                 umap2 = isl_union_map_read_from_str(ctx,
2289                                 subtract_domain_tests[i].difference);
2290                 umap1 = isl_union_map_subtract_domain(umap1, uset);
2291                 equal = isl_union_map_is_equal(umap1, umap2);
2292                 isl_union_map_free(umap1);
2293                 isl_union_map_free(umap2);
2294                 if (equal < 0)
2295                         return -1;
2296                 if (!equal)
2297                         isl_die(ctx, isl_error_unknown,
2298                                 "incorrect subtract domain result", return -1);
2299         }
2300
2301         return 0;
2302 }
2303
2304 int test_factorize(isl_ctx *ctx)
2305 {
2306         const char *str;
2307         isl_basic_set *bset;
2308         isl_factorizer *f;
2309
2310         str = "{ [i0, i1, i2, i3, i4, i5, i6, i7] : 3i5 <= 2 - 2i0 and "
2311             "i0 >= -2 and i6 >= 1 + i3 and i7 >= 0 and 3i5 >= -2i0 and "
2312             "2i4 <= i2 and i6 >= 1 + 2i0 + 3i1 and i4 <= -1 and "
2313             "i6 >= 1 + 2i0 + 3i5 and i6 <= 2 + 2i0 + 3i5 and "
2314             "3i5 <= 2 - 2i0 - i2 + 3i4 and i6 <= 2 + 2i0 + 3i1 and "
2315             "i0 <= -1 and i7 <= i2 + i3 - 3i4 - i6 and "
2316             "3i5 >= -2i0 - i2 + 3i4 }";
2317         bset = isl_basic_set_read_from_str(ctx, str);
2318         f = isl_basic_set_factorizer(bset);
2319         isl_basic_set_free(bset);
2320         isl_factorizer_free(f);
2321         if (!f)
2322                 isl_die(ctx, isl_error_unknown,
2323                         "failed to construct factorizer", return -1);
2324
2325         str = "{ [i0, i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11, i12] : "
2326             "i12 <= 2 + i0 - i11 and 2i8 >= -i4 and i11 >= i1 and "
2327             "3i5 <= -i2 and 2i11 >= -i4 - 2i7 and i11 <= 3 + i0 + 3i9 and "
2328             "i11 <= -i4 - 2i7 and i12 >= -i10 and i2 >= -2 and "
2329             "i11 >= i1 + 3i10 and i11 >= 1 + i0 + 3i9 and "
2330             "i11 <= 1 - i4 - 2i8 and 6i6 <= 6 - i2 and 3i6 >= 1 - i2 and "
2331             "i11 <= 2 + i1 and i12 <= i4 + i11 and i12 >= i0 - i11 and "
2332             "3i5 >= -2 - i2 and i12 >= -1 + i4 + i11 and 3i3 <= 3 - i2 and "
2333             "9i6 <= 11 - i2 + 6i5 and 3i3 >= 1 - i2 and "
2334             "9i6 <= 5 - i2 + 6i3 and i12 <= -1 and i2 <= 0 }";
2335         bset = isl_basic_set_read_from_str(ctx, str);
2336         f = isl_basic_set_factorizer(bset);
2337         isl_basic_set_free(bset);
2338         isl_factorizer_free(f);
2339         if (!f)
2340                 isl_die(ctx, isl_error_unknown,
2341                         "failed to construct factorizer", return -1);
2342
2343         return 0;
2344 }
2345
2346 static int check_injective(__isl_take isl_map *map, void *user)
2347 {
2348         int *injective = user;
2349
2350         *injective = isl_map_is_injective(map);
2351         isl_map_free(map);
2352
2353         if (*injective < 0 || !*injective)
2354                 return -1;
2355
2356         return 0;
2357 }
2358
2359 int test_one_schedule(isl_ctx *ctx, const char *d, const char *w,
2360         const char *r, const char *s, int tilable, int parallel)
2361 {
2362         int i;
2363         isl_union_set *D;
2364         isl_union_map *W, *R, *S;
2365         isl_union_map *empty;
2366         isl_union_map *dep_raw, *dep_war, *dep_waw, *dep;
2367         isl_union_map *validity, *proximity;
2368         isl_union_map *schedule;
2369         isl_union_map *test;
2370         isl_union_set *delta;
2371         isl_union_set *domain;
2372         isl_set *delta_set;
2373         isl_set *slice;
2374         isl_set *origin;
2375         isl_schedule *sched;
2376         int is_nonneg, is_parallel, is_tilable, is_injection, is_complete;
2377
2378         D = isl_union_set_read_from_str(ctx, d);
2379         W = isl_union_map_read_from_str(ctx, w);
2380         R = isl_union_map_read_from_str(ctx, r);
2381         S = isl_union_map_read_from_str(ctx, s);
2382
2383         W = isl_union_map_intersect_domain(W, isl_union_set_copy(D));
2384         R = isl_union_map_intersect_domain(R, isl_union_set_copy(D));
2385
2386         empty = isl_union_map_empty(isl_union_map_get_space(S));
2387         isl_union_map_compute_flow(isl_union_map_copy(R),
2388                                    isl_union_map_copy(W), empty,
2389                                    isl_union_map_copy(S),
2390                                    &dep_raw, NULL, NULL, NULL);
2391         isl_union_map_compute_flow(isl_union_map_copy(W),
2392                                    isl_union_map_copy(W),
2393                                    isl_union_map_copy(R),
2394                                    isl_union_map_copy(S),
2395                                    &dep_waw, &dep_war, NULL, NULL);
2396
2397         dep = isl_union_map_union(dep_waw, dep_war);
2398         dep = isl_union_map_union(dep, dep_raw);
2399         validity = isl_union_map_copy(dep);
2400         proximity = isl_union_map_copy(dep);
2401
2402         sched = isl_union_set_compute_schedule(isl_union_set_copy(D),
2403                                                validity, proximity);
2404         schedule = isl_schedule_get_map(sched);
2405         isl_schedule_free(sched);
2406         isl_union_map_free(W);
2407         isl_union_map_free(R);
2408         isl_union_map_free(S);
2409
2410         is_injection = 1;
2411         isl_union_map_foreach_map(schedule, &check_injective, &is_injection);
2412
2413         domain = isl_union_map_domain(isl_union_map_copy(schedule));
2414         is_complete = isl_union_set_is_subset(D, domain);
2415         isl_union_set_free(D);
2416         isl_union_set_free(domain);
2417
2418         test = isl_union_map_reverse(isl_union_map_copy(schedule));
2419         test = isl_union_map_apply_range(test, dep);
2420         test = isl_union_map_apply_range(test, schedule);
2421
2422         delta = isl_union_map_deltas(test);
2423         if (isl_union_set_n_set(delta) == 0) {
2424                 is_tilable = 1;
2425                 is_parallel = 1;
2426                 is_nonneg = 1;
2427                 isl_union_set_free(delta);
2428         } else {
2429                 delta_set = isl_set_from_union_set(delta);
2430
2431                 slice = isl_set_universe(isl_set_get_space(delta_set));
2432                 for (i = 0; i < tilable; ++i)
2433                         slice = isl_set_lower_bound_si(slice, isl_dim_set, i, 0);
2434                 is_tilable = isl_set_is_subset(delta_set, slice);
2435                 isl_set_free(slice);
2436
2437                 slice = isl_set_universe(isl_set_get_space(delta_set));
2438                 for (i = 0; i < parallel; ++i)
2439                         slice = isl_set_fix_si(slice, isl_dim_set, i, 0);
2440                 is_parallel = isl_set_is_subset(delta_set, slice);
2441                 isl_set_free(slice);
2442
2443                 origin = isl_set_universe(isl_set_get_space(delta_set));
2444                 for (i = 0; i < isl_set_dim(origin, isl_dim_set); ++i)
2445                         origin = isl_set_fix_si(origin, isl_dim_set, i, 0);
2446
2447                 delta_set = isl_set_union(delta_set, isl_set_copy(origin));
2448                 delta_set = isl_set_lexmin(delta_set);
2449
2450                 is_nonneg = isl_set_is_equal(delta_set, origin);
2451
2452                 isl_set_free(origin);
2453                 isl_set_free(delta_set);
2454         }
2455
2456         if (is_nonneg < 0 || is_parallel < 0 || is_tilable < 0 ||
2457             is_injection < 0 || is_complete < 0)
2458                 return -1;
2459         if (!is_complete)
2460                 isl_die(ctx, isl_error_unknown,
2461                         "generated schedule incomplete", return -1);
2462         if (!is_injection)
2463                 isl_die(ctx, isl_error_unknown,
2464                         "generated schedule not injective on each statement",
2465                         return -1);
2466         if (!is_nonneg)
2467                 isl_die(ctx, isl_error_unknown,
2468                         "negative dependences in generated schedule",
2469                         return -1);
2470         if (!is_tilable)
2471                 isl_die(ctx, isl_error_unknown,
2472                         "generated schedule not as tilable as expected",
2473                         return -1);
2474         if (!is_parallel)
2475                 isl_die(ctx, isl_error_unknown,
2476                         "generated schedule not as parallel as expected",
2477                         return -1);
2478
2479         return 0;
2480 }
2481
2482 static __isl_give isl_union_map *compute_schedule(isl_ctx *ctx,
2483         const char *domain, const char *validity, const char *proximity)
2484 {
2485         isl_union_set *dom;
2486         isl_union_map *dep;
2487         isl_union_map *prox;
2488         isl_schedule *schedule;
2489         isl_union_map *sched;
2490
2491         dom = isl_union_set_read_from_str(ctx, domain);
2492         dep = isl_union_map_read_from_str(ctx, validity);
2493         prox = isl_union_map_read_from_str(ctx, proximity);
2494         schedule = isl_union_set_compute_schedule(dom, dep, prox);
2495         sched = isl_schedule_get_map(schedule);
2496         isl_schedule_free(schedule);
2497
2498         return sched;
2499 }
2500
2501 /* Check that a schedule can be constructed on the given domain
2502  * with the given validity and proximity constraints.
2503  */
2504 static int test_has_schedule(isl_ctx *ctx, const char *domain,
2505         const char *validity, const char *proximity)
2506 {
2507         isl_union_map *sched;
2508
2509         sched = compute_schedule(ctx, domain, validity, proximity);
2510         if (!sched)
2511                 return -1;
2512
2513         isl_union_map_free(sched);
2514         return 0;
2515 }
2516
2517 int test_special_schedule(isl_ctx *ctx, const char *domain,
2518         const char *validity, const char *proximity, const char *expected_sched)
2519 {
2520         isl_union_map *sched1, *sched2;
2521         int equal;
2522
2523         sched1 = compute_schedule(ctx, domain, validity, proximity);
2524         sched2 = isl_union_map_read_from_str(ctx, expected_sched);
2525
2526         equal = isl_union_map_is_equal(sched1, sched2);
2527         isl_union_map_free(sched1);
2528         isl_union_map_free(sched2);
2529
2530         if (equal < 0)
2531                 return -1;
2532         if (!equal)
2533                 isl_die(ctx, isl_error_unknown, "unexpected schedule",
2534                         return -1);
2535
2536         return 0;
2537 }
2538
2539 /* Check that the schedule map is properly padded, even after being
2540  * reconstructed from the band forest.
2541  */
2542 static int test_padded_schedule(isl_ctx *ctx)
2543 {
2544         const char *str;
2545         isl_union_set *D;
2546         isl_union_map *validity, *proximity;
2547         isl_schedule *sched;
2548         isl_union_map *map1, *map2;
2549         isl_band_list *list;
2550         int equal;
2551
2552         str = "[N] -> { S0[i] : 0 <= i <= N; S1[i, j] : 0 <= i, j <= N }";
2553         D = isl_union_set_read_from_str(ctx, str);
2554         validity = isl_union_map_empty(isl_union_set_get_space(D));
2555         proximity = isl_union_map_copy(validity);
2556         sched = isl_union_set_compute_schedule(D, validity, proximity);
2557         map1 = isl_schedule_get_map(sched);
2558         list = isl_schedule_get_band_forest(sched);
2559         isl_band_list_free(list);
2560         map2 = isl_schedule_get_map(sched);
2561         isl_schedule_free(sched);
2562         equal = isl_union_map_is_equal(map1, map2);
2563         isl_union_map_free(map1);
2564         isl_union_map_free(map2);
2565
2566         if (equal < 0)
2567                 return -1;
2568         if (!equal)
2569                 isl_die(ctx, isl_error_unknown,
2570                         "reconstructed schedule map not the same as original",
2571                         return -1);
2572
2573         return 0;
2574 }
2575
2576 int test_schedule(isl_ctx *ctx)
2577 {
2578         const char *D, *W, *R, *V, *P, *S;
2579
2580         /* Handle resulting schedule with zero bands. */
2581         if (test_one_schedule(ctx, "{[]}", "{}", "{}", "{[] -> []}", 0, 0) < 0)
2582                 return -1;
2583
2584         /* Jacobi */
2585         D = "[T,N] -> { S1[t,i] : 1 <= t <= T and 2 <= i <= N - 1 }";
2586         W = "{ S1[t,i] -> a[t,i] }";
2587         R = "{ S1[t,i] -> a[t-1,i]; S1[t,i] -> a[t-1,i-1]; "
2588                 "S1[t,i] -> a[t-1,i+1] }";
2589         S = "{ S1[t,i] -> [t,i] }";
2590         if (test_one_schedule(ctx, D, W, R, S, 2, 0) < 0)
2591                 return -1;
2592
2593         /* Fig. 5 of CC2008 */
2594         D = "[N] -> { S_0[i, j] : i >= 0 and i <= -1 + N and j >= 2 and "
2595                                 "j <= -1 + N }";
2596         W = "[N] -> { S_0[i, j] -> a[i, j] : i >= 0 and i <= -1 + N and "
2597                                 "j >= 2 and j <= -1 + N }";
2598         R = "[N] -> { S_0[i, j] -> a[j, i] : i >= 0 and i <= -1 + N and "
2599                                 "j >= 2 and j <= -1 + N; "
2600                     "S_0[i, j] -> a[i, -1 + j] : i >= 0 and i <= -1 + N and "
2601                                 "j >= 2 and j <= -1 + N }";
2602         S = "[N] -> { S_0[i, j] -> [0, i, 0, j, 0] }";
2603         if (test_one_schedule(ctx, D, W, R, S, 2, 0) < 0)
2604                 return -1;
2605
2606         D = "{ S1[i] : 0 <= i <= 10; S2[i] : 0 <= i <= 9 }";
2607         W = "{ S1[i] -> a[i] }";
2608         R = "{ S2[i] -> a[i+1] }";
2609         S = "{ S1[i] -> [0,i]; S2[i] -> [1,i] }";
2610         if (test_one_schedule(ctx, D, W, R, S, 1, 1) < 0)
2611                 return -1;
2612
2613         D = "{ S1[i] : 0 <= i < 10; S2[i] : 0 <= i < 10 }";
2614         W = "{ S1[i] -> a[i] }";
2615         R = "{ S2[i] -> a[9-i] }";
2616         S = "{ S1[i] -> [0,i]; S2[i] -> [1,i] }";
2617         if (test_one_schedule(ctx, D, W, R, S, 1, 1) < 0)
2618                 return -1;
2619
2620         D = "[N] -> { S1[i] : 0 <= i < N; S2[i] : 0 <= i < N }";
2621         W = "{ S1[i] -> a[i] }";
2622         R = "[N] -> { S2[i] -> a[N-1-i] }";
2623         S = "{ S1[i] -> [0,i]; S2[i] -> [1,i] }";
2624         if (test_one_schedule(ctx, D, W, R, S, 1, 1) < 0)
2625                 return -1;
2626         
2627         D = "{ S1[i] : 0 < i < 10; S2[i] : 0 <= i < 10 }";
2628         W = "{ S1[i] -> a[i]; S2[i] -> b[i] }";
2629         R = "{ S2[i] -> a[i]; S1[i] -> b[i-1] }";
2630         S = "{ S1[i] -> [i,0]; S2[i] -> [i,1] }";
2631         if (test_one_schedule(ctx, D, W, R, S, 0, 0) < 0)
2632                 return -1;
2633
2634         D = "[N] -> { S1[i] : 1 <= i <= N; S2[i,j] : 1 <= i,j <= N }";
2635         W = "{ S1[i] -> a[0,i]; S2[i,j] -> a[i,j] }";
2636         R = "{ S2[i,j] -> a[i-1,j] }";
2637         S = "{ S1[i] -> [0,i,0]; S2[i,j] -> [1,i,j] }";
2638         if (test_one_schedule(ctx, D, W, R, S, 2, 1) < 0)
2639                 return -1;
2640
2641         D = "[N] -> { S1[i] : 1 <= i <= N; S2[i,j] : 1 <= i,j <= N }";
2642         W = "{ S1[i] -> a[i,0]; S2[i,j] -> a[i,j] }";
2643         R = "{ S2[i,j] -> a[i,j-1] }";
2644         S = "{ S1[i] -> [0,i,0]; S2[i,j] -> [1,i,j] }";
2645         if (test_one_schedule(ctx, D, W, R, S, 2, 1) < 0)
2646                 return -1;
2647
2648         D = "[N] -> { S_0[]; S_1[i] : i >= 0 and i <= -1 + N; S_2[] }";
2649         W = "[N] -> { S_0[] -> a[0]; S_2[] -> b[0]; "
2650                     "S_1[i] -> a[1 + i] : i >= 0 and i <= -1 + N }";
2651         R = "[N] -> { S_2[] -> a[N]; S_1[i] -> a[i] : i >= 0 and i <= -1 + N }";
2652         S = "[N] -> { S_1[i] -> [1, i, 0]; S_2[] -> [2, 0, 1]; "
2653                     "S_0[] -> [0, 0, 0] }";
2654         if (test_one_schedule(ctx, D, W, R, S, 1, 0) < 0)
2655                 return -1;
2656         ctx->opt->schedule_parametric = 0;
2657         if (test_one_schedule(ctx, D, W, R, S, 0, 0) < 0)
2658                 return -1;
2659         ctx->opt->schedule_parametric = 1;
2660
2661         D = "[N] -> { S1[i] : 1 <= i <= N; S2[i] : 1 <= i <= N; "
2662                     "S3[i,j] : 1 <= i,j <= N; S4[i] : 1 <= i <= N }";
2663         W = "{ S1[i] -> a[i,0]; S2[i] -> a[0,i]; S3[i,j] -> a[i,j] }";
2664         R = "[N] -> { S3[i,j] -> a[i-1,j]; S3[i,j] -> a[i,j-1]; "
2665                     "S4[i] -> a[i,N] }";
2666         S = "{ S1[i] -> [0,i,0]; S2[i] -> [1,i,0]; S3[i,j] -> [2,i,j]; "
2667                 "S4[i] -> [4,i,0] }";
2668         if (test_one_schedule(ctx, D, W, R, S, 2, 0) < 0)
2669                 return -1;
2670
2671         D = "[N] -> { S_0[i, j] : i >= 1 and i <= N and j >= 1 and j <= N }";
2672         W = "[N] -> { S_0[i, j] -> s[0] : i >= 1 and i <= N and j >= 1 and "
2673                                         "j <= N }";
2674         R = "[N] -> { S_0[i, j] -> s[0] : i >= 1 and i <= N and j >= 1 and "
2675                                         "j <= N; "
2676                     "S_0[i, j] -> a[i, j] : i >= 1 and i <= N and j >= 1 and "
2677                                         "j <= N }";
2678         S = "[N] -> { S_0[i, j] -> [0, i, 0, j, 0] }";
2679         if (test_one_schedule(ctx, D, W, R, S, 0, 0) < 0)
2680                 return -1;
2681
2682         D = "[N] -> { S_0[t] : t >= 0 and t <= -1 + N; "
2683                     " S_2[t] : t >= 0 and t <= -1 + N; "
2684                     " S_1[t, i] : t >= 0 and t <= -1 + N and i >= 0 and "
2685                                 "i <= -1 + N }";
2686         W = "[N] -> { S_0[t] -> a[t, 0] : t >= 0 and t <= -1 + N; "
2687                     " S_2[t] -> b[t] : t >= 0 and t <= -1 + N; "
2688                     " S_1[t, i] -> a[t, 1 + i] : t >= 0 and t <= -1 + N and "
2689                                                 "i >= 0 and i <= -1 + N }";
2690         R = "[N] -> { S_1[t, i] -> a[t, i] : t >= 0 and t <= -1 + N and "
2691                                             "i >= 0 and i <= -1 + N; "
2692                     " S_2[t] -> a[t, N] : t >= 0 and t <= -1 + N }";
2693         S = "[N] -> { S_2[t] -> [0, t, 2]; S_1[t, i] -> [0, t, 1, i, 0]; "
2694                     " S_0[t] -> [0, t, 0] }";
2695
2696         if (test_one_schedule(ctx, D, W, R, S, 2, 1) < 0)
2697                 return -1;
2698         ctx->opt->schedule_parametric = 0;
2699         if (test_one_schedule(ctx, D, W, R, S, 0, 0) < 0)
2700                 return -1;
2701         ctx->opt->schedule_parametric = 1;
2702
2703         D = "[N] -> { S1[i,j] : 0 <= i,j < N; S2[i,j] : 0 <= i,j < N }";
2704         S = "{ S1[i,j] -> [0,i,j]; S2[i,j] -> [1,i,j] }";
2705         if (test_one_schedule(ctx, D, "{}", "{}", S, 2, 2) < 0)
2706                 return -1;
2707
2708         D = "[M, N] -> { S_1[i] : i >= 0 and i <= -1 + M; "
2709             "S_0[i, j] : i >= 0 and i <= -1 + M and j >= 0 and j <= -1 + N }";
2710         W = "[M, N] -> { S_0[i, j] -> a[j] : i >= 0 and i <= -1 + M and "
2711                                             "j >= 0 and j <= -1 + N; "
2712                         "S_1[i] -> b[0] : i >= 0 and i <= -1 + M }";
2713         R = "[M, N] -> { S_0[i, j] -> a[0] : i >= 0 and i <= -1 + M and "
2714                                             "j >= 0 and j <= -1 + N; "
2715                         "S_1[i] -> b[0] : i >= 0 and i <= -1 + M }";
2716         S = "[M, N] -> { S_1[i] -> [1, i, 0]; S_0[i, j] -> [0, i, 0, j, 0] }";
2717         if (test_one_schedule(ctx, D, W, R, S, 0, 0) < 0)
2718                 return -1;
2719
2720         D = "{ S_0[i] : i >= 0 }";
2721         W = "{ S_0[i] -> a[i] : i >= 0 }";
2722         R = "{ S_0[i] -> a[0] : i >= 0 }";
2723         S = "{ S_0[i] -> [0, i, 0] }";
2724         if (test_one_schedule(ctx, D, W, R, S, 0, 0) < 0)
2725                 return -1;
2726
2727         D = "{ S_0[i] : i >= 0; S_1[i] : i >= 0 }";
2728         W = "{ S_0[i] -> a[i] : i >= 0; S_1[i] -> b[i] : i >= 0 }";
2729         R = "{ S_0[i] -> b[0] : i >= 0; S_1[i] -> a[i] : i >= 0 }";
2730         S = "{ S_1[i] -> [0, i, 1]; S_0[i] -> [0, i, 0] }";
2731         if (test_one_schedule(ctx, D, W, R, S, 0, 0) < 0)
2732                 return -1;
2733
2734         D = "[n] -> { S_0[j, k] : j <= -1 + n and j >= 0 and "
2735                                 "k <= -1 + n and k >= 0 }";
2736         W = "[n] -> { S_0[j, k] -> B[j] : j <= -1 + n and j >= 0 and "                                                  "k <= -1 + n and k >= 0 }";
2737         R = "[n] -> { S_0[j, k] -> B[j] : j <= -1 + n and j >= 0 and "
2738                                         "k <= -1 + n and k >= 0; "
2739                     "S_0[j, k] -> B[k] : j <= -1 + n and j >= 0 and "
2740                                         "k <= -1 + n and k >= 0; "
2741                     "S_0[j, k] -> A[k] : j <= -1 + n and j >= 0 and "
2742                                         "k <= -1 + n and k >= 0 }";
2743         S = "[n] -> { S_0[j, k] -> [2, j, k] }";
2744         ctx->opt->schedule_outer_zero_distance = 1;
2745         if (test_one_schedule(ctx, D, W, R, S, 0, 0) < 0)
2746                 return -1;
2747         ctx->opt->schedule_outer_zero_distance = 0;
2748
2749         D = "{Stmt_for_body24[i0, i1, i2, i3]:"
2750                 "i0 >= 0 and i0 <= 1 and i1 >= 0 and i1 <= 6 and i2 >= 2 and "
2751                 "i2 <= 6 - i1 and i3 >= 0 and i3 <= -1 + i2;"
2752              "Stmt_for_body24[i0, i1, 1, 0]:"
2753                 "i0 >= 0 and i0 <= 1 and i1 >= 0 and i1 <= 5;"
2754              "Stmt_for_body7[i0, i1, i2]:"
2755                 "i0 >= 0 and i0 <= 1 and i1 >= 0 and i1 <= 7 and i2 >= 0 and "
2756                 "i2 <= 7 }";
2757
2758         V = "{Stmt_for_body24[0, i1, i2, i3] -> "
2759                 "Stmt_for_body24[1, i1, i2, i3]:"
2760                 "i3 >= 0 and i3 <= -1 + i2 and i1 >= 0 and i2 <= 6 - i1 and "
2761                 "i2 >= 1;"
2762              "Stmt_for_body24[0, i1, i2, i3] -> "
2763                 "Stmt_for_body7[1, 1 + i1 + i3, 1 + i1 + i2]:"
2764                 "i3 <= -1 + i2 and i2 <= 6 - i1 and i2 >= 1 and i1 >= 0 and "
2765                 "i3 >= 0;"
2766               "Stmt_for_body24[0, i1, i2, i3] ->"
2767                 "Stmt_for_body7[1, i1, 1 + i1 + i3]:"
2768                 "i3 >= 0 and i2 <= 6 - i1 and i1 >= 0 and i3 <= -1 + i2;"
2769               "Stmt_for_body7[0, i1, i2] -> Stmt_for_body7[1, i1, i2]:"
2770                 "(i2 >= 1 + i1 and i2 <= 6 and i1 >= 0 and i1 <= 4) or "
2771                 "(i2 >= 3 and i2 <= 7 and i1 >= 1 and i2 >= 1 + i1) or "
2772                 "(i2 >= 0 and i2 <= i1 and i2 >= -7 + i1 and i1 <= 7);"
2773               "Stmt_for_body7[0, i1, 1 + i1] -> Stmt_for_body7[1, i1, 1 + i1]:"
2774                 "i1 <= 6 and i1 >= 0;"
2775               "Stmt_for_body7[0, 0, 7] -> Stmt_for_body7[1, 0, 7];"
2776               "Stmt_for_body7[i0, i1, i2] -> "
2777                 "Stmt_for_body24[i0, o1, -1 + i2 - o1, -1 + i1 - o1]:"
2778                 "i0 >= 0 and i0 <= 1 and o1 >= 0 and i2 >= 1 + i1 and "
2779                 "o1 <= -2 + i2 and i2 <= 7 and o1 <= -1 + i1;"
2780               "Stmt_for_body7[i0, i1, i2] -> "
2781                 "Stmt_for_body24[i0, i1, o2, -1 - i1 + i2]:"
2782                 "i0 >= 0 and i0 <= 1 and i1 >= 0 and o2 >= -i1 + i2 and "
2783                 "o2 >= 1 and o2 <= 6 - i1 and i2 >= 1 + i1 }";
2784         P = V;
2785         S = "{ Stmt_for_body24[i0, i1, i2, i3] -> "
2786                 "[i0, 5i0 + i1, 6i0 + i1 + i2, 1 + 6i0 + i1 + i2 + i3, 1];"
2787             "Stmt_for_body7[i0, i1, i2] -> [0, 5i0, 6i0 + i1, 6i0 + i2, 0] }";
2788
2789         if (test_special_schedule(ctx, D, V, P, S) < 0)
2790                 return -1;
2791
2792         D = "{ S_0[i, j] : i >= 1 and i <= 10 and j >= 1 and j <= 8 }";
2793         V = "{ S_0[i, j] -> S_0[i, 1 + j] : i >= 1 and i <= 10 and "
2794                                            "j >= 1 and j <= 7;"
2795                 "S_0[i, j] -> S_0[1 + i, j] : i >= 1 and i <= 9 and "
2796                                              "j >= 1 and j <= 8 }";
2797         P = "{ }";
2798         S = "{ S_0[i, j] -> [i + j, j] }";
2799         ctx->opt->schedule_algorithm = ISL_SCHEDULE_ALGORITHM_FEAUTRIER;
2800         if (test_special_schedule(ctx, D, V, P, S) < 0)
2801                 return -1;
2802         ctx->opt->schedule_algorithm = ISL_SCHEDULE_ALGORITHM_ISL;
2803
2804         /* Fig. 1 from Feautrier's "Some Efficient Solutions..." pt. 2, 1992 */
2805         D = "[N] -> { S_0[i, j] : i >= 0 and i <= -1 + N and "
2806                                  "j >= 0 and j <= -1 + i }";
2807         V = "[N] -> { S_0[i, j] -> S_0[i, 1 + j] : j <= -2 + i and "
2808                                         "i <= -1 + N and j >= 0;"
2809                      "S_0[i, -1 + i] -> S_0[1 + i, 0] : i >= 1 and "
2810                                         "i <= -2 + N }";
2811         P = "{ }";
2812         S = "{ S_0[i, j] -> [i, j] }";
2813         ctx->opt->schedule_algorithm = ISL_SCHEDULE_ALGORITHM_FEAUTRIER;
2814         if (test_special_schedule(ctx, D, V, P, S) < 0)
2815                 return -1;
2816         ctx->opt->schedule_algorithm = ISL_SCHEDULE_ALGORITHM_ISL;
2817
2818         /* Test both algorithms on a case with only proximity dependences. */
2819         D = "{ S[i,j] : 0 <= i <= 10 }";
2820         V = "{ }";
2821         P = "{ S[i,j] -> S[i+1,j] : 0 <= i,j <= 10 }";
2822         S = "{ S[i, j] -> [j, i] }";
2823         ctx->opt->schedule_algorithm = ISL_SCHEDULE_ALGORITHM_FEAUTRIER;
2824         if (test_special_schedule(ctx, D, V, P, S) < 0)
2825                 return -1;
2826         ctx->opt->schedule_algorithm = ISL_SCHEDULE_ALGORITHM_ISL;
2827         if (test_special_schedule(ctx, D, V, P, S) < 0)
2828                 return -1;
2829         
2830         D = "{ A[a]; B[] }";
2831         V = "{}";
2832         P = "{ A[a] -> B[] }";
2833         if (test_has_schedule(ctx, D, V, P) < 0)
2834                 return -1;
2835
2836         if (test_padded_schedule(ctx) < 0)
2837                 return -1;
2838
2839         /* Check that check for progress is not confused by rational
2840          * solution.
2841          */
2842         D = "[N] -> { S0[i, j] : i >= 0 and i <= N and j >= 0 and j <= N }";
2843         V = "[N] -> { S0[i0, -1 + N] -> S0[2 + i0, 0] : i0 >= 0 and "
2844                                                         "i0 <= -2 + N; "
2845                         "S0[i0, i1] -> S0[i0, 1 + i1] : i0 >= 0 and "
2846                                 "i0 <= N and i1 >= 0 and i1 <= -1 + N }";
2847         P = "{}";
2848         ctx->opt->schedule_algorithm = ISL_SCHEDULE_ALGORITHM_FEAUTRIER;
2849         if (test_has_schedule(ctx, D, V, P) < 0)
2850                 return -1;
2851         ctx->opt->schedule_algorithm = ISL_SCHEDULE_ALGORITHM_ISL;
2852
2853         return 0;
2854 }
2855
2856 int test_plain_injective(isl_ctx *ctx, const char *str, int injective)
2857 {
2858         isl_union_map *umap;
2859         int test;
2860
2861         umap = isl_union_map_read_from_str(ctx, str);
2862         test = isl_union_map_plain_is_injective(umap);
2863         isl_union_map_free(umap);
2864         if (test < 0)
2865                 return -1;
2866         if (test == injective)
2867                 return 0;
2868         if (injective)
2869                 isl_die(ctx, isl_error_unknown,
2870                         "map not detected as injective", return -1);
2871         else
2872                 isl_die(ctx, isl_error_unknown,
2873                         "map detected as injective", return -1);
2874 }
2875
2876 int test_injective(isl_ctx *ctx)
2877 {
2878         const char *str;
2879
2880         if (test_plain_injective(ctx, "{S[i,j] -> A[0]; T[i,j] -> B[1]}", 0))
2881                 return -1;
2882         if (test_plain_injective(ctx, "{S[] -> A[0]; T[] -> B[0]}", 1))
2883                 return -1;
2884         if (test_plain_injective(ctx, "{S[] -> A[0]; T[] -> A[1]}", 1))
2885                 return -1;
2886         if (test_plain_injective(ctx, "{S[] -> A[0]; T[] -> A[0]}", 0))
2887                 return -1;
2888         if (test_plain_injective(ctx, "{S[i] -> A[i,0]; T[i] -> A[i,1]}", 1))
2889                 return -1;
2890         if (test_plain_injective(ctx, "{S[i] -> A[i]; T[i] -> A[i]}", 0))
2891                 return -1;
2892         if (test_plain_injective(ctx, "{S[] -> A[0,0]; T[] -> A[0,1]}", 1))
2893                 return -1;
2894         if (test_plain_injective(ctx, "{S[] -> A[0,0]; T[] -> A[1,0]}", 1))
2895                 return -1;
2896
2897         str = "{S[] -> A[0,0]; T[] -> A[0,1]; U[] -> A[1,0]}";
2898         if (test_plain_injective(ctx, str, 1))
2899                 return -1;
2900         str = "{S[] -> A[0,0]; T[] -> A[0,1]; U[] -> A[0,0]}";
2901         if (test_plain_injective(ctx, str, 0))
2902                 return -1;
2903
2904         return 0;
2905 }
2906
2907 static int aff_plain_is_equal(__isl_keep isl_aff *aff, const char *str)
2908 {
2909         isl_aff *aff2;
2910         int equal;
2911
2912         if (!aff)
2913                 return -1;
2914
2915         aff2 = isl_aff_read_from_str(isl_aff_get_ctx(aff), str);
2916         equal = isl_aff_plain_is_equal(aff, aff2);
2917         isl_aff_free(aff2);
2918
2919         return equal;
2920 }
2921
2922 static int aff_check_plain_equal(__isl_keep isl_aff *aff, const char *str)
2923 {
2924         int equal;
2925
2926         equal = aff_plain_is_equal(aff, str);
2927         if (equal < 0)
2928                 return -1;
2929         if (!equal)
2930                 isl_die(isl_aff_get_ctx(aff), isl_error_unknown,
2931                         "result not as expected", return -1);
2932         return 0;
2933 }
2934
2935 int test_aff(isl_ctx *ctx)
2936 {
2937         const char *str;
2938         isl_set *set;
2939         isl_space *space;
2940         isl_local_space *ls;
2941         isl_aff *aff;
2942         int zero, equal;
2943
2944         space = isl_space_set_alloc(ctx, 0, 1);
2945         ls = isl_local_space_from_space(space);
2946         aff = isl_aff_zero_on_domain(ls);
2947
2948         aff = isl_aff_add_coefficient_si(aff, isl_dim_in, 0, 1);
2949         aff = isl_aff_scale_down_ui(aff, 3);
2950         aff = isl_aff_floor(aff);
2951         aff = isl_aff_add_coefficient_si(aff, isl_dim_in, 0, 1);
2952         aff = isl_aff_scale_down_ui(aff, 2);
2953         aff = isl_aff_floor(aff);
2954         aff = isl_aff_add_coefficient_si(aff, isl_dim_in, 0, 1);
2955
2956         str = "{ [10] }";
2957         set = isl_set_read_from_str(ctx, str);
2958         aff = isl_aff_gist(aff, set);
2959
2960         aff = isl_aff_add_constant_si(aff, -16);
2961         zero = isl_aff_plain_is_zero(aff);
2962         isl_aff_free(aff);
2963
2964         if (zero < 0)
2965                 return -1;
2966         if (!zero)
2967                 isl_die(ctx, isl_error_unknown, "unexpected result", return -1);
2968
2969         aff = isl_aff_read_from_str(ctx, "{ [-1] }");
2970         aff = isl_aff_scale_down_ui(aff, 64);
2971         aff = isl_aff_floor(aff);
2972         equal = aff_check_plain_equal(aff, "{ [-1] }");
2973         isl_aff_free(aff);
2974         if (equal < 0)
2975                 return -1;
2976
2977         return 0;
2978 }
2979
2980 int test_dim_max(isl_ctx *ctx)
2981 {
2982         int equal;
2983         const char *str;
2984         isl_set *set1, *set2;
2985         isl_set *set;
2986         isl_map *map;
2987         isl_pw_aff *pwaff;
2988
2989         str = "[N] -> { [i] : 0 <= i <= min(N,10) }";
2990         set = isl_set_read_from_str(ctx, str);
2991         pwaff = isl_set_dim_max(set, 0);
2992         set1 = isl_set_from_pw_aff(pwaff);
2993         str = "[N] -> { [10] : N >= 10; [N] : N <= 9 and N >= 0 }";
2994         set2 = isl_set_read_from_str(ctx, str);
2995         equal = isl_set_is_equal(set1, set2);
2996         isl_set_free(set1);
2997         isl_set_free(set2);
2998         if (equal < 0)
2999                 return -1;
3000         if (!equal)
3001                 isl_die(ctx, isl_error_unknown, "unexpected result", return -1);
3002
3003         str = "[N] -> { [i] : 0 <= i <= max(2N,N+6) }";
3004         set = isl_set_read_from_str(ctx, str);
3005         pwaff = isl_set_dim_max(set, 0);
3006         set1 = isl_set_from_pw_aff(pwaff);
3007         str = "[N] -> { [6 + N] : -6 <= N <= 5; [2N] : N >= 6 }";
3008         set2 = isl_set_read_from_str(ctx, str);
3009         equal = isl_set_is_equal(set1, set2);
3010         isl_set_free(set1);
3011         isl_set_free(set2);
3012         if (equal < 0)
3013                 return -1;
3014         if (!equal)
3015                 isl_die(ctx, isl_error_unknown, "unexpected result", return -1);
3016
3017         str = "[N] -> { [i] : 0 <= i <= 2N or 0 <= i <= N+6 }";
3018         set = isl_set_read_from_str(ctx, str);
3019         pwaff = isl_set_dim_max(set, 0);
3020         set1 = isl_set_from_pw_aff(pwaff);
3021         str = "[N] -> { [6 + N] : -6 <= N <= 5; [2N] : N >= 6 }";
3022         set2 = isl_set_read_from_str(ctx, str);
3023         equal = isl_set_is_equal(set1, set2);
3024         isl_set_free(set1);
3025         isl_set_free(set2);
3026         if (equal < 0)
3027                 return -1;
3028         if (!equal)
3029                 isl_die(ctx, isl_error_unknown, "unexpected result", return -1);
3030
3031         str = "[N,M] -> { [i,j] -> [([i/16]), i%16, ([j/16]), j%16] : "
3032                         "0 <= i < N and 0 <= j < M }";
3033         map = isl_map_read_from_str(ctx, str);
3034         set = isl_map_range(map);
3035
3036         pwaff = isl_set_dim_max(isl_set_copy(set), 0);
3037         set1 = isl_set_from_pw_aff(pwaff);
3038         str = "[N,M] -> { [([(N-1)/16])] : M,N > 0 }";
3039         set2 = isl_set_read_from_str(ctx, str);
3040         equal = isl_set_is_equal(set1, set2);
3041         isl_set_free(set1);
3042         isl_set_free(set2);
3043
3044         pwaff = isl_set_dim_max(isl_set_copy(set), 3);
3045         set1 = isl_set_from_pw_aff(pwaff);
3046         str = "[N,M] -> { [t] : t = min(M-1,15) and M,N > 0 }";
3047         set2 = isl_set_read_from_str(ctx, str);
3048         if (equal >= 0 && equal)
3049                 equal = isl_set_is_equal(set1, set2);
3050         isl_set_free(set1);
3051         isl_set_free(set2);
3052
3053         isl_set_free(set);
3054
3055         if (equal < 0)
3056                 return -1;
3057         if (!equal)
3058                 isl_die(ctx, isl_error_unknown, "unexpected result", return -1);
3059
3060         /* Check that solutions are properly merged. */
3061         str = "[n] -> { [a, b, c] : c >= -4a - 2b and "
3062                                 "c <= -1 + n - 4a - 2b and c >= -2b and "
3063                                 "4a >= -4 + n and c >= 0 }";
3064         set = isl_set_read_from_str(ctx, str);
3065         pwaff = isl_set_dim_min(set, 2);
3066         set1 = isl_set_from_pw_aff(pwaff);
3067         str = "[n] -> { [(0)] : n >= 1 }";
3068         set2 = isl_set_read_from_str(ctx, str);
3069         equal = isl_set_is_equal(set1, set2);
3070         isl_set_free(set1);
3071         isl_set_free(set2);
3072
3073         if (equal < 0)
3074                 return -1;
3075         if (!equal)
3076                 isl_die(ctx, isl_error_unknown, "unexpected result", return -1);
3077
3078         return 0;
3079 }
3080
3081 int test_product(isl_ctx *ctx)
3082 {
3083         const char *str;
3084         isl_set *set;
3085         isl_union_set *uset1, *uset2;
3086         int ok;
3087
3088         str = "{ A[i] }";
3089         set = isl_set_read_from_str(ctx, str);
3090         set = isl_set_product(set, isl_set_copy(set));
3091         ok = isl_set_is_wrapping(set);
3092         isl_set_free(set);
3093         if (ok < 0)
3094                 return -1;
3095         if (!ok)
3096                 isl_die(ctx, isl_error_unknown, "unexpected result", return -1);
3097
3098         str = "{ [] }";
3099         uset1 = isl_union_set_read_from_str(ctx, str);
3100         uset1 = isl_union_set_product(uset1, isl_union_set_copy(uset1));
3101         str = "{ [[] -> []] }";
3102         uset2 = isl_union_set_read_from_str(ctx, str);
3103         ok = isl_union_set_is_equal(uset1, uset2);
3104         isl_union_set_free(uset1);
3105         isl_union_set_free(uset2);
3106         if (ok < 0)
3107                 return -1;
3108         if (!ok)
3109                 isl_die(ctx, isl_error_unknown, "unexpected result", return -1);
3110
3111         return 0;
3112 }
3113
3114 int test_equal(isl_ctx *ctx)
3115 {
3116         const char *str;
3117         isl_set *set, *set2;
3118         int equal;
3119
3120         str = "{ S_6[i] }";
3121         set = isl_set_read_from_str(ctx, str);
3122         str = "{ S_7[i] }";
3123         set2 = isl_set_read_from_str(ctx, str);
3124         equal = isl_set_is_equal(set, set2);
3125         isl_set_free(set);
3126         isl_set_free(set2);
3127         if (equal < 0)
3128                 return -1;
3129         if (equal)
3130                 isl_die(ctx, isl_error_unknown, "unexpected result", return -1);
3131
3132         return 0;
3133 }
3134
3135 static int test_plain_fixed(isl_ctx *ctx, __isl_take isl_map *map,
3136         enum isl_dim_type type, unsigned pos, int fixed)
3137 {
3138         int test;
3139
3140         test = isl_map_plain_is_fixed(map, type, pos, NULL);
3141         isl_map_free(map);
3142         if (test < 0)
3143                 return -1;
3144         if (test == fixed)
3145                 return 0;
3146         if (fixed)
3147                 isl_die(ctx, isl_error_unknown,
3148                         "map not detected as fixed", return -1);
3149         else
3150                 isl_die(ctx, isl_error_unknown,
3151                         "map detected as fixed", return -1);
3152 }
3153
3154 int test_fixed(isl_ctx *ctx)
3155 {
3156         const char *str;
3157         isl_map *map;
3158
3159         str = "{ [i] -> [i] }";
3160         map = isl_map_read_from_str(ctx, str);
3161         if (test_plain_fixed(ctx, map, isl_dim_out, 0, 0))
3162                 return -1;
3163         str = "{ [i] -> [1] }";
3164         map = isl_map_read_from_str(ctx, str);
3165         if (test_plain_fixed(ctx, map, isl_dim_out, 0, 1))
3166                 return -1;
3167         str = "{ S_1[p1] -> [o0] : o0 = -2 and p1 >= 1 and p1 <= 7 }";
3168         map = isl_map_read_from_str(ctx, str);
3169         if (test_plain_fixed(ctx, map, isl_dim_out, 0, 1))
3170                 return -1;
3171         map = isl_map_read_from_str(ctx, str);
3172         map = isl_map_neg(map);
3173         if (test_plain_fixed(ctx, map, isl_dim_out, 0, 1))
3174                 return -1;
3175
3176         return 0;
3177 }
3178
3179 int test_vertices(isl_ctx *ctx)
3180 {
3181         const char *str;
3182         isl_basic_set *bset;
3183         isl_vertices *vertices;
3184
3185         str = "{ A[t, i] : t = 12 and i >= 4 and i <= 12 }";
3186         bset = isl_basic_set_read_from_str(ctx, str);
3187         vertices = isl_basic_set_compute_vertices(bset);
3188         isl_basic_set_free(bset);
3189         isl_vertices_free(vertices);
3190         if (!vertices)
3191                 return -1;
3192
3193         str = "{ A[t, i] : t = 14 and i = 1 }";
3194         bset = isl_basic_set_read_from_str(ctx, str);
3195         vertices = isl_basic_set_compute_vertices(bset);
3196         isl_basic_set_free(bset);
3197         isl_vertices_free(vertices);
3198         if (!vertices)
3199                 return -1;
3200
3201         return 0;
3202 }
3203
3204 int test_union_pw(isl_ctx *ctx)
3205 {
3206         int equal;
3207         const char *str;
3208         isl_union_set *uset;
3209         isl_union_pw_qpolynomial *upwqp1, *upwqp2;
3210
3211         str = "{ [x] -> x^2 }";
3212         upwqp1 = isl_union_pw_qpolynomial_read_from_str(ctx, str);
3213         upwqp2 = isl_union_pw_qpolynomial_copy(upwqp1);
3214         uset = isl_union_pw_qpolynomial_domain(upwqp1);
3215         upwqp1 = isl_union_pw_qpolynomial_copy(upwqp2);
3216         upwqp1 = isl_union_pw_qpolynomial_intersect_domain(upwqp1, uset);
3217         equal = isl_union_pw_qpolynomial_plain_is_equal(upwqp1, upwqp2);
3218         isl_union_pw_qpolynomial_free(upwqp1);
3219         isl_union_pw_qpolynomial_free(upwqp2);
3220         if (equal < 0)
3221                 return -1;
3222         if (!equal)
3223                 isl_die(ctx, isl_error_unknown, "unexpected result", return -1);
3224
3225         return 0;
3226 }
3227
3228 int test_output(isl_ctx *ctx)
3229 {
3230         char *s;
3231         const char *str;
3232         isl_pw_aff *pa;
3233         isl_printer *p;
3234         int equal;
3235
3236         str = "[x] -> { [1] : x % 4 <= 2; [2] : x = 3 }";
3237         pa = isl_pw_aff_read_from_str(ctx, str);
3238
3239         p = isl_printer_to_str(ctx);
3240         p = isl_printer_set_output_format(p, ISL_FORMAT_C);
3241         p = isl_printer_print_pw_aff(p, pa);
3242         s = isl_printer_get_str(p);
3243         isl_printer_free(p);
3244         isl_pw_aff_free(pa);
3245         if (!s)
3246                 equal = -1;
3247         else
3248                 equal = !strcmp(s, "(2 - x + 4*floord(x, 4) >= 0) ? (1) : 2");
3249         free(s);
3250         if (equal < 0)
3251                 return -1;
3252         if (!equal)
3253                 isl_die(ctx, isl_error_unknown, "unexpected result", return -1);
3254
3255         return 0;
3256 }
3257
3258 int test_sample(isl_ctx *ctx)
3259 {
3260         const char *str;
3261         isl_basic_set *bset1, *bset2;
3262         int empty, subset;
3263
3264         str = "{ [a, b, c, d, e, f, g, h, i, j, k] : "
3265             "3i >= 1073741823b - c - 1073741823e + f and c >= 0 and "
3266             "3i >= -1 + 3221225466b + c + d - 3221225466e - f and "
3267             "2e >= a - b and 3e <= 2a and 3k <= -a and f <= -1 + a and "
3268             "3i <= 4 - a + 4b + 2c - e - 2f and 3k <= -a + c - f and "
3269             "3h >= -2 + a and 3g >= -3 - a and 3k >= -2 - a and "
3270             "3i >= -2 - a - 2c + 3e + 2f and 3h <= a + c - f and "
3271             "3h >= a + 2147483646b + 2c - 2147483646e - 2f and "
3272             "3g <= -1 - a and 3i <= 1 + c + d - f and a <= 1073741823 and "
3273             "f >= 1 - a + 1073741822b + c + d - 1073741822e and "
3274             "3i >= 1 + 2b - 2c + e + 2f + 3g and "
3275             "1073741822f <= 1073741822 - a + 1073741821b + 1073741822c +"
3276                 "d - 1073741821e and "
3277             "3j <= 3 - a + 3b and 3g <= -2 - 2b + c + d - e - f and "
3278             "3j >= 1 - a + b + 2e and "
3279             "3f >= -3 + a + 3221225462b + 3c + d - 3221225465e and "
3280             "3i <= 4 - a + 4b - e and "
3281             "f <= 1073741822 + 1073741822b - 1073741822e and 3h <= a and "
3282             "f >= 0 and 2e <= 4 - a + 5b - d and 2e <= a - b + d and "
3283             "c <= -1 + a and 3i >= -2 - a + 3e and "
3284             "1073741822e <= 1073741823 - a + 1073741822b + c and "
3285             "3g >= -4 + 3221225464b + 3c + d - 3221225467e - 3f and "
3286             "3i >= -1 + 3221225466b + 3c + d - 3221225466e - 3f and "
3287             "1073741823e >= 1 + 1073741823b - d and "
3288             "3i >= 1073741823b + c - 1073741823e - f and "
3289             "3i >= 1 + 2b + e + 3g }";
3290         bset1 = isl_basic_set_read_from_str(ctx, str);
3291         bset2 = isl_basic_set_sample(isl_basic_set_copy(bset1));
3292         empty = isl_basic_set_is_empty(bset2);
3293         subset = isl_basic_set_is_subset(bset2, bset1);
3294         isl_basic_set_free(bset1);
3295         isl_basic_set_free(bset2);
3296         if (empty < 0 || subset < 0)
3297                 return -1;
3298         if (empty)
3299                 isl_die(ctx, isl_error_unknown, "point not found", return -1);
3300         if (!subset)
3301                 isl_die(ctx, isl_error_unknown, "bad point found", return -1);
3302
3303         return 0;
3304 }
3305
3306 int test_fixed_power(isl_ctx *ctx)
3307 {
3308         const char *str;
3309         isl_map *map;
3310         isl_int exp;
3311         int equal;
3312
3313         isl_int_init(exp);
3314         str = "{ [i] -> [i + 1] }";
3315         map = isl_map_read_from_str(ctx, str);
3316         isl_int_set_si(exp, 23);
3317         map = isl_map_fixed_power(map, exp);
3318         equal = map_check_equal(map, "{ [i] -> [i + 23] }");
3319         isl_int_clear(exp);
3320         isl_map_free(map);
3321         if (equal < 0)
3322                 return -1;
3323
3324         return 0;
3325 }
3326
3327 int test_slice(isl_ctx *ctx)
3328 {
3329         const char *str;
3330         isl_map *map;
3331         int equal;
3332
3333         str = "{ [i] -> [j] }";
3334         map = isl_map_read_from_str(ctx, str);
3335         map = isl_map_equate(map, isl_dim_in, 0, isl_dim_out, 0);
3336         equal = map_check_equal(map, "{ [i] -> [i] }");
3337         isl_map_free(map);
3338         if (equal < 0)
3339                 return -1;
3340
3341         str = "{ [i] -> [j] }";
3342         map = isl_map_read_from_str(ctx, str);
3343         map = isl_map_equate(map, isl_dim_in, 0, isl_dim_in, 0);
3344         equal = map_check_equal(map, "{ [i] -> [j] }");
3345         isl_map_free(map);
3346         if (equal < 0)
3347                 return -1;
3348
3349         str = "{ [i] -> [j] }";
3350         map = isl_map_read_from_str(ctx, str);
3351         map = isl_map_oppose(map, isl_dim_in, 0, isl_dim_out, 0);
3352         equal = map_check_equal(map, "{ [i] -> [-i] }");
3353         isl_map_free(map);
3354         if (equal < 0)
3355                 return -1;
3356
3357         str = "{ [i] -> [j] }";
3358         map = isl_map_read_from_str(ctx, str);
3359         map = isl_map_oppose(map, isl_dim_in, 0, isl_dim_in, 0);
3360         equal = map_check_equal(map, "{ [0] -> [j] }");
3361         isl_map_free(map);
3362         if (equal < 0)
3363                 return -1;
3364
3365         str = "{ [i] -> [j] }";
3366         map = isl_map_read_from_str(ctx, str);
3367         map = isl_map_order_gt(map, isl_dim_in, 0, isl_dim_out, 0);
3368         equal = map_check_equal(map, "{ [i] -> [j] : i > j }");
3369         isl_map_free(map);
3370         if (equal < 0)
3371                 return -1;
3372
3373         str = "{ [i] -> [j] }";
3374         map = isl_map_read_from_str(ctx, str);
3375         map = isl_map_order_gt(map, isl_dim_in, 0, isl_dim_in, 0);
3376         equal = map_check_equal(map, "{ [i] -> [j] : false }");
3377         isl_map_free(map);
3378         if (equal < 0)
3379                 return -1;
3380
3381         return 0;
3382 }
3383
3384 int test_eliminate(isl_ctx *ctx)
3385 {
3386         const char *str;
3387         isl_map *map;
3388         int equal;
3389
3390         str = "{ [i] -> [j] : i = 2j }";
3391         map = isl_map_read_from_str(ctx, str);
3392         map = isl_map_eliminate(map, isl_dim_out, 0, 1);
3393         equal = map_check_equal(map, "{ [i] -> [j] : exists a : i = 2a }");
3394         isl_map_free(map);
3395         if (equal < 0)
3396                 return -1;
3397
3398         return 0;
3399 }
3400
3401 /* Check that isl_set_dim_residue_class detects that the values of j
3402  * in the set below are all odd and that it does not detect any spurious
3403  * strides.
3404  */
3405 static int test_residue_class(isl_ctx *ctx)
3406 {
3407         const char *str;
3408         isl_set *set;
3409         isl_int m, r;
3410         int res;
3411
3412         str = "{ [i,j] : j = 4 i + 1 and 0 <= i <= 100; "
3413                 "[i,j] : j = 4 i + 3 and 500 <= i <= 600 }";
3414         set = isl_set_read_from_str(ctx, str);
3415         isl_int_init(m);
3416         isl_int_init(r);
3417         res = isl_set_dim_residue_class(set, 1, &m, &r);
3418         if (res >= 0 &&
3419             (isl_int_cmp_si(m, 2) != 0 || isl_int_cmp_si(r, 1) != 0))
3420                 isl_die(ctx, isl_error_unknown, "incorrect residue class",
3421                         res = -1);
3422         isl_int_clear(r);
3423         isl_int_clear(m);
3424         isl_set_free(set);
3425
3426         return res;
3427 }
3428
3429 int test_align_parameters(isl_ctx *ctx)
3430 {
3431         const char *str;
3432         isl_space *space;
3433         isl_multi_aff *ma1, *ma2;
3434         int equal;
3435
3436         str = "{ A[B[] -> C[]] -> D[E[] -> F[]] }";
3437         ma1 = isl_multi_aff_read_from_str(ctx, str);
3438
3439         space = isl_space_params_alloc(ctx, 1);
3440         space = isl_space_set_dim_name(space, isl_dim_param, 0, "N");
3441         ma1 = isl_multi_aff_align_params(ma1, space);
3442
3443         str = "[N] -> { A[B[] -> C[]] -> D[E[] -> F[]] }";
3444         ma2 = isl_multi_aff_read_from_str(ctx, str);
3445
3446         equal = isl_multi_aff_plain_is_equal(ma1, ma2);
3447
3448         isl_multi_aff_free(ma1);
3449         isl_multi_aff_free(ma2);
3450
3451         if (equal < 0)
3452                 return -1;
3453         if (!equal)
3454                 isl_die(ctx, isl_error_unknown,
3455                         "result not as expected", return -1);
3456
3457         return 0;
3458 }
3459
3460 static int test_list(isl_ctx *ctx)
3461 {
3462         isl_id *a, *b, *c, *d, *id;
3463         isl_id_list *list;
3464         int ok;
3465
3466         a = isl_id_alloc(ctx, "a", NULL);
3467         b = isl_id_alloc(ctx, "b", NULL);
3468         c = isl_id_alloc(ctx, "c", NULL);
3469         d = isl_id_alloc(ctx, "d", NULL);
3470
3471         list = isl_id_list_alloc(ctx, 4);
3472         list = isl_id_list_add(list, a);
3473         list = isl_id_list_add(list, b);
3474         list = isl_id_list_add(list, c);
3475         list = isl_id_list_add(list, d);
3476         list = isl_id_list_drop(list, 1, 1);
3477
3478         if (isl_id_list_n_id(list) != 3) {
3479                 isl_id_list_free(list);
3480                 isl_die(ctx, isl_error_unknown,
3481                         "unexpected number of elements in list", return -1);
3482         }
3483
3484         id = isl_id_list_get_id(list, 0);
3485         ok = id == a;
3486         isl_id_free(id);
3487         id = isl_id_list_get_id(list, 1);
3488         ok = ok && id == c;
3489         isl_id_free(id);
3490         id = isl_id_list_get_id(list, 2);
3491         ok = ok && id == d;
3492         isl_id_free(id);
3493
3494         isl_id_list_free(list);
3495
3496         if (!ok)
3497                 isl_die(ctx, isl_error_unknown,
3498                         "unexpected elements in list", return -1);
3499
3500         return 0;
3501 }
3502
3503 const char *set_conversion_tests[] = {
3504         "[N] -> { [i] : N - 1 <= 2 i <= N }",
3505         "[N] -> { [i] : exists a : i = 4 a and N - 1 <= i <= N }",
3506         "[N] -> { [i,j] : exists a : i = 4 a and N - 1 <= i, 2j <= N }",
3507         "[N] -> { [[i]->[j]] : exists a : i = 4 a and N - 1 <= i, 2j <= N }",
3508 };
3509
3510 /* Check that converting from isl_set to isl_pw_multi_aff and back
3511  * to isl_set produces the original isl_set.
3512  */
3513 static int test_set_conversion(isl_ctx *ctx)
3514 {
3515         int i;
3516         const char *str;
3517         isl_set *set1, *set2;
3518         isl_pw_multi_aff *pma;
3519         int equal;
3520
3521         for (i = 0; i < ARRAY_SIZE(set_conversion_tests); ++i) {
3522                 str = set_conversion_tests[i];
3523                 set1 = isl_set_read_from_str(ctx, str);
3524                 pma = isl_pw_multi_aff_from_set(isl_set_copy(set1));
3525                 set2 = isl_set_from_pw_multi_aff(pma);
3526                 equal = isl_set_is_equal(set1, set2);
3527                 isl_set_free(set1);
3528                 isl_set_free(set2);
3529
3530                 if (equal < 0)
3531                         return -1;
3532                 if (!equal)
3533                         isl_die(ctx, isl_error_unknown, "bad conversion",
3534                                 return -1);
3535         }
3536
3537         return 0;
3538 }
3539
3540 /* Check that converting from isl_map to isl_pw_multi_aff and back
3541  * to isl_map produces the original isl_map.
3542  */
3543 static int test_map_conversion(isl_ctx *ctx)
3544 {
3545         const char *str;
3546         isl_map *map1, *map2;
3547         isl_pw_multi_aff *pma;
3548         int equal;
3549
3550         str = "{ [a, b, c, d] -> s0[a, b, e, f] : "
3551                 "exists (e0 = [(a - 2c)/3], e1 = [(-4 + b - 5d)/9], "
3552                 "e2 = [(-d + f)/9]: 3e0 = a - 2c and 9e1 = -4 + b - 5d and "
3553                 "9e2 = -d + f and f >= 0 and f <= 8 and 9e >= -5 - 2a and "
3554                 "9e <= -2 - 2a) }";
3555         map1 = isl_map_read_from_str(ctx, str);
3556         pma = isl_pw_multi_aff_from_map(isl_map_copy(map1));
3557         map2 = isl_map_from_pw_multi_aff(pma);
3558         equal = isl_map_is_equal(map1, map2);
3559         isl_map_free(map1);
3560         isl_map_free(map2);
3561
3562         if (equal < 0)
3563                 return -1;
3564         if (!equal)
3565                 isl_die(ctx, isl_error_unknown, "bad conversion", return -1);
3566
3567         return 0;
3568 }
3569
3570 static int test_conversion(isl_ctx *ctx)
3571 {
3572         if (test_set_conversion(ctx) < 0)
3573                 return -1;
3574         if (test_map_conversion(ctx) < 0)
3575                 return -1;
3576         return 0;
3577 }
3578
3579 /* Check that isl_basic_map_curry does not modify input.
3580  */
3581 static int test_curry(isl_ctx *ctx)
3582 {
3583         const char *str;
3584         isl_basic_map *bmap1, *bmap2;
3585         int equal;
3586
3587         str = "{ [A[] -> B[]] -> C[] }";
3588         bmap1 = isl_basic_map_read_from_str(ctx, str);
3589         bmap2 = isl_basic_map_curry(isl_basic_map_copy(bmap1));
3590         equal = isl_basic_map_is_equal(bmap1, bmap2);
3591         isl_basic_map_free(bmap1);
3592         isl_basic_map_free(bmap2);
3593
3594         if (equal < 0)
3595                 return -1;
3596         if (equal)
3597                 isl_die(ctx, isl_error_unknown,
3598                         "curried map should not be equal to original",
3599                         return -1);
3600
3601         return 0;
3602 }
3603
3604 struct {
3605         const char *set;
3606         const char *ma;
3607         const char *res;
3608 } preimage_tests[] = {
3609         { "{ B[i,j] : 0 <= i < 10 and 0 <= j < 100 }",
3610           "{ A[j,i] -> B[i,j] }",
3611           "{ A[j,i] : 0 <= i < 10 and 0 <= j < 100 }" },
3612         { "{ rat: B[i,j] : 0 <= i, j and 3 i + 5 j <= 100 }",
3613           "{ A[a,b] -> B[a/2,b/6] }",
3614           "{ rat: A[a,b] : 0 <= a, b and 9 a + 5 b <= 600 }" },
3615         { "{ B[i,j] : 0 <= i, j and 3 i + 5 j <= 100 }",
3616           "{ A[a,b] -> B[a/2,b/6] }",
3617           "{ A[a,b] : 0 <= a, b and 9 a + 5 b <= 600 and "
3618                     "exists i,j : a = 2 i and b = 6 j }" },
3619         { "[n] -> { S[i] : 0 <= i <= 100 }", "[n] -> { S[n] }",
3620           "[n] -> { : 0 <= n <= 100 }" },
3621         { "{ B[i] : 0 <= i < 100 and exists a : i = 4 a }",
3622           "{ A[a] -> B[2a] }",
3623           "{ A[a] : 0 <= a < 50 and exists b : a = 2 b }" },
3624         { "{ B[i] : 0 <= i < 100 and exists a : i = 4 a }",
3625           "{ A[a] -> B[([a/2])] }",
3626           "{ A[a] : 0 <= a < 200 and exists b : [a/2] = 4 b }" },
3627         { "{ B[i,j,k] : 0 <= i,j,k <= 100 }",
3628           "{ A[a] -> B[a,a,a/3] }",
3629           "{ A[a] : 0 <= a <= 100 and exists b : a = 3 b }" },
3630         { "{ B[i,j] : j = [(i)/2] } ", "{ A[i,j] -> B[i/3,j] }",
3631           "{ A[i,j] : j = [(i)/6] and exists a : i = 3 a }" },
3632 };
3633
3634 static int test_preimage_basic_set(isl_ctx *ctx)
3635 {
3636         int i;
3637         isl_basic_set *bset1, *bset2;
3638         isl_multi_aff *ma;
3639         int equal;
3640
3641         for (i = 0; i < ARRAY_SIZE(preimage_tests); ++i) {
3642                 bset1 = isl_basic_set_read_from_str(ctx, preimage_tests[i].set);
3643                 ma = isl_multi_aff_read_from_str(ctx, preimage_tests[i].ma);
3644                 bset2 = isl_basic_set_read_from_str(ctx, preimage_tests[i].res);
3645                 bset1 = isl_basic_set_preimage_multi_aff(bset1, ma);
3646                 equal = isl_basic_set_is_equal(bset1, bset2);
3647                 isl_basic_set_free(bset1);
3648                 isl_basic_set_free(bset2);
3649                 if (equal < 0)
3650                         return -1;
3651                 if (!equal)
3652                         isl_die(ctx, isl_error_unknown, "bad preimage",
3653                                 return -1);
3654         }
3655
3656         return 0;
3657 }
3658
3659 struct {
3660         const char *map;
3661         const char *ma;
3662         const char *res;
3663 } preimage_domain_tests[] = {
3664         { "{ B[i,j] -> C[2i + 3j] : 0 <= i < 10 and 0 <= j < 100 }",
3665           "{ A[j,i] -> B[i,j] }",
3666           "{ A[j,i] -> C[2i + 3j] : 0 <= i < 10 and 0 <= j < 100 }" },
3667         { "{ B[i] -> C[i]; D[i] -> E[i] }",
3668           "{ A[i] -> B[i + 1] }",
3669           "{ A[i] -> C[i + 1] }" },
3670         { "{ B[i] -> C[i]; B[i] -> E[i] }",
3671           "{ A[i] -> B[i + 1] }",
3672           "{ A[i] -> C[i + 1]; A[i] -> E[i + 1] }" },
3673         { "{ B[i] -> C[([i/2])] }",
3674           "{ A[i] -> B[2i] }",
3675           "{ A[i] -> C[i] }" },
3676         { "{ B[i,j] -> C[([i/2]), ([(i+j)/3])] }",
3677           "{ A[i] -> B[([i/5]), ([i/7])] }",
3678           "{ A[i] -> C[([([i/5])/2]), ([(([i/5])+([i/7]))/3])] }" },
3679         { "[N] -> { B[i] -> C[([N/2]), i, ([N/3])] }",
3680           "[N] -> { A[] -> B[([N/5])] }",
3681           "[N] -> { A[] -> C[([N/2]), ([N/5]), ([N/3])] }" },
3682         { "{ B[i] -> C[i] : exists a : i = 5 a }",
3683           "{ A[i] -> B[2i] }",
3684           "{ A[i] -> C[2i] : exists a : 2i = 5 a }" },
3685         { "{ B[i] -> C[i] : exists a : i = 2 a; "
3686             "B[i] -> D[i] : exists a : i = 2 a + 1 }",
3687           "{ A[i] -> B[2i] }",
3688           "{ A[i] -> C[2i] }" },
3689 };
3690
3691 static int test_preimage_union_map(isl_ctx *ctx)
3692 {
3693         int i;
3694         isl_union_map *umap1, *umap2;
3695         isl_multi_aff *ma;
3696         int equal;
3697
3698         for (i = 0; i < ARRAY_SIZE(preimage_domain_tests); ++i) {
3699                 umap1 = isl_union_map_read_from_str(ctx,
3700                                                 preimage_domain_tests[i].map);
3701                 ma = isl_multi_aff_read_from_str(ctx,
3702                                                 preimage_domain_tests[i].ma);
3703                 umap2 = isl_union_map_read_from_str(ctx,
3704                                                 preimage_domain_tests[i].res);
3705                 umap1 = isl_union_map_preimage_domain_multi_aff(umap1, ma);
3706                 equal = isl_union_map_is_equal(umap1, umap2);
3707                 isl_union_map_free(umap1);
3708                 isl_union_map_free(umap2);
3709                 if (equal < 0)
3710                         return -1;
3711                 if (!equal)
3712                         isl_die(ctx, isl_error_unknown, "bad preimage",
3713                                 return -1);
3714         }
3715
3716         return 0;
3717 }
3718
3719 static int test_preimage(isl_ctx *ctx)
3720 {
3721         if (test_preimage_basic_set(ctx) < 0)
3722                 return -1;
3723         if (test_preimage_union_map(ctx) < 0)
3724                 return -1;
3725
3726         return 0;
3727 }
3728
3729 struct {
3730         const char *ma1;
3731         const char *ma;
3732         const char *res;
3733 } pullback_tests[] = {
3734         { "{ B[i,j] -> C[i + 2j] }" , "{ A[a,b] -> B[b,a] }",
3735           "{ A[a,b] -> C[b + 2a] }" },
3736         { "{ B[i] -> C[2i] }", "{ A[a] -> B[(a)/2] }", "{ A[a] -> C[a] }" },
3737         { "{ B[i] -> C[(i)/2] }", "{ A[a] -> B[2a] }", "{ A[a] -> C[a] }" },
3738         { "{ B[i] -> C[(i)/2] }", "{ A[a] -> B[(a)/3] }",
3739           "{ A[a] -> C[(a)/6] }" },
3740         { "{ B[i] -> C[2i] }", "{ A[a] -> B[5a] }", "{ A[a] -> C[10a] }" },
3741         { "{ B[i] -> C[2i] }", "{ A[a] -> B[(a)/3] }",
3742           "{ A[a] -> C[(2a)/3] }" },
3743         { "{ B[i,j] -> C[i + j] }", "{ A[a] -> B[a,a] }", "{ A[a] -> C[2a] }"},
3744         { "{ B[a] -> C[a,a] }", "{ A[i,j] -> B[i + j] }",
3745           "{ A[i,j] -> C[i + j, i + j] }"},
3746         { "{ B[i] -> C[([i/2])] }", "{ B[5] }", "{ C[2] }" },
3747         { "[n] -> { B[i,j] -> C[([i/2]) + 2j] }",
3748           "[n] -> { B[n,[n/3]] }", "[n] -> { C[([n/2]) + 2*[n/3]] }", },
3749 };
3750
3751 static int test_pullback(isl_ctx *ctx)
3752 {
3753         int i;
3754         isl_multi_aff *ma1, *ma2;
3755         isl_multi_aff *ma;
3756         int equal;
3757
3758         for (i = 0; i < ARRAY_SIZE(pullback_tests); ++i) {
3759                 ma1 = isl_multi_aff_read_from_str(ctx, pullback_tests[i].ma1);
3760                 ma = isl_multi_aff_read_from_str(ctx, pullback_tests[i].ma);
3761                 ma2 = isl_multi_aff_read_from_str(ctx, pullback_tests[i].res);
3762                 ma1 = isl_multi_aff_pullback_multi_aff(ma1, ma);
3763                 equal = isl_multi_aff_plain_is_equal(ma1, ma2);
3764                 isl_multi_aff_free(ma1);
3765                 isl_multi_aff_free(ma2);
3766                 if (equal < 0)
3767                         return -1;
3768                 if (!equal)
3769                         isl_die(ctx, isl_error_unknown, "bad pullback",
3770                                 return -1);
3771         }
3772
3773         return 0;
3774 }
3775
3776 /* Check that negation is printed correctly.
3777  */
3778 static int test_ast(isl_ctx *ctx)
3779 {
3780         isl_ast_expr *expr, *expr1, *expr2, *expr3;
3781         char *str;
3782         int ok;
3783
3784         expr1 = isl_ast_expr_from_id(isl_id_alloc(ctx, "A", NULL));
3785         expr2 = isl_ast_expr_from_id(isl_id_alloc(ctx, "B", NULL));
3786         expr = isl_ast_expr_add(expr1, expr2);
3787         expr = isl_ast_expr_neg(expr);
3788         str = isl_ast_expr_to_str(expr);
3789         ok = str ? !strcmp(str, "-(A + B)") : -1;
3790         free(str);
3791         isl_ast_expr_free(expr);
3792
3793         if (ok < 0)
3794                 return -1;
3795         if (!ok)
3796                 isl_die(ctx, isl_error_unknown,
3797                         "isl_ast_expr printed incorrectly", return -1);
3798
3799         expr1 = isl_ast_expr_from_id(isl_id_alloc(ctx, "A", NULL));
3800         expr2 = isl_ast_expr_from_id(isl_id_alloc(ctx, "B", NULL));
3801         expr = isl_ast_expr_add(expr1, expr2);
3802         expr3 = isl_ast_expr_from_id(isl_id_alloc(ctx, "C", NULL));
3803         expr = isl_ast_expr_sub(expr3, expr);
3804         str = isl_ast_expr_to_str(expr);
3805         ok = str ? !strcmp(str, "C - (A + B)") : -1;
3806         free(str);
3807         isl_ast_expr_free(expr);
3808
3809         if (ok < 0)
3810                 return -1;
3811         if (!ok)
3812                 isl_die(ctx, isl_error_unknown,
3813                         "isl_ast_expr printed incorrectly", return -1);
3814
3815         return 0;
3816 }
3817
3818 /* Internal data structure for before_for and after_for callbacks.
3819  *
3820  * depth is the current depth
3821  * before is the number of times before_for has been called
3822  * after is the number of times after_for has been called
3823  */
3824 struct isl_test_codegen_data {
3825         int depth;
3826         int before;
3827         int after;
3828 };
3829
3830 /* This function is called before each for loop in the AST generated
3831  * from test_ast_gen1.
3832  *
3833  * Increment the number of calls and the depth.
3834  * Check that the space returned by isl_ast_build_get_schedule_space
3835  * matches the target space of the schedule returned by
3836  * isl_ast_build_get_schedule.
3837  * Return an isl_id that is checked by the corresponding call
3838  * to after_for.
3839  */
3840 static __isl_give isl_id *before_for(__isl_keep isl_ast_build *build,
3841         void *user)
3842 {
3843         struct isl_test_codegen_data *data = user;
3844         isl_ctx *ctx;
3845         isl_space *space;
3846         isl_union_map *schedule;
3847         isl_union_set *uset;
3848         isl_set *set;
3849         int empty;
3850         char name[] = "d0";
3851
3852         ctx = isl_ast_build_get_ctx(build);
3853
3854         if (data->before >= 3)
3855                 isl_die(ctx, isl_error_unknown,
3856                         "unexpected number of for nodes", return NULL);
3857         if (data->depth >= 2)
3858                 isl_die(ctx, isl_error_unknown,
3859                         "unexpected depth", return NULL);
3860
3861         snprintf(name, sizeof(name), "d%d", data->depth);
3862         data->before++;
3863         data->depth++;
3864
3865         schedule = isl_ast_build_get_schedule(build);
3866         uset = isl_union_map_range(schedule);
3867         if (!uset)
3868                 return NULL;
3869         if (isl_union_set_n_set(uset) != 1) {
3870                 isl_union_set_free(uset);
3871                 isl_die(ctx, isl_error_unknown,
3872                         "expecting single range space", return NULL);
3873         }
3874
3875         space = isl_ast_build_get_schedule_space(build);
3876         set = isl_union_set_extract_set(uset, space);
3877         isl_union_set_free(uset);
3878         empty = isl_set_is_empty(set);
3879         isl_set_free(set);
3880
3881         if (empty < 0)
3882                 return NULL;
3883         if (empty)
3884                 isl_die(ctx, isl_error_unknown,
3885                         "spaces don't match", return NULL);
3886
3887         return isl_id_alloc(ctx, name, NULL);
3888 }
3889
3890 /* This function is called after each for loop in the AST generated
3891  * from test_ast_gen1.
3892  *
3893  * Increment the number of calls and decrement the depth.
3894  * Check that the annotation attached to the node matches
3895  * the isl_id returned by the corresponding call to before_for.
3896  */
3897 static __isl_give isl_ast_node *after_for(__isl_take isl_ast_node *node,
3898         __isl_keep isl_ast_build *build, void *user)
3899 {
3900         struct isl_test_codegen_data *data = user;
3901         isl_id *id;
3902         const char *name;
3903         int valid;
3904
3905         data->after++;
3906         data->depth--;
3907
3908         if (data->after > data->before)
3909                 isl_die(isl_ast_node_get_ctx(node), isl_error_unknown,
3910                         "mismatch in number of for nodes",
3911                         return isl_ast_node_free(node));
3912
3913         id = isl_ast_node_get_annotation(node);
3914         if (!id)
3915                 isl_die(isl_ast_node_get_ctx(node), isl_error_unknown,
3916                         "missing annotation", return isl_ast_node_free(node));
3917
3918         name = isl_id_get_name(id);
3919         valid = name && atoi(name + 1) == data->depth;
3920         isl_id_free(id);
3921
3922         if (!valid)
3923                 isl_die(isl_ast_node_get_ctx(node), isl_error_unknown,
3924                         "wrong annotation", return isl_ast_node_free(node));
3925
3926         return node;
3927 }
3928
3929 /* Check that the before_each_for and after_each_for callbacks
3930  * are called for each for loop in the generated code,
3931  * that they are called in the right order and that the isl_id
3932  * returned from the before_each_for callback is attached to
3933  * the isl_ast_node passed to the corresponding after_each_for call.
3934  */
3935 static int test_ast_gen1(isl_ctx *ctx)
3936 {
3937         const char *str;
3938         isl_set *set;
3939         isl_union_map *schedule;
3940         isl_ast_build *build;
3941         isl_ast_node *tree;
3942         struct isl_test_codegen_data data;
3943
3944         str = "[N] -> { : N >= 10 }";
3945         set = isl_set_read_from_str(ctx, str);
3946         str = "[N] -> { A[i,j] -> S[8,i,3,j] : 0 <= i,j <= N; "
3947                     "B[i,j] -> S[8,j,9,i] : 0 <= i,j <= N }";
3948         schedule = isl_union_map_read_from_str(ctx, str);
3949
3950         data.before = 0;
3951         data.after = 0;
3952         data.depth = 0;
3953         build = isl_ast_build_from_context(set);
3954         build = isl_ast_build_set_before_each_for(build,
3955                         &before_for, &data);
3956         build = isl_ast_build_set_after_each_for(build,
3957                         &after_for, &data);
3958         tree = isl_ast_build_ast_from_schedule(build, schedule);
3959         isl_ast_build_free(build);
3960         if (!tree)
3961                 return -1;
3962
3963         isl_ast_node_free(tree);
3964
3965         if (data.before != 3 || data.after != 3)
3966                 isl_die(ctx, isl_error_unknown,
3967                         "unexpected number of for nodes", return -1);
3968
3969         return 0;
3970 }
3971
3972 /* Check that the AST generator handles domains that are integrally disjoint
3973  * but not ratinoally disjoint.
3974  */
3975 static int test_ast_gen2(isl_ctx *ctx)
3976 {
3977         const char *str;
3978         isl_set *set;
3979         isl_union_map *schedule;
3980         isl_union_map *options;
3981         isl_ast_build *build;
3982         isl_ast_node *tree;
3983
3984         str = "{ A[i,j] -> [i,j] : 0 <= i,j <= 1 }";
3985         schedule = isl_union_map_read_from_str(ctx, str);
3986         set = isl_set_universe(isl_space_params_alloc(ctx, 0));
3987         build = isl_ast_build_from_context(set);
3988
3989         str = "{ [i,j] -> atomic[1] : i + j = 1; [i,j] -> unroll[1] : i = j }";
3990         options = isl_union_map_read_from_str(ctx, str);
3991         build = isl_ast_build_set_options(build, options);
3992         tree = isl_ast_build_ast_from_schedule(build, schedule);
3993         isl_ast_build_free(build);
3994         if (!tree)
3995                 return -1;
3996         isl_ast_node_free(tree);
3997
3998         return 0;
3999 }
4000
4001 /* Increment *user on each call.
4002  */
4003 static __isl_give isl_ast_node *count_domains(__isl_take isl_ast_node *node,
4004         __isl_keep isl_ast_build *build, void *user)
4005 {
4006         int *n = user;
4007
4008         (*n)++;
4009
4010         return node;
4011 }
4012
4013 /* Test that unrolling tries to minimize the number of instances.
4014  * In particular, for the schedule given below, make sure it generates
4015  * 3 nodes (rather than 101).
4016  */
4017 static int test_ast_gen3(isl_ctx *ctx)
4018 {
4019         const char *str;
4020         isl_set *set;
4021         isl_union_map *schedule;
4022         isl_union_map *options;
4023         isl_ast_build *build;
4024         isl_ast_node *tree;
4025         int n_domain = 0;
4026
4027         str = "[n] -> { A[i] -> [i] : 0 <= i <= 100 and n <= i <= n + 2 }";
4028         schedule = isl_union_map_read_from_str(ctx, str);
4029         set = isl_set_universe(isl_space_params_alloc(ctx, 0));
4030
4031         str = "{ [i] -> unroll[0] }";
4032         options = isl_union_map_read_from_str(ctx, str);
4033
4034         build = isl_ast_build_from_context(set);
4035         build = isl_ast_build_set_options(build, options);
4036         build = isl_ast_build_set_at_each_domain(build,
4037                         &count_domains, &n_domain);
4038         tree = isl_ast_build_ast_from_schedule(build, schedule);
4039         isl_ast_build_free(build);
4040         if (!tree)
4041                 return -1;
4042
4043         isl_ast_node_free(tree);
4044
4045         if (n_domain != 3)
4046                 isl_die(ctx, isl_error_unknown,
4047                         "unexpected number of for nodes", return -1);
4048
4049         return 0;
4050 }
4051
4052 /* Check that if the ast_build_exploit_nested_bounds options is set,
4053  * we do not get an outer if node in the generated AST,
4054  * while we do get such an outer if node if the options is not set.
4055  */
4056 static int test_ast_gen4(isl_ctx *ctx)
4057 {
4058         const char *str;
4059         isl_set *set;
4060         isl_union_map *schedule;
4061         isl_ast_build *build;
4062         isl_ast_node *tree;
4063         enum isl_ast_node_type type;
4064         int enb;
4065
4066         enb = isl_options_get_ast_build_exploit_nested_bounds(ctx);
4067         str = "[N,M] -> { A[i,j] -> [i,j] : 0 <= i <= N and 0 <= j <= M }";
4068
4069         isl_options_set_ast_build_exploit_nested_bounds(ctx, 1);
4070
4071         schedule = isl_union_map_read_from_str(ctx, str);
4072         set = isl_set_universe(isl_space_params_alloc(ctx, 0));
4073         build = isl_ast_build_from_context(set);
4074         tree = isl_ast_build_ast_from_schedule(build, schedule);
4075         isl_ast_build_free(build);
4076         if (!tree)
4077                 return -1;
4078
4079         type = isl_ast_node_get_type(tree);
4080         isl_ast_node_free(tree);
4081
4082         if (type == isl_ast_node_if)
4083                 isl_die(ctx, isl_error_unknown,
4084                         "not expecting if node", return -1);
4085
4086         isl_options_set_ast_build_exploit_nested_bounds(ctx, 0);
4087
4088         schedule = isl_union_map_read_from_str(ctx, str);
4089         set = isl_set_universe(isl_space_params_alloc(ctx, 0));
4090         build = isl_ast_build_from_context(set);
4091         tree = isl_ast_build_ast_from_schedule(build, schedule);
4092         isl_ast_build_free(build);
4093         if (!tree)
4094                 return -1;
4095
4096         type = isl_ast_node_get_type(tree);
4097         isl_ast_node_free(tree);
4098
4099         if (type != isl_ast_node_if)
4100                 isl_die(ctx, isl_error_unknown,
4101                         "expecting if node", return -1);
4102
4103         isl_options_set_ast_build_exploit_nested_bounds(ctx, enb);
4104
4105         return 0;
4106 }
4107
4108 /* This function is called for each leaf in the AST generated
4109  * from test_ast_gen5.
4110  *
4111  * We finalize the AST generation by extending the outer schedule
4112  * with a zero-dimensional schedule.  If this results in any for loops,
4113  * then this means that we did not pass along enough information
4114  * about the outer schedule to the inner AST generation.
4115  */
4116 static __isl_give isl_ast_node *create_leaf(__isl_take isl_ast_build *build,
4117         void *user)
4118 {
4119         isl_union_map *schedule, *extra;
4120         isl_ast_node *tree;
4121
4122         schedule = isl_ast_build_get_schedule(build);
4123         extra = isl_union_map_copy(schedule);
4124         extra = isl_union_map_from_domain(isl_union_map_domain(extra));
4125         schedule = isl_union_map_range_product(schedule, extra);
4126         tree = isl_ast_build_ast_from_schedule(build, schedule);
4127         isl_ast_build_free(build);
4128
4129         if (!tree)
4130                 return NULL;
4131
4132         if (isl_ast_node_get_type(tree) == isl_ast_node_for)
4133                 isl_die(isl_ast_node_get_ctx(tree), isl_error_unknown,
4134                         "code should not contain any for loop",
4135                         return isl_ast_node_free(tree));
4136
4137         return tree;
4138 }
4139
4140 /* Check that we do not lose any information when going back and
4141  * forth between internal and external schedule.
4142  *
4143  * In particular, we create an AST where we unroll the only
4144  * non-constant dimension in the schedule.  We therefore do
4145  * not expect any for loops in the AST.  However, older versions
4146  * of isl would not pass along enough information about the outer
4147  * schedule when performing an inner code generation from a create_leaf
4148  * callback, resulting in the inner code generation producing a for loop.
4149  */
4150 static int test_ast_gen5(isl_ctx *ctx)
4151 {
4152         const char *str;
4153         isl_set *set;
4154         isl_union_map *schedule, *options;
4155         isl_ast_build *build;
4156         isl_ast_node *tree;
4157
4158         str = "{ A[] -> [1, 1, 2]; B[i] -> [1, i, 0] : i >= 1 and i <= 2 }";
4159         schedule = isl_union_map_read_from_str(ctx, str);
4160
4161         str = "{ [a, b, c] -> unroll[1] : exists (e0 = [(a)/4]: "
4162                                 "4e0 >= -1 + a - b and 4e0 <= -2 + a + b) }";
4163         options = isl_union_map_read_from_str(ctx, str);
4164
4165         set = isl_set_universe(isl_space_params_alloc(ctx, 0));
4166         build = isl_ast_build_from_context(set);
4167         build = isl_ast_build_set_options(build, options);
4168         build = isl_ast_build_set_create_leaf(build, &create_leaf, NULL);
4169         tree = isl_ast_build_ast_from_schedule(build, schedule);
4170         isl_ast_build_free(build);
4171         isl_ast_node_free(tree);
4172         if (!tree)
4173                 return -1;
4174
4175         return 0;
4176 }
4177
4178 static int test_ast_gen(isl_ctx *ctx)
4179 {
4180         if (test_ast_gen1(ctx) < 0)
4181                 return -1;
4182         if (test_ast_gen2(ctx) < 0)
4183                 return -1;
4184         if (test_ast_gen3(ctx) < 0)
4185                 return -1;
4186         if (test_ast_gen4(ctx) < 0)
4187                 return -1;
4188         if (test_ast_gen5(ctx) < 0)
4189                 return -1;
4190         return 0;
4191 }
4192
4193 /* Check if dropping output dimensions from an isl_pw_multi_aff
4194  * works properly.
4195  */
4196 static int test_pw_multi_aff(isl_ctx *ctx)
4197 {
4198         const char *str;
4199         isl_pw_multi_aff *pma1, *pma2;
4200         int equal;
4201
4202         str = "{ [i,j] -> [i+j, 4i-j] }";
4203         pma1 = isl_pw_multi_aff_read_from_str(ctx, str);
4204         str = "{ [i,j] -> [4i-j] }";
4205         pma2 = isl_pw_multi_aff_read_from_str(ctx, str);
4206
4207         pma1 = isl_pw_multi_aff_drop_dims(pma1, isl_dim_out, 0, 1);
4208
4209         equal = isl_pw_multi_aff_plain_is_equal(pma1, pma2);
4210
4211         isl_pw_multi_aff_free(pma1);
4212         isl_pw_multi_aff_free(pma2);
4213         if (equal < 0)
4214                 return -1;
4215         if (!equal)
4216                 isl_die(ctx, isl_error_unknown,
4217                         "expressions not equal", return -1);
4218
4219         return 0;
4220 }
4221
4222 /* This is a regression test for a bug where isl_basic_map_simplify
4223  * would end up in an infinite loop.  In particular, we construct
4224  * an empty basic set that is not obviously empty.
4225  * isl_basic_set_is_empty marks the basic set as empty.
4226  * After projecting out i3, the variable can be dropped completely,
4227  * but isl_basic_map_simplify refrains from doing so if the basic set
4228  * is empty and would end up in an infinite loop if it didn't test
4229  * explicitly for empty basic maps in the outer loop.
4230  */
4231 static int test_simplify(isl_ctx *ctx)
4232 {
4233         const char *str;
4234         isl_basic_set *bset;
4235         int empty;
4236
4237         str = "{ [i0, i1, i2, i3] : i0 >= -2 and 6i2 <= 4 + i0 + 5i1 and "
4238                 "i2 <= 22 and 75i2 <= 111 + 13i0 + 60i1 and "
4239                 "25i2 >= 38 + 6i0 + 20i1 and i0 <= -1 and i2 >= 20 and "
4240                 "i3 >= i2 }";
4241         bset = isl_basic_set_read_from_str(ctx, str);
4242         empty = isl_basic_set_is_empty(bset);
4243         bset = isl_basic_set_project_out(bset, isl_dim_set, 3, 1);
4244         isl_basic_set_free(bset);
4245         if (!bset)
4246                 return -1;
4247         if (!empty)
4248                 isl_die(ctx, isl_error_unknown,
4249                         "basic set should be empty", return -1);
4250
4251         return 0;
4252 }
4253
4254 /* This is a regression test for a bug where isl_tab_basic_map_partial_lexopt
4255  * with gbr context would fail to disable the use of the shifted tableau
4256  * when transferring equalities for the input to the context, resulting
4257  * in invalid sample values.
4258  */
4259 static int test_partial_lexmin(isl_ctx *ctx)
4260 {
4261         const char *str;
4262         isl_basic_set *bset;
4263         isl_basic_map *bmap;
4264         isl_map *map;
4265
4266         str = "{ [1, b, c, 1 - c] -> [e] : 2e <= -c and 2e >= -3 + c }";
4267         bmap = isl_basic_map_read_from_str(ctx, str);
4268         str = "{ [a, b, c, d] : c <= 1 and 2d >= 6 - 4b - c }";
4269         bset = isl_basic_set_read_from_str(ctx, str);
4270         map = isl_basic_map_partial_lexmin(bmap, bset, NULL);
4271         isl_map_free(map);
4272
4273         if (!map)
4274                 return -1;
4275
4276         return 0;
4277 }
4278
4279 /* Check that the variable compression performed on the existentially
4280  * quantified variables inside isl_basic_set_compute_divs is not confused
4281  * by the implicit equalities among the parameters.
4282  */
4283 static int test_compute_divs(isl_ctx *ctx)
4284 {
4285         const char *str;
4286         isl_basic_set *bset;
4287         isl_set *set;
4288
4289         str = "[a, b, c, d, e] -> { [] : exists (e0: 2d = b and a <= 124 and "
4290                 "b <= 2046 and b >= 0 and b <= 60 + 64a and 2e >= b + 2c and "
4291                 "2e >= b and 2e <= 1 + b and 2e <= 1 + b + 2c and "
4292                 "32768e0 >= -124 + a and 2097152e0 <= 60 + 64a - b) }";
4293         bset = isl_basic_set_read_from_str(ctx, str);
4294         set = isl_basic_set_compute_divs(bset);
4295         isl_set_free(set);
4296         if (!set)
4297                 return -1;
4298
4299         return 0;
4300 }
4301
4302 struct {
4303         const char *name;
4304         int (*fn)(isl_ctx *ctx);
4305 } tests [] = {
4306         { "val", &test_val },
4307         { "compute divs", &test_compute_divs },
4308         { "partial lexmin", &test_partial_lexmin },
4309         { "simplify", &test_simplify },
4310         { "curry", &test_curry },
4311         { "piecewise multi affine expressions", &test_pw_multi_aff },
4312         { "conversion", &test_conversion },
4313         { "list", &test_list },
4314         { "align parameters", &test_align_parameters },
4315         { "preimage", &test_preimage },
4316         { "pullback", &test_pullback },
4317         { "AST", &test_ast },
4318         { "AST generation", &test_ast_gen },
4319         { "eliminate", &test_eliminate },
4320         { "residue class", &test_residue_class },
4321         { "div", &test_div },
4322         { "slice", &test_slice },
4323         { "fixed power", &test_fixed_power },
4324         { "sample", &test_sample },
4325         { "output", &test_output },
4326         { "vertices", &test_vertices },
4327         { "fixed", &test_fixed },
4328         { "equal", &test_equal },
4329         { "product", &test_product },
4330         { "dim_max", &test_dim_max },
4331         { "affine", &test_aff },
4332         { "injective", &test_injective },
4333         { "schedule", &test_schedule },
4334         { "union_pw", &test_union_pw },
4335         { "parse", &test_parse },
4336         { "single-valued", &test_sv },
4337         { "affine hull", &test_affine_hull },
4338         { "coalesce", &test_coalesce },
4339         { "factorize", &test_factorize },
4340         { "subset", &test_subset },
4341         { "subtract", &test_subtract },
4342         { "lexmin", &test_lexmin },
4343         { "piecewise quasi-polynomials", &test_pwqp },
4344 };
4345
4346 int main()
4347 {
4348         int i;
4349         struct isl_ctx *ctx;
4350
4351         srcdir = getenv("srcdir");
4352         assert(srcdir);
4353
4354         ctx = isl_ctx_alloc();
4355         for (i = 0; i < ARRAY_SIZE(tests); ++i) {
4356                 printf("%s\n", tests[i].name);
4357                 if (tests[i].fn(ctx) < 0)
4358                         goto error;
4359         }
4360         test_lift(ctx);
4361         test_bound(ctx);
4362         test_union(ctx);
4363         test_split_periods(ctx);
4364         test_lex(ctx);
4365         test_bijective(ctx);
4366         test_dep(ctx);
4367         test_read(ctx);
4368         test_bounded(ctx);
4369         test_construction(ctx);
4370         test_dim(ctx);
4371         test_application(ctx);
4372         test_convex_hull(ctx);
4373         test_gist(ctx);
4374         test_closure(ctx);
4375         isl_ctx_free(ctx);
4376         return 0;
4377 error:
4378         isl_ctx_free(ctx);
4379         return -1;
4380 }