Home | History | Annotate | Line # | Download | only in dist
      1 /*
      2  * Copyright 2008-2009 Katholieke Universiteit Leuven
      3  * Copyright 2010      INRIA Saclay
      4  * Copyright 2012-2013 Ecole Normale Superieure
      5  * Copyright 2014      INRIA Rocquencourt
      6  * Copyright 2022      Cerebras Systems
      7  *
      8  * Use of this software is governed by the MIT license
      9  *
     10  * Written by Sven Verdoolaege, K.U.Leuven, Departement
     11  * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
     12  * and INRIA Saclay - Ile-de-France, Parc Club Orsay Universite,
     13  * ZAC des vignes, 4 rue Jacques Monod, 91893 Orsay, France
     14  * and Ecole Normale Superieure, 45 rue dUlm, 75230 Paris, France
     15  * and Inria Paris - Rocquencourt, Domaine de Voluceau - Rocquencourt,
     16  * B.P. 105 - 78153 Le Chesnay, France
     17  * and Cerebras Systems, 1237 E Arques Ave, Sunnyvale, CA, USA
     18  */
     19 
     20 #include <assert.h>
     21 #include <stdio.h>
     22 #include <limits.h>
     23 #include <isl_ctx_private.h>
     24 #include <isl_map_private.h>
     25 #include <isl_aff_private.h>
     26 #include <isl_space_private.h>
     27 #include <isl/id.h>
     28 #include <isl/set.h>
     29 #include <isl/flow.h>
     30 #include <isl_constraint_private.h>
     31 #include <isl/polynomial.h>
     32 #include <isl/union_set.h>
     33 #include <isl/union_map.h>
     34 #include <isl_factorization.h>
     35 #include <isl/schedule.h>
     36 #include <isl/schedule_node.h>
     37 #include <isl_options_private.h>
     38 #include <isl_vertices_private.h>
     39 #include <isl/ast_build.h>
     40 #include <isl/val.h>
     41 #include <isl/ilp.h>
     42 #include <isl_ast_build_expr.h>
     43 #include <isl/options.h>
     44 
     45 #include "isl_srcdir.c"
     46 
     47 #define ARRAY_SIZE(array) (sizeof(array)/sizeof(*array))
     48 
     49 static char *get_filename(isl_ctx *ctx, const char *name, const char *suffix) {
     50 	char *filename;
     51 	int length;
     52 	char *pattern = "%s/test_inputs/%s.%s";
     53 
     54 	length = strlen(pattern) - 6 + strlen(srcdir) + strlen(name)
     55 		+ strlen(suffix) + 1;
     56 	filename = isl_alloc_array(ctx, char, length);
     57 
     58 	if (!filename)
     59 		return NULL;
     60 
     61 	sprintf(filename, pattern, srcdir, name, suffix);
     62 
     63 	return filename;
     64 }
     65 
     66 void test_parse_map(isl_ctx *ctx, const char *str)
     67 {
     68 	isl_map *map;
     69 
     70 	map = isl_map_read_from_str(ctx, str);
     71 	assert(map);
     72 	isl_map_free(map);
     73 }
     74 
     75 int test_parse_map_equal(isl_ctx *ctx, const char *str, const char *str2)
     76 {
     77 	isl_map *map, *map2;
     78 	int equal;
     79 
     80 	map = isl_map_read_from_str(ctx, str);
     81 	map2 = isl_map_read_from_str(ctx, str2);
     82 	equal = isl_map_is_equal(map, map2);
     83 	isl_map_free(map);
     84 	isl_map_free(map2);
     85 
     86 	if (equal < 0)
     87 		return -1;
     88 	if (!equal)
     89 		isl_die(ctx, isl_error_unknown, "maps not equal",
     90 			return -1);
     91 
     92 	return 0;
     93 }
     94 
     95 void test_parse_pwqp(isl_ctx *ctx, const char *str)
     96 {
     97 	isl_pw_qpolynomial *pwqp;
     98 
     99 	pwqp = isl_pw_qpolynomial_read_from_str(ctx, str);
    100 	assert(pwqp);
    101 	isl_pw_qpolynomial_free(pwqp);
    102 }
    103 
    104 static void test_parse_pwaff(isl_ctx *ctx, const char *str)
    105 {
    106 	isl_pw_aff *pwaff;
    107 
    108 	pwaff = isl_pw_aff_read_from_str(ctx, str);
    109 	assert(pwaff);
    110 	isl_pw_aff_free(pwaff);
    111 }
    112 
    113 /* Check that we can read an isl_multi_val from "str" without errors.
    114  */
    115 static int test_parse_multi_val(isl_ctx *ctx, const char *str)
    116 {
    117 	isl_multi_val *mv;
    118 
    119 	mv = isl_multi_val_read_from_str(ctx, str);
    120 	isl_multi_val_free(mv);
    121 
    122 	return mv ? 0 : -1;
    123 }
    124 
    125 /* String descriptions of multi piecewise affine expressions
    126  * that are used for testing printing and parsing.
    127  */
    128 static const char *reparse_multi_pw_aff_tests[] = {
    129 	"{ A[x, y] -> [] : x + y >= 0 }",
    130 	"{ A[x, y] -> B[] : x + y >= 0 }",
    131 	"{ A[x, y] -> [x] : x + y >= 0 }",
    132 	"[N] -> { A[x, y] -> [x] : x + y <= N }",
    133 	"{ A[x, y] -> [x, y] : x + y >= 0 }",
    134 	"{ A[x, y] -> [(x : x >= 0), (y : y >= 0)] : x + y >= 0 }",
    135 	"[N] -> { [] : N >= 0 }",
    136 	"[N] -> { [] : N >= 0 }",
    137 	"[N] -> { [N] : N >= 0 }",
    138 	"[N] -> { [N, N + 1] : N >= 0 }",
    139 	"[N, M] -> { [(N : N >= 0), (M : M >= 0)] : N + M >= 0 }",
    140 	"{ [a] -> [b = a] }",
    141 	"{ [a] -> [b = a] : a >= 0 }",
    142 };
    143 
    144 #undef BASE
    145 #define BASE multi_pw_aff
    146 
    147 #include "check_reparse_templ.c"
    148 #include "check_reparse_test_templ.c"
    149 
    150 /* String descriptions that cannot be parsed
    151  * as multi piecewise affine expressions.
    152  */
    153 static const char *parse_multi_pw_aff_fail_tests[] = {
    154 	"{ [a] -> [b] : b = a }",
    155 	"{ [a] -> [b = a] : b >= 0 }",
    156 };
    157 
    158 #include "check_parse_fail_test_templ.c"
    159 
    160 /* String descriptions of piecewise multi affine expressions
    161  * that are used for testing printing and parsing.
    162  */
    163 static const char *reparse_pw_multi_aff_tests[] = {
    164 	"{ [x] -> [x] }",
    165 	"{ [x] -> [x % 4] }",
    166 	"{ [x] -> [x % 4] : x mod 3 = 1 }",
    167 	"{ [x, x] -> [x % 4] }",
    168 	"{ [x, x + 1] -> [x % 4] : x mod 3 = 1 }",
    169 	"{ [x, x mod 2] -> [x % 4] }",
    170 	"{ [a] -> [a//2] : exists (e0: 8*floor((-a + e0)/8) <= -8 - a + 8e0) }",
    171 	"{ [a, b] -> [(2*floor((a)/8) + floor((b)/6))] }",
    172 };
    173 
    174 #undef BASE
    175 #define BASE pw_multi_aff
    176 
    177 #include "check_reparse_templ.c"
    178 #include "check_reparse_test_templ.c"
    179 
    180 /* Test parsing of piecewise multi affine expressions by printing
    181  * the expressions and checking that parsing the output results
    182  * in the same expression.
    183  * Do this for an expression converted from a map with an output
    184  * dimension name that is equal to an automatically generated name, and
    185  * a set of expressions parsed from strings.
    186  */
    187 static isl_stat test_parse_pma(isl_ctx *ctx)
    188 {
    189 	isl_map *map;
    190 	isl_pw_multi_aff *pma;
    191 
    192 	map = isl_map_read_from_str(ctx, "{ [a, a] -> [i1 = a + 1] }");
    193 	pma = isl_pw_multi_aff_from_map(map);
    194 	if (check_reparse_pw_multi_aff(ctx, pma) < 0)
    195 		return isl_stat_error;
    196 
    197 	if (check_reparse_pw_multi_aff_tests(ctx) < 0)
    198 		return isl_stat_error;
    199 
    200 	return isl_stat_ok;
    201 }
    202 
    203 /* String descriptions that cannot be parsed
    204  * as union piecewise multi affine expressions.
    205  */
    206 static const char *parse_union_pw_multi_aff_fail_tests[] = {
    207 	"{ [a] -> [b] : b = a }",
    208 	"{ [a] -> [b = a] : b >= 0 }",
    209 };
    210 
    211 #undef BASE
    212 #define BASE union_pw_multi_aff
    213 
    214 #include "check_parse_fail_test_templ.c"
    215 
    216 /* Test parsing of union piecewise multi affine expressions.
    217  *
    218  * In particular, check some cases where parsing is supposed to fail.
    219  */
    220 static isl_stat test_parse_upma(isl_ctx *ctx)
    221 {
    222 	if (check_parse_union_pw_multi_aff_fail_tests(ctx) < 0)
    223 		return isl_stat_error;
    224 
    225 	return isl_stat_ok;
    226 }
    227 
    228 /* Test parsing of multi piecewise affine expressions by printing
    229  * the expressions and checking that parsing the output results
    230  * in the same expression.
    231  * Do this for a couple of manually constructed expressions,
    232  * an expression converted from a map with an output dimension name
    233  * that is equal to an automatically generated name, and
    234  * a set of expressions parsed from strings.
    235  *
    236  * Additionally, check some cases where parsing is supposed to fail.
    237  */
    238 static int test_parse_mpa(isl_ctx *ctx)
    239 {
    240 	isl_space *space;
    241 	isl_set *dom;
    242 	isl_map *map;
    243 	isl_pw_multi_aff *pma;
    244 	isl_multi_pw_aff *mpa;
    245 	isl_stat r;
    246 
    247 	space = isl_space_set_alloc(ctx, 0, 0);
    248 	space = isl_space_set_tuple_name(space, isl_dim_set, "A");
    249 	mpa = isl_multi_pw_aff_zero(space);
    250 	r = check_reparse_multi_pw_aff(ctx, mpa);
    251 	if (r < 0)
    252 		return -1;
    253 
    254 	space = isl_space_set_alloc(ctx, 1, 0);
    255 	space = isl_space_set_dim_name(space, isl_dim_param, 0, "N");
    256 	space = isl_space_set_tuple_name(space, isl_dim_set, "A");
    257 	dom = isl_set_universe(isl_space_params(isl_space_copy(space)));
    258 	dom = isl_set_lower_bound_si(dom, isl_dim_param, 0, 5);
    259 	mpa = isl_multi_pw_aff_zero(space);
    260 	mpa = isl_multi_pw_aff_intersect_domain(mpa, dom);
    261 	r = check_reparse_multi_pw_aff(ctx, mpa);
    262 	if (r < 0)
    263 		return -1;
    264 
    265 	map = isl_map_read_from_str(ctx, "{ [a, a] -> [i1 = a + 1] }");
    266 	pma = isl_pw_multi_aff_from_map(map);
    267 	mpa = isl_multi_pw_aff_from_pw_multi_aff(pma);
    268 	if (check_reparse_multi_pw_aff(ctx, mpa) < 0)
    269 		return -1;
    270 
    271 	if (check_reparse_multi_pw_aff_tests(ctx) < 0)
    272 		return -1;
    273 	if (check_parse_multi_pw_aff_fail_tests(ctx) < 0)
    274 		return -1;
    275 
    276 	return 0;
    277 }
    278 
    279 /* String descriptions of multi union piecewise affine expressions
    280  * that are used for testing printing and parsing.
    281  */
    282 static const char *reparse_multi_union_pw_aff_tests[] = {
    283 	"[]",
    284 	"A[]",
    285 	"A[B[] -> C[]]",
    286 	"(A[] : { S[x] : x > 0; T[y] : y >= 0 })",
    287 	"(A[] : { })",
    288 	"[N] -> (A[] : { })",
    289 	"[N] -> (A[] : { : N >= 0 })",
    290 	"[N] -> (A[] : { S[x] : x > N; T[y] : y >= 0 })",
    291 	"(A[] : [N] -> { S[x] : x > N; T[y] : y >= 0 })",
    292 	"A[{ S[x] -> [x + 1]; T[x] -> [x] }]",
    293 	"(A[{ S[x] -> [x + 1]; T[x] -> [x] }] : "
    294 		"{ S[x] : x > 0; T[y] : y >= 0 })",
    295 };
    296 
    297 #undef BASE
    298 #define BASE multi_union_pw_aff
    299 
    300 #include "check_reparse_templ.c"
    301 #include "check_reparse_test_templ.c"
    302 
    303 /* Test parsing of multi union piecewise affine expressions by printing
    304  * the expressions and checking that parsing the output results
    305  * in the same expression.
    306  * Do this for a couple of manually constructed expressions and
    307  * a set of expressions parsed from strings.
    308  */
    309 static int test_parse_mupa(isl_ctx *ctx)
    310 {
    311 	isl_space *space;
    312 	isl_multi_union_pw_aff *mupa;
    313 	isl_set *dom;
    314 	isl_union_set *uset;
    315 	isl_stat r;
    316 
    317 	space = isl_space_set_alloc(ctx, 0, 0);
    318 	space = isl_space_set_tuple_name(space, isl_dim_set, "A");
    319 	mupa = isl_multi_union_pw_aff_zero(space);
    320 	r = check_reparse_multi_union_pw_aff(ctx, mupa);
    321 	if (r < 0)
    322 		return -1;
    323 
    324 	space = isl_space_set_alloc(ctx, 1, 0);
    325 	space = isl_space_set_dim_name(space, isl_dim_param, 0, "N");
    326 	space = isl_space_set_tuple_name(space, isl_dim_set, "A");
    327 	dom = isl_set_universe(space);
    328 	dom = isl_set_lower_bound_si(dom, isl_dim_param, 0, 5);
    329 	uset = isl_union_set_from_set(dom);
    330 	space = isl_space_set_alloc(ctx, 1, 0);
    331 	space = isl_space_set_dim_name(space, isl_dim_param, 0, "N");
    332 	space = isl_space_set_tuple_name(space, isl_dim_set, "B");
    333 	mupa = isl_multi_union_pw_aff_zero(space);
    334 	mupa = isl_multi_union_pw_aff_intersect_domain(mupa, uset);
    335 	r = check_reparse_multi_union_pw_aff(ctx, mupa);
    336 	if (r < 0)
    337 		return -1;
    338 
    339 	if (check_reparse_multi_union_pw_aff_tests(ctx) < 0)
    340 		return -1;
    341 
    342 	return 0;
    343 }
    344 
    345 /* Test parsing of multi expressions.
    346  */
    347 static int test_parse_multi(isl_ctx *ctx)
    348 {
    349 	if (test_parse_mpa(ctx) < 0)
    350 		return -1;
    351 	if (test_parse_mupa(ctx) < 0)
    352 		return -1;
    353 
    354 	return 0;
    355 }
    356 
    357 /* Pairs of binary relation representations that should represent
    358  * the same binary relations.
    359  */
    360 struct {
    361 	const char *map1;
    362 	const char *map2;
    363 } parse_map_equal_tests[] = {
    364 	{ "{ [x,y]  : [([x/2]+y)/3] >= 1 }",
    365 	  "{ [x, y] : 2y >= 6 - x }" },
    366 	{ "{ [x,y] : x <= min(y, 2*y+3) }",
    367 	  "{ [x,y] : x <= y, 2*y + 3 }" },
    368 	{ "{ [x,y] : x >= min(y, 2*y+3) }",
    369 	  "{ [x, y] : (y <= x and y >= -3) or (2y <= -3 + x and y <= -4) }" },
    370 	{ "[n] -> { [c1] : c1>=0 and c1<=floord(n-4,3) }",
    371 	  "[n] -> { [c1] : c1 >= 0 and 3c1 <= -4 + n }" },
    372 	{ "{ [i,j] -> [i] : i < j; [i,j] -> [j] : j <= i }",
    373 	  "{ [i,j] -> [min(i,j)] }" },
    374 	{ "{ [i,j] : i != j }",
    375 	  "{ [i,j] : i < j or i > j }" },
    376 	{ "{ [i,j] : (i+1)*2 >= j }",
    377 	  "{ [i, j] : j <= 2 + 2i }" },
    378 	{ "{ [i] -> [i > 0 ? 4 : 5] }",
    379 	  "{ [i] -> [5] : i <= 0; [i] -> [4] : i >= 1 }" },
    380 	{ "[N=2,M] -> { [i=[(M+N)/4]] }",
    381 	  "[N, M] -> { [i] : N = 2 and 4i <= 2 + M and 4i >= -1 + M }" },
    382 	{ "{ [x] : x >= 0 }",
    383 	  "{ [x] : x-0 >= 0 }" },
    384 	{ "{ [i] : ((i > 10)) }",
    385 	  "{ [i] : i >= 11 }" },
    386 	{ "{ [i] -> [0] }",
    387 	  "{ [i] -> [0 * i] }" },
    388 	{ "{ [a] -> [b] : (not false) }",
    389 	  "{ [a] -> [b] : true }" },
    390 	{ "{ [i] : i/2 <= 5 }",
    391 	  "{ [i] : i <= 10 }" },
    392 	{ "{Sym=[n] [i] : i <= n }",
    393 	  "[n] -> { [i] : i <= n }" },
    394 	{ "{ [*] }",
    395 	  "{ [a] }" },
    396 	{ "{ [i] : 2*floor(i/2) = i }",
    397 	  "{ [i] : exists a : i = 2 a }" },
    398 	{ "{ [a] -> [b] : a = 5 implies b = 5 }",
    399 	  "{ [a] -> [b] : a != 5 or b = 5 }" },
    400 	{ "{ [a] -> [a - 1 : a > 0] }",
    401 	  "{ [a] -> [a - 1] : a > 0 }" },
    402 	{ "{ [a] -> [a - 1 : a > 0; a : a <= 0] }",
    403 	  "{ [a] -> [a - 1] : a > 0; [a] -> [a] : a <= 0 }" },
    404 	{ "{ [a] -> [(a) * 2 : a >= 0; 0 : a < 0] }",
    405 	  "{ [a] -> [2a] : a >= 0; [a] -> [0] : a < 0 }" },
    406 	{ "{ [a] -> [(a * 2) : a >= 0; 0 : a < 0] }",
    407 	  "{ [a] -> [2a] : a >= 0; [a] -> [0] : a < 0 }" },
    408 	{ "{ [a] -> [(a * 2 : a >= 0); 0 : a < 0] }",
    409 	  "{ [a] -> [2a] : a >= 0; [a] -> [0] : a < 0 }" },
    410 	{ "{ [a] -> [(a * 2 : a >= 0; 0 : a < 0)] }",
    411 	  "{ [a] -> [2a] : a >= 0; [a] -> [0] : a < 0 }" },
    412 	{ "{ [a,b] -> [i,j] : a,b << i,j }",
    413 	  "{ [a,b] -> [i,j] : a < i or (a = i and b < j) }" },
    414 	{ "{ [a,b] -> [i,j] : a,b <<= i,j }",
    415 	  "{ [a,b] -> [i,j] : a < i or (a = i and b <= j) }" },
    416 	{ "{ [a,b] -> [i,j] : a,b >> i,j }",
    417 	  "{ [a,b] -> [i,j] : a > i or (a = i and b > j) }" },
    418 	{ "{ [a,b] -> [i,j] : a,b >>= i,j }",
    419 	  "{ [a,b] -> [i,j] : a > i or (a = i and b >= j) }" },
    420 	{ "{ [n] -> [i] : exists (a, b, c: 8b <= i - 32a and "
    421 			    "8b >= -7 + i - 32 a and b >= 0 and b <= 3 and "
    422 			    "8c < n - 32a and i < n and c >= 0 and "
    423 			    "c <= 3 and c >= -4a) }",
    424 	  "{ [n] -> [i] : 0 <= i < n }" },
    425 	{ "{ [x] -> [] : exists (a, b: 0 <= a <= 1 and 0 <= b <= 3 and "
    426 			    "2b <= x - 8a and 2b >= -1 + x - 8a) }",
    427 	  "{ [x] -> [] : 0 <= x <= 15 }" },
    428 	{ "{ [x] -> [x] : }",
    429 	  "{ [x] -> [x] }" },
    430 	{ "{ [x=4:5] -> [x + 1] }",
    431 	  "{ [x] -> [x + 1] : 4 <= x <= 5 }" },
    432 	{ "{ [x=4:5] -> [x + 1 : x + 1] }",
    433 	  "{ [x=4:5] -> [x + 1] }" },
    434 	{ "{ [x] -> [x - 1 : x + 1] }",
    435 	  "{ [x] -> [y] : x - 1 <= y <= x + 1 }" },
    436 	{ "{ [x=4:] -> [x + 1] }",
    437 	  "{ [x] -> [x + 1] : 4 <= x }" },
    438 	{ "{ [x=:5] -> [x + 1] }",
    439 	  "{ [x] -> [x + 1] : x <= 5 }" },
    440 	{ "{ [x=:] -> [x + 1] }",
    441 	  "{ [x] -> [x + 1] }" },
    442 	{ "{ [:] -> [:] }",
    443 	  "{ [x] -> [y] }" },
    444 	{ "{ [x, x//4] }",
    445 	  "{ [x, floor(x/4)] }" },
    446 	{ "{ [10//4] }",
    447 	  "{ [2] }" },
    448 	{ "{ [-1//4] }",
    449 	  "{ [-1] }" },
    450 	{ "{ [0-1//4] }",
    451 	  "{ [0] }" },
    452 	{ "{ [- 1//4] }",
    453 	  "{ [-1] }" },
    454 	{ "{ [0 - 1//4] }",
    455 	  "{ [0] }" },
    456 	{ "{ [0--1//4] }",
    457 	  "{ [1] }" },
    458 	{ "{ [0 - -1//4] }",
    459 	  "{ [1] }" },
    460 	{ "{ [-2^2:2^2-1] }",
    461 	  "{ [-4:3] }" },
    462 	{ "{ [2*-2] }",
    463 	  "{ [-4] }" },
    464 	{ "{ [i,i*-2] }",
    465 	  "{ [i,-2i] }" },
    466 	{ "[a, b, c, d] -> { [max(a,b,c,d)] }",
    467 	  "[a, b, c, d] -> { [a] : b < a and c < a and d < a; "
    468 		"[b] : b >= a and c < b and d < b; "
    469 		"[c] : c >= a and c >= b and d < c; "
    470 		"[d] : d >= a and d >= b and d >= c }" },
    471 	{ "[a, b, c, d] -> { [min(a,b,c,d)] }",
    472 	  "[a, b, c, d] -> { [a] : b >= a and c >= a and d >= a; "
    473 		"[b] : b < a and c >= b and d >= b; "
    474 		"[c] : c < b and c < a and d >= c; "
    475 		"[d] : d < c and d < b and d < a }" },
    476 };
    477 
    478 int test_parse(struct isl_ctx *ctx)
    479 {
    480 	int i;
    481 	isl_map *map, *map2;
    482 	const char *str, *str2;
    483 
    484 	if (test_parse_multi_val(ctx, "{ A[B[2] -> C[5, 7]] }") < 0)
    485 		return -1;
    486 	if (test_parse_multi_val(ctx, "[n] -> { [2] }") < 0)
    487 		return -1;
    488 	if (test_parse_multi_val(ctx, "{ A[4, infty, NaN, -1/2, 2/3] }") < 0)
    489 		return -1;
    490 	if (test_parse_multi(ctx) < 0)
    491 		return -1;
    492 	if (test_parse_pma(ctx) < 0)
    493 		return -1;
    494 	if (test_parse_upma(ctx) < 0)
    495 		return -1;
    496 
    497 	str = "{ [i] -> [-i] }";
    498 	map = isl_map_read_from_str(ctx, str);
    499 	assert(map);
    500 	isl_map_free(map);
    501 
    502 	str = "{ A[i] -> L[([i/3])] }";
    503 	map = isl_map_read_from_str(ctx, str);
    504 	assert(map);
    505 	isl_map_free(map);
    506 
    507 	test_parse_map(ctx, "{[[s] -> A[i]] -> [[s+1] -> A[i]]}");
    508 	test_parse_map(ctx, "{ [p1, y1, y2] -> [2, y1, y2] : "
    509 				"p1 = 1 && (y1 <= y2 || y2 = 0) }");
    510 
    511 	for (i = 0; i < ARRAY_SIZE(parse_map_equal_tests); ++i) {
    512 		str = parse_map_equal_tests[i].map1;
    513 		str2 = parse_map_equal_tests[i].map2;
    514 		if (test_parse_map_equal(ctx, str, str2) < 0)
    515 			return -1;
    516 	}
    517 
    518 	str = "{[new,old] -> [new+1-2*[(new+1)/2],old+1-2*[(old+1)/2]]}";
    519 	map = isl_map_read_from_str(ctx, str);
    520 	str = "{ [new, old] -> [o0, o1] : "
    521 	       "exists (e0 = [(-1 - new + o0)/2], e1 = [(-1 - old + o1)/2]: "
    522 	       "2e0 = -1 - new + o0 and 2e1 = -1 - old + o1 and o0 >= 0 and "
    523 	       "o0 <= 1 and o1 >= 0 and o1 <= 1) }";
    524 	map2 = isl_map_read_from_str(ctx, str);
    525 	assert(isl_map_is_equal(map, map2));
    526 	isl_map_free(map);
    527 	isl_map_free(map2);
    528 
    529 	str = "{[new,old] -> [new+1-2*[(new+1)/2],old+1-2*[(old+1)/2]]}";
    530 	map = isl_map_read_from_str(ctx, str);
    531 	str = "{[new,old] -> [(new+1)%2,(old+1)%2]}";
    532 	map2 = isl_map_read_from_str(ctx, str);
    533 	assert(isl_map_is_equal(map, map2));
    534 	isl_map_free(map);
    535 	isl_map_free(map2);
    536 
    537 	test_parse_pwqp(ctx, "{ [i] -> i + [ (i + [i/3])/2 ] }");
    538 	test_parse_map(ctx, "{ S1[i] -> [([i/10]),i%10] : 0 <= i <= 45 }");
    539 	test_parse_pwaff(ctx, "{ [i] -> [i + 1] : i > 0; [a] -> [a] : a < 0 }");
    540 	test_parse_pwqp(ctx, "{ [x] -> ([(x)/2] * [(x)/3]) }");
    541 	test_parse_pwaff(ctx, "{ [] -> [(100)] }");
    542 
    543 	return 0;
    544 }
    545 
    546 static int test_read(isl_ctx *ctx)
    547 {
    548 	char *filename;
    549 	FILE *input;
    550 	isl_basic_set *bset1, *bset2;
    551 	const char *str = "{[y]: Exists ( alpha : 2alpha = y)}";
    552 	int equal;
    553 
    554 	filename = get_filename(ctx, "set", "omega");
    555 	assert(filename);
    556 	input = fopen(filename, "r");
    557 	assert(input);
    558 
    559 	bset1 = isl_basic_set_read_from_file(ctx, input);
    560 	bset2 = isl_basic_set_read_from_str(ctx, str);
    561 
    562 	equal = isl_basic_set_is_equal(bset1, bset2);
    563 
    564 	isl_basic_set_free(bset1);
    565 	isl_basic_set_free(bset2);
    566 	free(filename);
    567 
    568 	fclose(input);
    569 
    570 	if (equal < 0)
    571 		return -1;
    572 	if (!equal)
    573 		isl_die(ctx, isl_error_unknown,
    574 			"read sets not equal", return -1);
    575 
    576 	return 0;
    577 }
    578 
    579 static int test_bounded(isl_ctx *ctx)
    580 {
    581 	isl_set *set;
    582 	isl_bool bounded;
    583 
    584 	set = isl_set_read_from_str(ctx, "[n] -> {[i] : 0 <= i <= n }");
    585 	bounded = isl_set_is_bounded(set);
    586 	isl_set_free(set);
    587 
    588 	if (bounded < 0)
    589 		return -1;
    590 	if (!bounded)
    591 		isl_die(ctx, isl_error_unknown,
    592 			"set not considered bounded", return -1);
    593 
    594 	set = isl_set_read_from_str(ctx, "{[n, i] : 0 <= i <= n }");
    595 	bounded = isl_set_is_bounded(set);
    596 	assert(!bounded);
    597 	isl_set_free(set);
    598 
    599 	if (bounded < 0)
    600 		return -1;
    601 	if (bounded)
    602 		isl_die(ctx, isl_error_unknown,
    603 			"set considered bounded", return -1);
    604 
    605 	set = isl_set_read_from_str(ctx, "[n] -> {[i] : i <= n }");
    606 	bounded = isl_set_is_bounded(set);
    607 	isl_set_free(set);
    608 
    609 	if (bounded < 0)
    610 		return -1;
    611 	if (bounded)
    612 		isl_die(ctx, isl_error_unknown,
    613 			"set considered bounded", return -1);
    614 
    615 	return 0;
    616 }
    617 
    618 /* Construct the basic set { [i] : 5 <= i <= N } */
    619 static int test_construction_1(isl_ctx *ctx)
    620 {
    621 	isl_space *space;
    622 	isl_local_space *ls;
    623 	isl_basic_set *bset;
    624 	isl_constraint *c;
    625 
    626 	space = isl_space_set_alloc(ctx, 1, 1);
    627 	bset = isl_basic_set_universe(isl_space_copy(space));
    628 	ls = isl_local_space_from_space(space);
    629 
    630 	c = isl_constraint_alloc_inequality(isl_local_space_copy(ls));
    631 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, -1);
    632 	c = isl_constraint_set_coefficient_si(c, isl_dim_param, 0, 1);
    633 	bset = isl_basic_set_add_constraint(bset, c);
    634 
    635 	c = isl_constraint_alloc_inequality(isl_local_space_copy(ls));
    636 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, 1);
    637 	c = isl_constraint_set_constant_si(c, -5);
    638 	bset = isl_basic_set_add_constraint(bset, c);
    639 
    640 	isl_local_space_free(ls);
    641 	isl_basic_set_free(bset);
    642 
    643 	return 0;
    644 }
    645 
    646 /* Construct the basic set { [x] : -100 <= x <= 100 }
    647  * using isl_basic_set_{lower,upper}_bound_val and
    648  * check that it is equal the same basic set parsed from a string.
    649  */
    650 static int test_construction_2(isl_ctx *ctx)
    651 {
    652 	isl_bool equal;
    653 	isl_val *v;
    654 	isl_space *space;
    655 	isl_basic_set *bset1, *bset2;
    656 
    657 	v = isl_val_int_from_si(ctx, 100);
    658 	space = isl_space_set_alloc(ctx, 0, 1);
    659 	bset1 = isl_basic_set_universe(space);
    660 	bset1 = isl_basic_set_upper_bound_val(bset1, isl_dim_set, 0,
    661 						isl_val_copy(v));
    662 	bset1 = isl_basic_set_lower_bound_val(bset1, isl_dim_set, 0,
    663 						isl_val_neg(v));
    664 	bset2 = isl_basic_set_read_from_str(ctx, "{ [x] : -100 <= x <= 100 }");
    665 	equal = isl_basic_set_is_equal(bset1, bset2);
    666 	isl_basic_set_free(bset1);
    667 	isl_basic_set_free(bset2);
    668 
    669 	if (equal < 0)
    670 		return -1;
    671 	if (!equal)
    672 		isl_die(ctx, isl_error_unknown,
    673 			"failed construction", return -1);
    674 
    675 	return 0;
    676 }
    677 
    678 /* Basic tests for constructing basic sets.
    679  */
    680 static int test_construction(isl_ctx *ctx)
    681 {
    682 	if (test_construction_1(ctx) < 0)
    683 		return -1;
    684 	if (test_construction_2(ctx) < 0)
    685 		return -1;
    686 	return 0;
    687 }
    688 
    689 static int test_dim(isl_ctx *ctx)
    690 {
    691 	const char *str;
    692 	isl_map *map1, *map2;
    693 	int equal;
    694 
    695 	map1 = isl_map_read_from_str(ctx,
    696 	    "[n] -> { [i] -> [j] : exists (a = [i/10] : i - 10a <= n ) }");
    697 	map1 = isl_map_add_dims(map1, isl_dim_in, 1);
    698 	map2 = isl_map_read_from_str(ctx,
    699 	    "[n] -> { [i,k] -> [j] : exists (a = [i/10] : i - 10a <= n ) }");
    700 	equal = isl_map_is_equal(map1, map2);
    701 	isl_map_free(map2);
    702 
    703 	map1 = isl_map_project_out(map1, isl_dim_in, 0, 1);
    704 	map2 = isl_map_read_from_str(ctx, "[n] -> { [i] -> [j] : n >= 0 }");
    705 	if (equal >= 0 && equal)
    706 		equal = isl_map_is_equal(map1, map2);
    707 
    708 	isl_map_free(map1);
    709 	isl_map_free(map2);
    710 
    711 	if (equal < 0)
    712 		return -1;
    713 	if (!equal)
    714 		isl_die(ctx, isl_error_unknown,
    715 			"unexpected result", return -1);
    716 
    717 	str = "[n] -> { [i] -> [] : exists a : 0 <= i <= n and i = 2 a }";
    718 	map1 = isl_map_read_from_str(ctx, str);
    719 	str = "{ [i] -> [j] : exists a : 0 <= i <= j and i = 2 a }";
    720 	map2 = isl_map_read_from_str(ctx, str);
    721 	map1 = isl_map_move_dims(map1, isl_dim_out, 0, isl_dim_param, 0, 1);
    722 	equal = isl_map_is_equal(map1, map2);
    723 	isl_map_free(map1);
    724 	isl_map_free(map2);
    725 
    726 	if (equal < 0)
    727 		return -1;
    728 	if (!equal)
    729 		isl_die(ctx, isl_error_unknown,
    730 			"unexpected result", return -1);
    731 
    732 	return 0;
    733 }
    734 
    735 #undef BASE
    736 #define BASE	multi_val
    737 #include "isl_test_plain_equal_templ.c"
    738 
    739 #undef BASE
    740 #define BASE	multi_aff
    741 #include "isl_test_plain_equal_templ.c"
    742 
    743 /* Check that "val" is equal to the value described by "str".
    744  * If "str" is "NaN", then check for a NaN value explicitly.
    745  */
    746 static isl_stat val_check_equal(__isl_keep isl_val *val, const char *str)
    747 {
    748 	isl_bool ok, is_nan;
    749 	isl_ctx *ctx;
    750 	isl_val *res;
    751 
    752 	if (!val)
    753 		return isl_stat_error;
    754 
    755 	ctx = isl_val_get_ctx(val);
    756 	res = isl_val_read_from_str(ctx, str);
    757 	is_nan = isl_val_is_nan(res);
    758 	if (is_nan < 0)
    759 		ok = isl_bool_error;
    760 	else if (is_nan)
    761 		ok = isl_val_is_nan(val);
    762 	else
    763 		ok = isl_val_eq(val, res);
    764 	isl_val_free(res);
    765 	if (ok < 0)
    766 		return isl_stat_error;
    767 	if (!ok)
    768 		isl_die(ctx, isl_error_unknown,
    769 			"unexpected result", return isl_stat_error);
    770 	return isl_stat_ok;
    771 }
    772 
    773 struct {
    774 	__isl_give isl_val *(*op)(__isl_take isl_val *v);
    775 	const char *arg;
    776 	const char *res;
    777 } val_un_tests[] = {
    778 	{ &isl_val_neg, "0", "0" },
    779 	{ &isl_val_abs, "0", "0" },
    780 	{ &isl_val_pow2, "0", "1" },
    781 	{ &isl_val_floor, "0", "0" },
    782 	{ &isl_val_ceil, "0", "0" },
    783 	{ &isl_val_neg, "1", "-1" },
    784 	{ &isl_val_neg, "-1", "1" },
    785 	{ &isl_val_neg, "1/2", "-1/2" },
    786 	{ &isl_val_neg, "-1/2", "1/2" },
    787 	{ &isl_val_neg, "infty", "-infty" },
    788 	{ &isl_val_neg, "-infty", "infty" },
    789 	{ &isl_val_neg, "NaN", "NaN" },
    790 	{ &isl_val_abs, "1", "1" },
    791 	{ &isl_val_abs, "-1", "1" },
    792 	{ &isl_val_abs, "1/2", "1/2" },
    793 	{ &isl_val_abs, "-1/2", "1/2" },
    794 	{ &isl_val_abs, "infty", "infty" },
    795 	{ &isl_val_abs, "-infty", "infty" },
    796 	{ &isl_val_abs, "NaN", "NaN" },
    797 	{ &isl_val_floor, "1", "1" },
    798 	{ &isl_val_floor, "-1", "-1" },
    799 	{ &isl_val_floor, "1/2", "0" },
    800 	{ &isl_val_floor, "-1/2", "-1" },
    801 	{ &isl_val_floor, "infty", "infty" },
    802 	{ &isl_val_floor, "-infty", "-infty" },
    803 	{ &isl_val_floor, "NaN", "NaN" },
    804 	{ &isl_val_ceil, "1", "1" },
    805 	{ &isl_val_ceil, "-1", "-1" },
    806 	{ &isl_val_ceil, "1/2", "1" },
    807 	{ &isl_val_ceil, "-1/2", "0" },
    808 	{ &isl_val_ceil, "infty", "infty" },
    809 	{ &isl_val_ceil, "-infty", "-infty" },
    810 	{ &isl_val_ceil, "NaN", "NaN" },
    811 	{ &isl_val_pow2, "-3", "1/8" },
    812 	{ &isl_val_pow2, "-1", "1/2" },
    813 	{ &isl_val_pow2, "1", "2" },
    814 	{ &isl_val_pow2, "2", "4" },
    815 	{ &isl_val_pow2, "3", "8" },
    816 	{ &isl_val_inv, "1", "1" },
    817 	{ &isl_val_inv, "2", "1/2" },
    818 	{ &isl_val_inv, "1/2", "2" },
    819 	{ &isl_val_inv, "-2", "-1/2" },
    820 	{ &isl_val_inv, "-1/2", "-2" },
    821 	{ &isl_val_inv, "0", "NaN" },
    822 	{ &isl_val_inv, "NaN", "NaN" },
    823 	{ &isl_val_inv, "infty", "0" },
    824 	{ &isl_val_inv, "-infty", "0" },
    825 };
    826 
    827 /* Perform some basic tests of unary operations on isl_val objects.
    828  */
    829 static int test_un_val(isl_ctx *ctx)
    830 {
    831 	int i;
    832 	isl_val *v;
    833 	__isl_give isl_val *(*fn)(__isl_take isl_val *v);
    834 
    835 	for (i = 0; i < ARRAY_SIZE(val_un_tests); ++i) {
    836 		isl_stat r;
    837 
    838 		v = isl_val_read_from_str(ctx, val_un_tests[i].arg);
    839 		fn = val_un_tests[i].op;
    840 		v = fn(v);
    841 		r = val_check_equal(v, val_un_tests[i].res);
    842 		isl_val_free(v);
    843 		if (r < 0)
    844 			return -1;
    845 	}
    846 
    847 	return 0;
    848 }
    849 
    850 struct {
    851 	__isl_give isl_val *(*fn)(__isl_take isl_val *v1,
    852 				__isl_take isl_val *v2);
    853 } val_bin_op[] = {
    854 	['+'] = { &isl_val_add },
    855 	['-'] = { &isl_val_sub },
    856 	['*'] = { &isl_val_mul },
    857 	['/'] = { &isl_val_div },
    858 	['g'] = { &isl_val_gcd },
    859 	['m'] = { &isl_val_min },
    860 	['M'] = { &isl_val_max },
    861 };
    862 
    863 struct {
    864 	const char *arg1;
    865 	unsigned char op;
    866 	const char *arg2;
    867 	const char *res;
    868 } val_bin_tests[] = {
    869 	{ "0", '+', "0", "0" },
    870 	{ "1", '+', "0", "1" },
    871 	{ "1", '+', "1", "2" },
    872 	{ "1", '-', "1", "0" },
    873 	{ "1", '*', "1", "1" },
    874 	{ "1", '/', "1", "1" },
    875 	{ "2", '*', "3", "6" },
    876 	{ "2", '*', "1/2", "1" },
    877 	{ "2", '*', "1/3", "2/3" },
    878 	{ "2/3", '*', "3/5", "2/5" },
    879 	{ "2/3", '*', "7/5", "14/15" },
    880 	{ "2", '/', "1/2", "4" },
    881 	{ "-2", '/', "-1/2", "4" },
    882 	{ "-2", '/', "1/2", "-4" },
    883 	{ "2", '/', "-1/2", "-4" },
    884 	{ "2", '/', "2", "1" },
    885 	{ "2", '/', "3", "2/3" },
    886 	{ "2/3", '/', "5/3", "2/5" },
    887 	{ "2/3", '/', "5/7", "14/15" },
    888 	{ "0", '/', "0", "NaN" },
    889 	{ "42", '/', "0", "NaN" },
    890 	{ "-42", '/', "0", "NaN" },
    891 	{ "infty", '/', "0", "NaN" },
    892 	{ "-infty", '/', "0", "NaN" },
    893 	{ "NaN", '/', "0", "NaN" },
    894 	{ "0", '/', "NaN", "NaN" },
    895 	{ "42", '/', "NaN", "NaN" },
    896 	{ "-42", '/', "NaN", "NaN" },
    897 	{ "infty", '/', "NaN", "NaN" },
    898 	{ "-infty", '/', "NaN", "NaN" },
    899 	{ "NaN", '/', "NaN", "NaN" },
    900 	{ "0", '/', "infty", "0" },
    901 	{ "42", '/', "infty", "0" },
    902 	{ "-42", '/', "infty", "0" },
    903 	{ "infty", '/', "infty", "NaN" },
    904 	{ "-infty", '/', "infty", "NaN" },
    905 	{ "NaN", '/', "infty", "NaN" },
    906 	{ "0", '/', "-infty", "0" },
    907 	{ "42", '/', "-infty", "0" },
    908 	{ "-42", '/', "-infty", "0" },
    909 	{ "infty", '/', "-infty", "NaN" },
    910 	{ "-infty", '/', "-infty", "NaN" },
    911 	{ "NaN", '/', "-infty", "NaN" },
    912 	{ "1", '-', "1/3", "2/3" },
    913 	{ "1/3", '+', "1/2", "5/6" },
    914 	{ "1/2", '+', "1/2", "1" },
    915 	{ "3/4", '-', "1/4", "1/2" },
    916 	{ "1/2", '-', "1/3", "1/6" },
    917 	{ "infty", '+', "42", "infty" },
    918 	{ "infty", '+', "infty", "infty" },
    919 	{ "42", '+', "infty", "infty" },
    920 	{ "infty", '-', "infty", "NaN" },
    921 	{ "infty", '*', "infty", "infty" },
    922 	{ "infty", '*', "-infty", "-infty" },
    923 	{ "-infty", '*', "infty", "-infty" },
    924 	{ "-infty", '*', "-infty", "infty" },
    925 	{ "0", '*', "infty", "NaN" },
    926 	{ "1", '*', "infty", "infty" },
    927 	{ "infty", '*', "0", "NaN" },
    928 	{ "infty", '*', "42", "infty" },
    929 	{ "42", '-', "infty", "-infty" },
    930 	{ "infty", '+', "-infty", "NaN" },
    931 	{ "4", 'g', "6", "2" },
    932 	{ "5", 'g', "6", "1" },
    933 	{ "42", 'm', "3", "3" },
    934 	{ "42", 'M', "3", "42" },
    935 	{ "3", 'm', "42", "3" },
    936 	{ "3", 'M', "42", "42" },
    937 	{ "42", 'm', "infty", "42" },
    938 	{ "42", 'M', "infty", "infty" },
    939 	{ "42", 'm', "-infty", "-infty" },
    940 	{ "42", 'M', "-infty", "42" },
    941 	{ "42", 'm', "NaN", "NaN" },
    942 	{ "42", 'M', "NaN", "NaN" },
    943 	{ "infty", 'm', "-infty", "-infty" },
    944 	{ "infty", 'M', "-infty", "infty" },
    945 };
    946 
    947 /* Perform some basic tests of binary operations on isl_val objects.
    948  */
    949 static int test_bin_val(isl_ctx *ctx)
    950 {
    951 	int i;
    952 	isl_val *v1, *v2, *res;
    953 	__isl_give isl_val *(*fn)(__isl_take isl_val *v1,
    954 				__isl_take isl_val *v2);
    955 	int ok;
    956 
    957 	for (i = 0; i < ARRAY_SIZE(val_bin_tests); ++i) {
    958 		v1 = isl_val_read_from_str(ctx, val_bin_tests[i].arg1);
    959 		v2 = isl_val_read_from_str(ctx, val_bin_tests[i].arg2);
    960 		res = isl_val_read_from_str(ctx, val_bin_tests[i].res);
    961 		fn = val_bin_op[val_bin_tests[i].op].fn;
    962 		v1 = fn(v1, v2);
    963 		if (isl_val_is_nan(res))
    964 			ok = isl_val_is_nan(v1);
    965 		else
    966 			ok = isl_val_eq(v1, res);
    967 		isl_val_free(v1);
    968 		isl_val_free(res);
    969 		if (ok < 0)
    970 			return -1;
    971 		if (!ok)
    972 			isl_die(ctx, isl_error_unknown,
    973 				"unexpected result", return -1);
    974 	}
    975 
    976 	return 0;
    977 }
    978 
    979 /* Perform some basic tests on isl_val objects.
    980  */
    981 static int test_val(isl_ctx *ctx)
    982 {
    983 	if (test_un_val(ctx) < 0)
    984 		return -1;
    985 	if (test_bin_val(ctx) < 0)
    986 		return -1;
    987 	return 0;
    988 }
    989 
    990 /* Sets described using existentially quantified variables that
    991  * can also be described without.
    992  */
    993 static const char *elimination_tests[] = {
    994 	"{ [i,j] : 2 * [i/2] + 3 * [j/4] <= 10 and 2 i = j }",
    995 	"{ [m, w] : exists a : w - 2m - 5 <= 3a <= m - 2w }",
    996 	"{ [m, w] : exists a : w >= 0 and a < m and -1 + w <= a <= 2m - w }",
    997 };
    998 
    999 /* Check that redundant existentially quantified variables are
   1000  * getting removed.
   1001  */
   1002 static int test_elimination(isl_ctx *ctx)
   1003 {
   1004 	int i;
   1005 	isl_size n;
   1006 	isl_basic_set *bset;
   1007 
   1008 	for (i = 0; i < ARRAY_SIZE(elimination_tests); ++i) {
   1009 		bset = isl_basic_set_read_from_str(ctx, elimination_tests[i]);
   1010 		n = isl_basic_set_dim(bset, isl_dim_div);
   1011 		isl_basic_set_free(bset);
   1012 		if (n < 0)
   1013 			return -1;
   1014 		if (n != 0)
   1015 			isl_die(ctx, isl_error_unknown,
   1016 				"expecting no existentials", return -1);
   1017 	}
   1018 
   1019 	return 0;
   1020 }
   1021 
   1022 static int test_div(isl_ctx *ctx)
   1023 {
   1024 	const char *str;
   1025 	int empty;
   1026 	isl_space *space;
   1027 	isl_set *set;
   1028 	isl_local_space *ls;
   1029 	struct isl_basic_set *bset;
   1030 	struct isl_constraint *c;
   1031 
   1032 	/* test 1 */
   1033 	space = isl_space_set_alloc(ctx, 0, 3);
   1034 	bset = isl_basic_set_universe(isl_space_copy(space));
   1035 	ls = isl_local_space_from_space(space);
   1036 
   1037 	c = isl_constraint_alloc_equality(isl_local_space_copy(ls));
   1038 	c = isl_constraint_set_constant_si(c, -1);
   1039 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, 1);
   1040 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 1, 3);
   1041 	bset = isl_basic_set_add_constraint(bset, c);
   1042 
   1043 	c = isl_constraint_alloc_equality(isl_local_space_copy(ls));
   1044 	c = isl_constraint_set_constant_si(c, 1);
   1045 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, -1);
   1046 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 2, 3);
   1047 	bset = isl_basic_set_add_constraint(bset, c);
   1048 
   1049 	bset = isl_basic_set_project_out(bset, isl_dim_set, 1, 2);
   1050 
   1051 	assert(bset && bset->n_div == 1);
   1052 	isl_local_space_free(ls);
   1053 	isl_basic_set_free(bset);
   1054 
   1055 	/* test 2 */
   1056 	space = isl_space_set_alloc(ctx, 0, 3);
   1057 	bset = isl_basic_set_universe(isl_space_copy(space));
   1058 	ls = isl_local_space_from_space(space);
   1059 
   1060 	c = isl_constraint_alloc_equality(isl_local_space_copy(ls));
   1061 	c = isl_constraint_set_constant_si(c, 1);
   1062 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, -1);
   1063 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 1, 3);
   1064 	bset = isl_basic_set_add_constraint(bset, c);
   1065 
   1066 	c = isl_constraint_alloc_equality(isl_local_space_copy(ls));
   1067 	c = isl_constraint_set_constant_si(c, -1);
   1068 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, 1);
   1069 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 2, 3);
   1070 	bset = isl_basic_set_add_constraint(bset, c);
   1071 
   1072 	bset = isl_basic_set_project_out(bset, isl_dim_set, 1, 2);
   1073 
   1074 	assert(bset && bset->n_div == 1);
   1075 	isl_local_space_free(ls);
   1076 	isl_basic_set_free(bset);
   1077 
   1078 	/* test 3 */
   1079 	space = isl_space_set_alloc(ctx, 0, 3);
   1080 	bset = isl_basic_set_universe(isl_space_copy(space));
   1081 	ls = isl_local_space_from_space(space);
   1082 
   1083 	c = isl_constraint_alloc_equality(isl_local_space_copy(ls));
   1084 	c = isl_constraint_set_constant_si(c, 1);
   1085 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, -1);
   1086 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 1, 3);
   1087 	bset = isl_basic_set_add_constraint(bset, c);
   1088 
   1089 	c = isl_constraint_alloc_equality(isl_local_space_copy(ls));
   1090 	c = isl_constraint_set_constant_si(c, -3);
   1091 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, 1);
   1092 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 2, 4);
   1093 	bset = isl_basic_set_add_constraint(bset, c);
   1094 
   1095 	bset = isl_basic_set_project_out(bset, isl_dim_set, 1, 2);
   1096 
   1097 	assert(bset && bset->n_div == 1);
   1098 	isl_local_space_free(ls);
   1099 	isl_basic_set_free(bset);
   1100 
   1101 	/* test 4 */
   1102 	space = isl_space_set_alloc(ctx, 0, 3);
   1103 	bset = isl_basic_set_universe(isl_space_copy(space));
   1104 	ls = isl_local_space_from_space(space);
   1105 
   1106 	c = isl_constraint_alloc_equality(isl_local_space_copy(ls));
   1107 	c = isl_constraint_set_constant_si(c, 2);
   1108 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, -1);
   1109 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 1, 3);
   1110 	bset = isl_basic_set_add_constraint(bset, c);
   1111 
   1112 	c = isl_constraint_alloc_equality(isl_local_space_copy(ls));
   1113 	c = isl_constraint_set_constant_si(c, -1);
   1114 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, 1);
   1115 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 2, 6);
   1116 	bset = isl_basic_set_add_constraint(bset, c);
   1117 
   1118 	bset = isl_basic_set_project_out(bset, isl_dim_set, 1, 2);
   1119 
   1120 	assert(isl_basic_set_is_empty(bset));
   1121 	isl_local_space_free(ls);
   1122 	isl_basic_set_free(bset);
   1123 
   1124 	/* test 5 */
   1125 	space = isl_space_set_alloc(ctx, 0, 3);
   1126 	bset = isl_basic_set_universe(isl_space_copy(space));
   1127 	ls = isl_local_space_from_space(space);
   1128 
   1129 	c = isl_constraint_alloc_equality(isl_local_space_copy(ls));
   1130 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, -1);
   1131 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 2, 3);
   1132 	bset = isl_basic_set_add_constraint(bset, c);
   1133 
   1134 	c = isl_constraint_alloc_equality(isl_local_space_copy(ls));
   1135 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, 1);
   1136 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 1, -3);
   1137 	bset = isl_basic_set_add_constraint(bset, c);
   1138 
   1139 	bset = isl_basic_set_project_out(bset, isl_dim_set, 2, 1);
   1140 
   1141 	assert(bset && bset->n_div == 0);
   1142 	isl_basic_set_free(bset);
   1143 	isl_local_space_free(ls);
   1144 
   1145 	/* test 6 */
   1146 	space = isl_space_set_alloc(ctx, 0, 3);
   1147 	bset = isl_basic_set_universe(isl_space_copy(space));
   1148 	ls = isl_local_space_from_space(space);
   1149 
   1150 	c = isl_constraint_alloc_equality(isl_local_space_copy(ls));
   1151 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, -1);
   1152 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 2, 6);
   1153 	bset = isl_basic_set_add_constraint(bset, c);
   1154 
   1155 	c = isl_constraint_alloc_equality(isl_local_space_copy(ls));
   1156 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, 1);
   1157 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 1, -3);
   1158 	bset = isl_basic_set_add_constraint(bset, c);
   1159 
   1160 	bset = isl_basic_set_project_out(bset, isl_dim_set, 2, 1);
   1161 
   1162 	assert(bset && bset->n_div == 1);
   1163 	isl_basic_set_free(bset);
   1164 	isl_local_space_free(ls);
   1165 
   1166 	/* test 7 */
   1167 	/* This test is a bit tricky.  We set up an equality
   1168 	 *		a + 3b + 3c = 6 e0
   1169 	 * Normalization of divs creates _two_ divs
   1170 	 *		a = 3 e0
   1171 	 *		c - b - e0 = 2 e1
   1172 	 * Afterwards e0 is removed again because it has coefficient -1
   1173 	 * and we end up with the original equality and div again.
   1174 	 * Perhaps we can avoid the introduction of this temporary div.
   1175 	 */
   1176 	space = isl_space_set_alloc(ctx, 0, 4);
   1177 	bset = isl_basic_set_universe(isl_space_copy(space));
   1178 	ls = isl_local_space_from_space(space);
   1179 
   1180 	c = isl_constraint_alloc_equality(isl_local_space_copy(ls));
   1181 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, -1);
   1182 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 1, -3);
   1183 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 2, -3);
   1184 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 3, 6);
   1185 	bset = isl_basic_set_add_constraint(bset, c);
   1186 
   1187 	bset = isl_basic_set_project_out(bset, isl_dim_set, 3, 1);
   1188 
   1189 	/* Test disabled for now */
   1190 	/*
   1191 	assert(bset && bset->n_div == 1);
   1192 	*/
   1193 	isl_local_space_free(ls);
   1194 	isl_basic_set_free(bset);
   1195 
   1196 	/* test 8 */
   1197 	space = isl_space_set_alloc(ctx, 0, 5);
   1198 	bset = isl_basic_set_universe(isl_space_copy(space));
   1199 	ls = isl_local_space_from_space(space);
   1200 
   1201 	c = isl_constraint_alloc_equality(isl_local_space_copy(ls));
   1202 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, -1);
   1203 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 1, -3);
   1204 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 3, -3);
   1205 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 4, 6);
   1206 	bset = isl_basic_set_add_constraint(bset, c);
   1207 
   1208 	c = isl_constraint_alloc_equality(isl_local_space_copy(ls));
   1209 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, -1);
   1210 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 2, 1);
   1211 	c = isl_constraint_set_constant_si(c, 1);
   1212 	bset = isl_basic_set_add_constraint(bset, c);
   1213 
   1214 	bset = isl_basic_set_project_out(bset, isl_dim_set, 4, 1);
   1215 
   1216 	/* Test disabled for now */
   1217 	/*
   1218 	assert(bset && bset->n_div == 1);
   1219 	*/
   1220 	isl_local_space_free(ls);
   1221 	isl_basic_set_free(bset);
   1222 
   1223 	/* test 9 */
   1224 	space = isl_space_set_alloc(ctx, 0, 4);
   1225 	bset = isl_basic_set_universe(isl_space_copy(space));
   1226 	ls = isl_local_space_from_space(space);
   1227 
   1228 	c = isl_constraint_alloc_equality(isl_local_space_copy(ls));
   1229 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, 1);
   1230 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 1, -1);
   1231 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 2, -2);
   1232 	bset = isl_basic_set_add_constraint(bset, c);
   1233 
   1234 	c = isl_constraint_alloc_equality(isl_local_space_copy(ls));
   1235 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, -1);
   1236 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 3, 3);
   1237 	c = isl_constraint_set_constant_si(c, 2);
   1238 	bset = isl_basic_set_add_constraint(bset, c);
   1239 
   1240 	bset = isl_basic_set_project_out(bset, isl_dim_set, 2, 2);
   1241 
   1242 	bset = isl_basic_set_fix_si(bset, isl_dim_set, 0, 2);
   1243 
   1244 	assert(!isl_basic_set_is_empty(bset));
   1245 
   1246 	isl_local_space_free(ls);
   1247 	isl_basic_set_free(bset);
   1248 
   1249 	/* test 10 */
   1250 	space = isl_space_set_alloc(ctx, 0, 3);
   1251 	bset = isl_basic_set_universe(isl_space_copy(space));
   1252 	ls = isl_local_space_from_space(space);
   1253 
   1254 	c = isl_constraint_alloc_equality(isl_local_space_copy(ls));
   1255 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, 1);
   1256 	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 2, -2);
   1257 	bset = isl_basic_set_add_constraint(bset, c);
   1258 
   1259 	bset = isl_basic_set_project_out(bset, isl_dim_set, 2, 1);
   1260 
   1261 	bset = isl_basic_set_fix_si(bset, isl_dim_set, 0, 2);
   1262 
   1263 	isl_local_space_free(ls);
   1264 	isl_basic_set_free(bset);
   1265 
   1266 	str = "{ [i] : exists (e0, e1: 3e1 >= 1 + 2e0 and "
   1267 	    "8e1 <= -1 + 5i - 5e0 and 2e1 >= 1 + 2i - 5e0) }";
   1268 	set = isl_set_read_from_str(ctx, str);
   1269 	set = isl_set_compute_divs(set);
   1270 	isl_set_free(set);
   1271 	if (!set)
   1272 		return -1;
   1273 
   1274 	if (test_elimination(ctx) < 0)
   1275 		return -1;
   1276 
   1277 	str = "{ [i,j,k] : 3 + i + 2j >= 0 and 2 * [(i+2j)/4] <= k }";
   1278 	set = isl_set_read_from_str(ctx, str);
   1279 	set = isl_set_remove_divs_involving_dims(set, isl_dim_set, 0, 2);
   1280 	set = isl_set_fix_si(set, isl_dim_set, 2, -3);
   1281 	empty = isl_set_is_empty(set);
   1282 	isl_set_free(set);
   1283 	if (empty < 0)
   1284 		return -1;
   1285 	if (!empty)
   1286 		isl_die(ctx, isl_error_unknown,
   1287 			"result not as accurate as expected", return -1);
   1288 
   1289 	return 0;
   1290 }
   1291 
   1292 void test_application_case(struct isl_ctx *ctx, const char *name)
   1293 {
   1294 	char *filename;
   1295 	FILE *input;
   1296 	struct isl_basic_set *bset1, *bset2;
   1297 	struct isl_basic_map *bmap;
   1298 
   1299 	filename = get_filename(ctx, name, "omega");
   1300 	assert(filename);
   1301 	input = fopen(filename, "r");
   1302 	assert(input);
   1303 
   1304 	bset1 = isl_basic_set_read_from_file(ctx, input);
   1305 	bmap = isl_basic_map_read_from_file(ctx, input);
   1306 
   1307 	bset1 = isl_basic_set_apply(bset1, bmap);
   1308 
   1309 	bset2 = isl_basic_set_read_from_file(ctx, input);
   1310 
   1311 	assert(isl_basic_set_is_equal(bset1, bset2) == 1);
   1312 
   1313 	isl_basic_set_free(bset1);
   1314 	isl_basic_set_free(bset2);
   1315 	free(filename);
   1316 
   1317 	fclose(input);
   1318 }
   1319 
   1320 static int test_application(isl_ctx *ctx)
   1321 {
   1322 	test_application_case(ctx, "application");
   1323 	test_application_case(ctx, "application2");
   1324 
   1325 	return 0;
   1326 }
   1327 
   1328 void test_affine_hull_case(struct isl_ctx *ctx, const char *name)
   1329 {
   1330 	char *filename;
   1331 	FILE *input;
   1332 	struct isl_basic_set *bset1, *bset2;
   1333 
   1334 	filename = get_filename(ctx, name, "polylib");
   1335 	assert(filename);
   1336 	input = fopen(filename, "r");
   1337 	assert(input);
   1338 
   1339 	bset1 = isl_basic_set_read_from_file(ctx, input);
   1340 	bset2 = isl_basic_set_read_from_file(ctx, input);
   1341 
   1342 	bset1 = isl_basic_set_affine_hull(bset1);
   1343 
   1344 	assert(isl_basic_set_is_equal(bset1, bset2) == 1);
   1345 
   1346 	isl_basic_set_free(bset1);
   1347 	isl_basic_set_free(bset2);
   1348 	free(filename);
   1349 
   1350 	fclose(input);
   1351 }
   1352 
   1353 /* Pairs of sets and the corresponding expected results of
   1354  * isl_basic_set_recession_cone.
   1355  */
   1356 struct {
   1357 	const char *set;
   1358 	const char *cone;
   1359 } recession_cone_tests[] = {
   1360 	{ "{ [i] : 0 <= i <= 10 }", "{ [0] }" },
   1361 	{ "{ [i] : 0 <= i }", "{ [i] : 0 <= i }" },
   1362 	{ "{ [i] : i <= 10 }", "{ [i] : i <= 0 }" },
   1363 	{ "{ [i] : false }", "{ [i] : false }" },
   1364 };
   1365 
   1366 /* Perform some basic isl_basic_set_recession_cone tests.
   1367  */
   1368 static int test_recession_cone(struct isl_ctx *ctx)
   1369 {
   1370 	int i;
   1371 
   1372 	for (i = 0; i < ARRAY_SIZE(recession_cone_tests); ++i) {
   1373 		const char *str;
   1374 		isl_basic_set *bset;
   1375 		isl_basic_set *cone, *expected;
   1376 		isl_bool equal;
   1377 
   1378 		str = recession_cone_tests[i].set;
   1379 		bset = isl_basic_set_read_from_str(ctx, str);
   1380 		str = recession_cone_tests[i].cone;
   1381 		expected = isl_basic_set_read_from_str(ctx, str);
   1382 		cone = isl_basic_set_recession_cone(bset);
   1383 		equal = isl_basic_set_is_equal(cone, expected);
   1384 		isl_basic_set_free(cone);
   1385 		isl_basic_set_free(expected);
   1386 		if (equal < 0)
   1387 			return -1;
   1388 		if (!equal)
   1389 			isl_die(ctx, isl_error_unknown, "unexpected cone",
   1390 				return -1);
   1391 	}
   1392 
   1393 	return 0;
   1394 }
   1395 
   1396 int test_affine_hull(struct isl_ctx *ctx)
   1397 {
   1398 	const char *str;
   1399 	isl_set *set;
   1400 	isl_basic_set *bset, *bset2;
   1401 	isl_size n;
   1402 	isl_bool subset;
   1403 
   1404 	test_affine_hull_case(ctx, "affine2");
   1405 	test_affine_hull_case(ctx, "affine");
   1406 	test_affine_hull_case(ctx, "affine3");
   1407 
   1408 	str = "[m] -> { [i0] : exists (e0, e1: e1 <= 1 + i0 and "
   1409 			"m >= 3 and 4i0 <= 2 + m and e1 >= i0 and "
   1410 			"e1 >= 0 and e1 <= 2 and e1 >= 1 + 2e0 and "
   1411 			"2e1 <= 1 + m + 4e0 and 2e1 >= 2 - m + 4i0 - 4e0) }";
   1412 	set = isl_set_read_from_str(ctx, str);
   1413 	bset = isl_set_affine_hull(set);
   1414 	n = isl_basic_set_dim(bset, isl_dim_div);
   1415 	isl_basic_set_free(bset);
   1416 	if (n < 0)
   1417 		return -1;
   1418 	if (n != 0)
   1419 		isl_die(ctx, isl_error_unknown, "not expecting any divs",
   1420 			return -1);
   1421 
   1422 	/* Check that isl_map_affine_hull is not confused by
   1423 	 * the reordering of divs in isl_map_align_divs.
   1424 	 */
   1425 	str = "{ [a, b, c, 0] : exists (e0 = [(b)/32], e1 = [(c)/32]: "
   1426 				"32e0 = b and 32e1 = c); "
   1427 		"[a, 0, c, 0] : exists (e0 = [(c)/32]: 32e0 = c) }";
   1428 	set = isl_set_read_from_str(ctx, str);
   1429 	bset = isl_set_affine_hull(set);
   1430 	isl_basic_set_free(bset);
   1431 	if (!bset)
   1432 		return -1;
   1433 
   1434 	str = "{ [a] : exists e0, e1, e2: 32e1 = 31 + 31a + 31e0 and "
   1435 			"32e2 = 31 + 31e0 }";
   1436 	set = isl_set_read_from_str(ctx, str);
   1437 	bset = isl_set_affine_hull(set);
   1438 	str = "{ [a] : exists e : a = 32 e }";
   1439 	bset2 = isl_basic_set_read_from_str(ctx, str);
   1440 	subset = isl_basic_set_is_subset(bset, bset2);
   1441 	isl_basic_set_free(bset);
   1442 	isl_basic_set_free(bset2);
   1443 	if (subset < 0)
   1444 		return -1;
   1445 	if (!subset)
   1446 		isl_die(ctx, isl_error_unknown, "not as accurate as expected",
   1447 			return -1);
   1448 
   1449 	return 0;
   1450 }
   1451 
   1452 /* Test a special case of isl_set_plain_unshifted_simple_hull
   1453  * where older versions of isl would include a redundant constraint
   1454  * in the result.
   1455  * Check that the result does not have any constraints.
   1456  */
   1457 static isl_stat test_plain_unshifted_simple_hull_special(isl_ctx *ctx)
   1458 {
   1459 	const char *str;
   1460 	isl_bool is_universe;
   1461 	isl_set *set;
   1462 	isl_basic_set *bset;
   1463 
   1464 	str = "{[x, y] : x = 0 or 2*((x+y)//2) <= y + 2 }";
   1465 	set = isl_set_read_from_str(ctx, str);
   1466 	bset = isl_set_plain_unshifted_simple_hull(set);
   1467 	is_universe = isl_basic_set_plain_is_universe(bset);
   1468 	isl_basic_set_free(bset);
   1469 
   1470 	if (is_universe < 0)
   1471 		return isl_stat_error;
   1472 	if (!is_universe)
   1473 		isl_die(ctx, isl_error_unknown,
   1474 			"hull should not have any constraints",
   1475 			return isl_stat_error);
   1476 
   1477 	return isl_stat_ok;
   1478 }
   1479 
   1480 /* Inputs for simple hull tests, consisting of
   1481  * the specific simple hull function, the input set and the expected result.
   1482  */
   1483 struct {
   1484 	__isl_give isl_basic_set *(*fn)(__isl_take isl_set *set);
   1485 	const char *set;
   1486 	const char *hull;
   1487 } simple_hull_tests[] = {
   1488 	{ &isl_set_plain_unshifted_simple_hull,
   1489 	  "{ [i,j] : i >= 1 and j >= 1 or i >= 2 and j <= 10 }",
   1490 	  "{ [i,j] : i >= 1 }" },
   1491 	{ &isl_set_plain_unshifted_simple_hull,
   1492 	  "{ [n,i,j,k] : (i mod 3 = 2 and j mod 4 = 2) or "
   1493 		"(j mod 4 = 2 and k mod 6 = n) }",
   1494 	  "{ [n,i,j,k] : j mod 4 = 2 }" },
   1495 	{ &isl_set_unshifted_simple_hull,
   1496 	  "{ [0,x,y] : x <= -1; [1,x,y] : x <= y <= -x; [2,x,y] : x <= 1 }",
   1497 	  "{ [t,x,y] : 0 <= t <= 2 and x <= 1 }" },
   1498 	{ &isl_set_simple_hull,
   1499 	  "{ [a, b] : b <= 0 and "
   1500 			"2*floor((-2*floor((b)/2))/5) >= a - floor((b)/2); "
   1501 	    "[a, b] : a mod 2 = 0 }",
   1502 	  "{ [a, b] }" },
   1503 };
   1504 
   1505 /* Basic tests for various simple hull functions.
   1506  */
   1507 static int test_various_simple_hull(isl_ctx *ctx)
   1508 {
   1509 	int i;
   1510 	isl_set *set;
   1511 	isl_basic_set *hull, *expected;
   1512 	isl_bool equal;
   1513 
   1514 	for (i = 0; i < ARRAY_SIZE(simple_hull_tests); ++i) {
   1515 		const char *str;
   1516 		str = simple_hull_tests[i].set;
   1517 		set = isl_set_read_from_str(ctx, str);
   1518 		str = simple_hull_tests[i].hull;
   1519 		expected = isl_basic_set_read_from_str(ctx, str);
   1520 		hull = simple_hull_tests[i].fn(set);
   1521 		equal = isl_basic_set_is_equal(hull, expected);
   1522 		isl_basic_set_free(hull);
   1523 		isl_basic_set_free(expected);
   1524 		if (equal < 0)
   1525 			return -1;
   1526 		if (!equal)
   1527 			isl_die(ctx, isl_error_unknown, "unexpected hull",
   1528 				return -1);
   1529 	}
   1530 
   1531 	return 0;
   1532 }
   1533 
   1534 static int test_simple_hull(struct isl_ctx *ctx)
   1535 {
   1536 	const char *str;
   1537 	isl_set *set;
   1538 	isl_basic_set *bset;
   1539 	isl_bool is_empty;
   1540 
   1541 	str = "{ [x, y] : 3y <= 2x and y >= -2 + 2x and 2y >= 2 - x;"
   1542 		"[y, x] : 3y <= 2x and y >= -2 + 2x and 2y >= 2 - x }";
   1543 	set = isl_set_read_from_str(ctx, str);
   1544 	bset = isl_set_simple_hull(set);
   1545 	is_empty = isl_basic_set_is_empty(bset);
   1546 	isl_basic_set_free(bset);
   1547 
   1548 	if (is_empty == isl_bool_error)
   1549 		return -1;
   1550 
   1551 	if (is_empty == isl_bool_false)
   1552 		isl_die(ctx, isl_error_unknown, "Empty set should be detected",
   1553 			return -1);
   1554 
   1555 	if (test_plain_unshifted_simple_hull_special(ctx) < 0)
   1556 		return -1;
   1557 	if (test_various_simple_hull(ctx) < 0)
   1558 		return -1;
   1559 
   1560 	return 0;
   1561 }
   1562 
   1563 /* Inputs for isl_set_get_simple_fixed_box_hull tests.
   1564  * "set" is the input set.
   1565  * "offset" is the expected box offset.
   1566  * "size" is the expected box size.
   1567  */
   1568 static struct {
   1569 	const char *set;
   1570 	const char *offset;
   1571 	const char *size;
   1572 } box_hull_tests[] = {
   1573 	{ "{ S[x, y] : 0 <= x, y < 10 }", "{ S[0, 0] }", "{ S[10, 10] }" },
   1574 	{ "[N] -> { S[x, y] : N <= x, y < N + 10 }",
   1575 	  "[N] -> { S[N, N] }", "{ S[10, 10] }" },
   1576 	{ "{ S[x, y] : 0 <= x + y, x - y < 10 }",
   1577 	  "{ S[0, -4] }", "{ S[10, 9] }" },
   1578 	{ "{ [i=0:10] : exists (e0, e1: 3e1 >= 1 + 2e0 and "
   1579 	    "8e1 <= -1 + 5i - 5e0 and 2e1 >= 1 + 2i - 5e0) }",
   1580 	  "{ [3] }", "{ [8] }" },
   1581 	{ "[N] -> { [w = 0:17] : exists (e0: w < 2N and "
   1582 	    "-1 + w <= e0 <= w and 2e0 >= N + w and w <= 2e0 <= 15 + w) }",
   1583 	  "[N] -> { [N] }", "{ [9] }" },
   1584 };
   1585 
   1586 /* Perform basic isl_set_get_simple_fixed_box_hull tests.
   1587  */
   1588 static int test_box_hull(struct isl_ctx *ctx)
   1589 {
   1590 	int i;
   1591 
   1592 	for (i = 0; i < ARRAY_SIZE(box_hull_tests); ++i) {
   1593 		const char *str;
   1594 		isl_stat r;
   1595 		isl_set *set;
   1596 		isl_multi_aff *offset;
   1597 		isl_multi_val *size;
   1598 		isl_fixed_box *box;
   1599 
   1600 		set = isl_set_read_from_str(ctx, box_hull_tests[i].set);
   1601 		box = isl_set_get_simple_fixed_box_hull(set);
   1602 		offset = isl_fixed_box_get_offset(box);
   1603 		size = isl_fixed_box_get_size(box);
   1604 		str = box_hull_tests[i].offset;
   1605 		r = multi_aff_check_plain_equal(offset, str);
   1606 		str = box_hull_tests[i].size;
   1607 		if (r >= 0)
   1608 			r = multi_val_check_plain_equal(size, str);
   1609 		isl_multi_aff_free(offset);
   1610 		isl_multi_val_free(size);
   1611 		isl_fixed_box_free(box);
   1612 		isl_set_free(set);
   1613 		if (r < 0)
   1614 			return -1;
   1615 	}
   1616 
   1617 	return 0;
   1618 }
   1619 
   1620 void test_convex_hull_case(struct isl_ctx *ctx, const char *name)
   1621 {
   1622 	char *filename;
   1623 	FILE *input;
   1624 	struct isl_basic_set *bset1, *bset2;
   1625 	struct isl_set *set;
   1626 
   1627 	filename = get_filename(ctx, name, "polylib");
   1628 	assert(filename);
   1629 	input = fopen(filename, "r");
   1630 	assert(input);
   1631 
   1632 	bset1 = isl_basic_set_read_from_file(ctx, input);
   1633 	bset2 = isl_basic_set_read_from_file(ctx, input);
   1634 
   1635 	set = isl_basic_set_union(bset1, bset2);
   1636 	bset1 = isl_set_convex_hull(set);
   1637 
   1638 	bset2 = isl_basic_set_read_from_file(ctx, input);
   1639 
   1640 	assert(isl_basic_set_is_equal(bset1, bset2) == 1);
   1641 
   1642 	isl_basic_set_free(bset1);
   1643 	isl_basic_set_free(bset2);
   1644 	free(filename);
   1645 
   1646 	fclose(input);
   1647 }
   1648 
   1649 struct {
   1650 	const char *set;
   1651 	const char *hull;
   1652 } convex_hull_tests[] = {
   1653 	{ "{ [i0, i1, i2] : (i2 = 1 and i0 = 0 and i1 >= 0) or "
   1654 	       "(i0 = 1 and i1 = 0 and i2 = 1) or "
   1655 	       "(i0 = 0 and i1 = 0 and i2 = 0) }",
   1656 	  "{ [i0, i1, i2] : i0 >= 0 and i2 >= i0 and i2 <= 1 and i1 >= 0 }" },
   1657 	{ "[n] -> { [i0, i1, i0] : i0 <= -4 + n; "
   1658 	    "[i0, i0, i2] : n = 6 and i0 >= 0 and i2 <= 7 - i0 and "
   1659 	    "i2 <= 5 and i2 >= 4; "
   1660 	    "[3, i1, 3] : n = 5 and i1 <= 2 and i1 >= 0 }",
   1661 	  "[n] -> { [i0, i1, i2] : i2 <= -1 + n and 2i2 <= -6 + 3n - i0 and "
   1662 	    "i2 <= 5 + i0 and i2 >= i0 }" },
   1663 	{ "{ [x, y] : 3y <= 2x and y >= -2 + 2x and 2y >= 2 - x }",
   1664 	    "{ [x, y] : 1 = 0 }" },
   1665 	{ "{ [x, y, z] : 0 <= x, y, z <= 10; [x, y, 0] : x >= 0 and y > 0; "
   1666 	    "[x, y, 0] : x >= 0 and y < 0 }",
   1667 	    "{ [x, y, z] : x >= 0 and 0 <= z <= 10 }" },
   1668 	{ "{ [a, b, c] : a <= 1 and -a < b <= 1 and 0 <= c <= 2 - a - b and "
   1669 			    "c <= a; "
   1670 	    "[0, 2, 0]; [3, 1, 0] }",
   1671 	    "{ [a, b, c] : b > -a and 2b >= -1 + a and 0 <= c <= a and "
   1672 			    "5c <= 6 - a - 3b }" },
   1673 };
   1674 
   1675 static int test_convex_hull_algo(isl_ctx *ctx, int convex)
   1676 {
   1677 	int i;
   1678 	int orig_convex = ctx->opt->convex;
   1679 	ctx->opt->convex = convex;
   1680 
   1681 	test_convex_hull_case(ctx, "convex0");
   1682 	test_convex_hull_case(ctx, "convex1");
   1683 	test_convex_hull_case(ctx, "convex2");
   1684 	test_convex_hull_case(ctx, "convex3");
   1685 	test_convex_hull_case(ctx, "convex4");
   1686 	test_convex_hull_case(ctx, "convex5");
   1687 	test_convex_hull_case(ctx, "convex6");
   1688 	test_convex_hull_case(ctx, "convex7");
   1689 	test_convex_hull_case(ctx, "convex8");
   1690 	test_convex_hull_case(ctx, "convex9");
   1691 	test_convex_hull_case(ctx, "convex10");
   1692 	test_convex_hull_case(ctx, "convex11");
   1693 	test_convex_hull_case(ctx, "convex12");
   1694 	test_convex_hull_case(ctx, "convex13");
   1695 	test_convex_hull_case(ctx, "convex14");
   1696 	test_convex_hull_case(ctx, "convex15");
   1697 
   1698 	for (i = 0; i < ARRAY_SIZE(convex_hull_tests); ++i) {
   1699 		isl_set *set1, *set2;
   1700 		int equal;
   1701 
   1702 		set1 = isl_set_read_from_str(ctx, convex_hull_tests[i].set);
   1703 		set2 = isl_set_read_from_str(ctx, convex_hull_tests[i].hull);
   1704 		set1 = isl_set_from_basic_set(isl_set_convex_hull(set1));
   1705 		equal = isl_set_is_equal(set1, set2);
   1706 		isl_set_free(set1);
   1707 		isl_set_free(set2);
   1708 
   1709 		if (equal < 0)
   1710 			return -1;
   1711 		if (!equal)
   1712 			isl_die(ctx, isl_error_unknown,
   1713 				"unexpected convex hull", return -1);
   1714 	}
   1715 
   1716 	ctx->opt->convex = orig_convex;
   1717 
   1718 	return 0;
   1719 }
   1720 
   1721 static int test_convex_hull(isl_ctx *ctx)
   1722 {
   1723 	if (test_convex_hull_algo(ctx, ISL_CONVEX_HULL_FM) < 0)
   1724 		return -1;
   1725 	if (test_convex_hull_algo(ctx, ISL_CONVEX_HULL_WRAP) < 0)
   1726 		return -1;
   1727 	return 0;
   1728 }
   1729 
   1730 /* Check that computing the gist of "map" with respect to "context"
   1731  * does not make any copy of "map" get marked empty.
   1732  * Earlier versions of isl would end up doing that.
   1733  */
   1734 static isl_stat test_gist_empty_pair(isl_ctx *ctx, const char *map,
   1735 	const char *context)
   1736 {
   1737 	isl_map *m1, *m2, *m3;
   1738 	isl_bool empty_before, empty_after;
   1739 
   1740 	m1 = isl_map_read_from_str(ctx, map);
   1741 	m2 = isl_map_read_from_str(ctx, context);
   1742 	m3 = isl_map_copy(m1);
   1743 	empty_before = isl_map_is_empty(m3);
   1744 	m1 = isl_map_gist(m1, m2);
   1745 	empty_after = isl_map_is_empty(m3);
   1746 	isl_map_free(m1);
   1747 	isl_map_free(m3);
   1748 
   1749 	if (empty_before < 0 || empty_after < 0)
   1750 		return isl_stat_error;
   1751 	if (empty_before)
   1752 		isl_die(ctx, isl_error_unknown, "map should not be empty",
   1753 			return isl_stat_error);
   1754 	if (empty_after)
   1755 		isl_die(ctx, isl_error_unknown, "map should still not be empty",
   1756 			return isl_stat_error);
   1757 
   1758 	return isl_stat_ok;
   1759 }
   1760 
   1761 /* Check that computing a gist does not make any copy of the input
   1762  * get marked empty.
   1763  * Earlier versions of isl would end up doing that on some pairs of inputs.
   1764  */
   1765 static isl_stat test_gist_empty(isl_ctx *ctx)
   1766 {
   1767 	const char *map, *context;
   1768 
   1769 	map = "{ [] -> [a, b, c] : 2b = 1 + a }";
   1770 	context = "{ [] -> [a, b, c] : 2c = 2 + a }";
   1771 	if (test_gist_empty_pair(ctx, map, context) < 0)
   1772 		return isl_stat_error;
   1773 	map = "{ [] -> [0, 0] }";
   1774 	context = "{ [] -> [a, b] : a > b }";
   1775 	if (test_gist_empty_pair(ctx, map, context) < 0)
   1776 		return isl_stat_error;
   1777 
   1778 	return isl_stat_ok;
   1779 }
   1780 
   1781 /* Inputs to isl_map_plain_gist_basic_map, along with the expected output.
   1782  */
   1783 struct {
   1784 	const char *map;
   1785 	const char *context;
   1786 	const char *gist;
   1787 } plain_gist_tests[] = {
   1788 	{ "{ [i] -> [j] : i >= 1 and j >= 1 or i >= 2 and j <= 10 }",
   1789 	  "{ [i] -> [j] : i >= 1 }",
   1790 	  "{ [i] -> [j] : j >= 1 or i >= 2 and j <= 10 }" },
   1791 	{ "{ [n] -> [i,j,k] : (i mod 3 = 2 and j mod 4 = 2) or "
   1792 		"(j mod 4 = 2 and k mod 6 = n) }",
   1793 	  "{ [n] -> [i,j,k] : j mod 4 = 2 }",
   1794 	  "{ [n] -> [i,j,k] : (i mod 3 = 2) or (k mod 6 = n) }" },
   1795 	{ "{ [i] -> [j] : i > j and (exists a,b : i <= 2a + 5b <= 2) }",
   1796 	  "{ [i] -> [j] : i > j }",
   1797 	  "{ [i] -> [j] : exists a,b : i <= 2a + 5b <= 2 }" },
   1798 };
   1799 
   1800 /* Basic tests for isl_map_plain_gist_basic_map.
   1801  */
   1802 static int test_plain_gist(isl_ctx *ctx)
   1803 {
   1804 	int i;
   1805 
   1806 	for (i = 0; i < ARRAY_SIZE(plain_gist_tests); ++i) {
   1807 		const char *str;
   1808 		int equal;
   1809 		isl_map *map, *gist;
   1810 		isl_basic_map *context;
   1811 
   1812 		map = isl_map_read_from_str(ctx, plain_gist_tests[i].map);
   1813 		str = plain_gist_tests[i].context;
   1814 		context = isl_basic_map_read_from_str(ctx, str);
   1815 		map = isl_map_plain_gist_basic_map(map, context);
   1816 		gist = isl_map_read_from_str(ctx, plain_gist_tests[i].gist);
   1817 		equal = isl_map_is_equal(map, gist);
   1818 		isl_map_free(map);
   1819 		isl_map_free(gist);
   1820 		if (equal < 0)
   1821 			return -1;
   1822 		if (!equal)
   1823 			isl_die(ctx, isl_error_unknown,
   1824 				"incorrect gist result", return -1);
   1825 	}
   1826 
   1827 	return 0;
   1828 }
   1829 
   1830 /* Inputs for isl_basic_set_gist tests that are expected to fail.
   1831  */
   1832 struct {
   1833 	const char *set;
   1834 	const char *context;
   1835 } gist_fail_tests[] = {
   1836 	{ "{ [i] : exists (e0, e1: 3e1 >= 1 + 2e0 and "
   1837 	    "8e1 <= -1 + 5i - 5e0 and 2e1 >= 1 + 2i - 5e0) }",
   1838 	  "{ [i] : i >= 0 }" },
   1839 };
   1840 
   1841 /* Check that isl_basic_set_gist fails (gracefully) when expected.
   1842  * In particular, the user should be able to recover from the failure.
   1843  */
   1844 static isl_stat test_gist_fail(struct isl_ctx *ctx)
   1845 {
   1846 	int i, n;
   1847 	int on_error;
   1848 
   1849 	on_error = isl_options_get_on_error(ctx);
   1850 	isl_options_set_on_error(ctx, ISL_ON_ERROR_CONTINUE);
   1851 	n = ARRAY_SIZE(gist_fail_tests);
   1852 	for (i = 0; i < n; ++i) {
   1853 		const char *str;
   1854 		isl_basic_set *bset, *context;
   1855 
   1856 		bset = isl_basic_set_read_from_str(ctx, gist_fail_tests[i].set);
   1857 		str = gist_fail_tests[i].context;
   1858 		context = isl_basic_set_read_from_str(ctx, str);
   1859 		bset = isl_basic_set_gist(bset, context);
   1860 		isl_basic_set_free(bset);
   1861 		if (bset)
   1862 			break;
   1863 	}
   1864 	isl_options_set_on_error(ctx, on_error);
   1865 	if (i < n)
   1866 		isl_die(ctx, isl_error_unknown,
   1867 			"operation not expected to succeed",
   1868 			return isl_stat_error);
   1869 
   1870 	return isl_stat_ok;
   1871 }
   1872 
   1873 struct {
   1874 	const char *set;
   1875 	const char *context;
   1876 	const char *gist;
   1877 } gist_tests[] = {
   1878 	{ "{ [1, -1, 3] }",
   1879 	  "{ [1, b, 2 - b] : -1 <= b <= 2 }",
   1880 	  "{ [a, -1, c] }" },
   1881 	{ "{ [a, b, c] : a <= 15 and a >= 1 }",
   1882 	  "{ [a, b, c] : exists (e0 = floor((-1 + a)/16): a >= 1 and "
   1883 			"c <= 30 and 32e0 >= -62 + 2a + 2b - c and b >= 0) }",
   1884 	  "{ [a, b, c] : a <= 15 }" },
   1885 	{ "{ : }", "{ : 1 = 0 }", "{ : }" },
   1886 	{ "{ : 1 = 0 }", "{ : 1 = 0 }", "{ : }" },
   1887 	{ "[M] -> { [x] : exists (e0 = floor((-2 + x)/3): 3e0 = -2 + x) }",
   1888 	  "[M] -> { [3M] }" , "[M] -> { [x] : 1 = 0 }" },
   1889 	{ "{ [m, n, a, b] : a <= 2147 + n }",
   1890 	  "{ [m, n, a, b] : (m >= 1 and n >= 1 and a <= 2148 - m and "
   1891 			"b <= 2148 - n and b >= 0 and b >= 2149 - n - a) or "
   1892 			"(n >= 1 and a >= 0 and b <= 2148 - n - a and "
   1893 			"b >= 0) }",
   1894 	  "{ [m, n, ku, kl] }" },
   1895 	{ "{ [a, a, b] : a >= 10 }",
   1896 	  "{ [a, b, c] : c >= a and c <= b and c >= 2 }",
   1897 	  "{ [a, a, b] : a >= 10 }" },
   1898 	{ "{ [i, j] : i >= 0 and i + j >= 0 }", "{ [i, j] : i <= 0 }",
   1899 	  "{ [0, j] : j >= 0 }" },
   1900 	/* Check that no constraints on i6 are introduced in the gist */
   1901 	{ "[t1] -> { [i4, i6] : exists (e0 = floor((1530 - 4t1 - 5i4)/20): "
   1902 		"20e0 <= 1530 - 4t1 - 5i4 and 20e0 >= 1511 - 4t1 - 5i4 and "
   1903 		"5e0 <= 381 - t1 and i4 <= 1) }",
   1904 	  "[t1] -> { [i4, i6] : exists (e0 = floor((-t1 + i6)/5): "
   1905 		"5e0 = -t1 + i6 and i6 <= 6 and i6 >= 3) }",
   1906 	  "[t1] -> { [i4, i6] : exists (e0 = floor((1530 - 4t1 - 5i4)/20): "
   1907 		"i4 <= 1 and 5e0 <= 381 - t1 and 20e0 <= 1530 - 4t1 - 5i4 and "
   1908 		"20e0 >= 1511 - 4t1 - 5i4) }" },
   1909 	/* Check that no constraints on i6 are introduced in the gist */
   1910 	{ "[t1, t2] -> { [i4, i5, i6] : exists (e0 = floor((1 + i4)/2), "
   1911 		"e1 = floor((1530 - 4t1 - 5i4)/20), "
   1912 		"e2 = floor((-4t1 - 5i4 + 10*floor((1 + i4)/2))/20), "
   1913 		"e3 = floor((-1 + i4)/2): t2 = 0 and 2e3 = -1 + i4 and "
   1914 			"20e2 >= -19 - 4t1 - 5i4 + 10e0 and 5e2 <= 1 - t1 and "
   1915 			"2e0 <= 1 + i4 and 2e0 >= i4 and "
   1916 			"20e1 <= 1530 - 4t1 - 5i4 and "
   1917 			"20e1 >= 1511 - 4t1 - 5i4 and i4 <= 1 and "
   1918 			"5e1 <= 381 - t1 and 20e2 <= -4t1 - 5i4 + 10e0) }",
   1919 	  "[t1, t2] -> { [i4, i5, i6] : exists (e0 = floor((-17 + i4)/2), "
   1920 		"e1 = floor((-t1 + i6)/5): 5e1 = -t1 + i6 and "
   1921 			"2e0 <= -17 + i4 and 2e0 >= -18 + i4 and "
   1922 			"10e0 <= -91 + 5i4 + 4i6 and "
   1923 			"10e0 >= -105 + 5i4 + 4i6) }",
   1924 	  "[t1, t2] -> { [i4, i5, i6] : exists (e0 = floor((381 - t1)/5), "
   1925 		"e1 = floor((-1 + i4)/2): t2 = 0 and 2e1 = -1 + i4 and "
   1926 		"i4 <= 1 and 5e0 <= 381 - t1 and 20e0 >= 1511 - 4t1 - 5i4) }" },
   1927 	{ "{ [0, 0, q, p] : -5 <= q <= 5 and p >= 0 }",
   1928 	  "{ [a, b, q, p] : b >= 1 + a }",
   1929 	  "{ [a, b, q, p] : false }" },
   1930 	{ "[n] -> { [x] : x = n && x mod 32 = 0 }",
   1931 	  "[n] -> { [x] : x mod 32 = 0 }",
   1932 	  "[n] -> { [x = n] }" },
   1933 	{ "{ [x] : x mod 6 = 0 }", "{ [x] : x mod 3 = 0 }",
   1934 	  "{ [x] : x mod 2 = 0 }" },
   1935 	{ "{ [x] : x mod 3200 = 0 }", "{ [x] : x mod 10000 = 0 }",
   1936 	  "{ [x] : x mod 128 = 0 }" },
   1937 	{ "{ [x] : x mod 3200 = 0 }", "{ [x] : x mod 10 = 0 }",
   1938 	  "{ [x] : x mod 3200 = 0 }" },
   1939 	{ "{ [a, b, c] : a mod 2 = 0 and a = c }",
   1940 	  "{ [a, b, c] : b mod 2 = 0 and b = c }",
   1941 	  "{ [a, b, c = a] }" },
   1942 	{ "{ [a, b, c] : a mod 6 = 0 and a = c }",
   1943 	  "{ [a, b, c] : b mod 2 = 0 and b = c }",
   1944 	  "{ [a, b, c = a] : a mod 3 = 0 }" },
   1945 	{ "{ [x] : 0 <= x <= 4 or 6 <= x <= 9 }",
   1946 	  "{ [x] : 1 <= x <= 3 or 7 <= x <= 8 }",
   1947 	  "{ [x] }" },
   1948 	{ "{ [x,y] : x < 0 and 0 <= y <= 4 or x >= -2 and -x <= y <= 10 + x }",
   1949 	  "{ [x,y] : 1 <= y <= 3 }",
   1950 	  "{ [x,y] }" },
   1951 };
   1952 
   1953 /* Check that isl_set_gist behaves as expected.
   1954  *
   1955  * For the test cases in gist_tests, besides checking that the result
   1956  * is as expected, also check that applying the gist operation does
   1957  * not modify the input set (an earlier version of isl would do that) and
   1958  * that the test case is consistent, i.e., that the gist has the same
   1959  * intersection with the context as the input set.
   1960  */
   1961 static int test_gist(struct isl_ctx *ctx)
   1962 {
   1963 	int i;
   1964 	const char *str;
   1965 	isl_basic_set *bset1, *bset2;
   1966 	isl_map *map1, *map2;
   1967 	isl_bool equal;
   1968 	isl_size n_div;
   1969 
   1970 	for (i = 0; i < ARRAY_SIZE(gist_tests); ++i) {
   1971 		isl_bool equal_input, equal_intersection;
   1972 		isl_set *set1, *set2, *copy, *context;
   1973 
   1974 		set1 = isl_set_read_from_str(ctx, gist_tests[i].set);
   1975 		context = isl_set_read_from_str(ctx, gist_tests[i].context);
   1976 		copy = isl_set_copy(set1);
   1977 		set1 = isl_set_gist(set1, isl_set_copy(context));
   1978 		set2 = isl_set_read_from_str(ctx, gist_tests[i].gist);
   1979 		equal = isl_set_is_equal(set1, set2);
   1980 		isl_set_free(set1);
   1981 		set1 = isl_set_read_from_str(ctx, gist_tests[i].set);
   1982 		equal_input = isl_set_is_equal(set1, copy);
   1983 		isl_set_free(copy);
   1984 		set1 = isl_set_intersect(set1, isl_set_copy(context));
   1985 		set2 = isl_set_intersect(set2, context);
   1986 		equal_intersection = isl_set_is_equal(set1, set2);
   1987 		isl_set_free(set2);
   1988 		isl_set_free(set1);
   1989 		if (equal < 0 || equal_input < 0 || equal_intersection < 0)
   1990 			return -1;
   1991 		if (!equal)
   1992 			isl_die(ctx, isl_error_unknown,
   1993 				"incorrect gist result", return -1);
   1994 		if (!equal_input)
   1995 			isl_die(ctx, isl_error_unknown,
   1996 				"gist modified input", return -1);
   1997 		if (!equal_input)
   1998 			isl_die(ctx, isl_error_unknown,
   1999 				"inconsistent gist test case", return -1);
   2000 	}
   2001 
   2002 	if (test_gist_fail(ctx) < 0)
   2003 		return -1;
   2004 
   2005 	str = "[p0, p2, p3, p5, p6, p10] -> { [] : "
   2006 	    "exists (e0 = [(15 + p0 + 15p6 + 15p10)/16], e1 = [(p5)/8], "
   2007 	    "e2 = [(p6)/128], e3 = [(8p2 - p5)/128], "
   2008 	    "e4 = [(128p3 - p6)/4096]: 8e1 = p5 and 128e2 = p6 and "
   2009 	    "128e3 = 8p2 - p5 and 4096e4 = 128p3 - p6 and p2 >= 0 and "
   2010 	    "16e0 >= 16 + 16p6 + 15p10 and  p2 <= 15 and p3 >= 0 and "
   2011 	    "p3 <= 31 and  p6 >= 128p3 and p5 >= 8p2 and p10 >= 0 and "
   2012 	    "16e0 <= 15 + p0 + 15p6 + 15p10 and 16e0 >= p0 + 15p6 + 15p10 and "
   2013 	    "p10 <= 15 and p10 <= -1 + p0 - p6) }";
   2014 	bset1 = isl_basic_set_read_from_str(ctx, str);
   2015 	str = "[p0, p2, p3, p5, p6, p10] -> { [] : exists (e0 = [(p5)/8], "
   2016 	    "e1 = [(p6)/128], e2 = [(8p2 - p5)/128], "
   2017 	    "e3 = [(128p3 - p6)/4096]: 8e0 = p5 and 128e1 = p6 and "
   2018 	    "128e2 = 8p2 - p5 and 4096e3 = 128p3 - p6 and p5 >= -7 and "
   2019 	    "p2 >= 0 and 8p2 <= -1 + p0 and p2 <= 15 and p3 >= 0 and "
   2020 	    "p3 <= 31 and 128p3 <= -1 + p0 and p6 >= -127 and "
   2021 	    "p5 <= -1 + p0 and p6 <= -1 + p0 and p6 >= 128p3 and "
   2022 	    "p0 >= 1 and p5 >= 8p2 and p10 >= 0 and p10 <= 15 ) }";
   2023 	bset2 = isl_basic_set_read_from_str(ctx, str);
   2024 	bset1 = isl_basic_set_gist(bset1, bset2);
   2025 	assert(bset1 && bset1->n_div == 0);
   2026 	isl_basic_set_free(bset1);
   2027 
   2028 	/* Check that the integer divisions of the second disjunct
   2029 	 * do not spread to the first disjunct.
   2030 	 */
   2031 	str = "[t1] -> { S_0[] -> A[o0] : (exists (e0 = [(-t1 + o0)/16]: "
   2032 		"16e0 = -t1 + o0 and o0 >= 0 and o0 <= 15 and t1 >= 0)) or "
   2033 		"(exists (e0 = [(-1 + t1)/16], "
   2034 			"e1 = [(-16 + t1 - 16e0)/4294967296]: "
   2035 			"4294967296e1 = -16 + t1 - o0 - 16e0 and "
   2036 			"16e0 <= -1 + t1 and 16e0 >= -16 + t1 and o0 >= 0 and "
   2037 			"o0 <= 4294967295 and t1 <= -1)) }";
   2038 	map1 = isl_map_read_from_str(ctx, str);
   2039 	str = "[t1] -> { S_0[] -> A[o0] : t1 >= 0 and t1 <= 4294967295 }";
   2040 	map2 = isl_map_read_from_str(ctx, str);
   2041 	map1 = isl_map_gist(map1, map2);
   2042 	if (!map1)
   2043 		return -1;
   2044 	if (map1->n != 1)
   2045 		isl_die(ctx, isl_error_unknown, "expecting single disjunct",
   2046 			isl_map_free(map1); return -1);
   2047 	n_div = isl_basic_map_dim(map1->p[0], isl_dim_div);
   2048 	isl_map_free(map1);
   2049 	if (n_div < 0)
   2050 		return -1;
   2051 	if (n_div != 1)
   2052 		isl_die(ctx, isl_error_unknown, "expecting single div",
   2053 			return -1);
   2054 
   2055 	if (test_gist_empty(ctx) < 0)
   2056 		return -1;
   2057 	if (test_plain_gist(ctx) < 0)
   2058 		return -1;
   2059 
   2060 	return 0;
   2061 }
   2062 
   2063 int test_coalesce_set(isl_ctx *ctx, const char *str, int check_one)
   2064 {
   2065 	isl_set *set, *set2;
   2066 	int equal;
   2067 	int one;
   2068 
   2069 	set = isl_set_read_from_str(ctx, str);
   2070 	set = isl_set_coalesce(set);
   2071 	set2 = isl_set_read_from_str(ctx, str);
   2072 	equal = isl_set_is_equal(set, set2);
   2073 	one = set && set->n == 1;
   2074 	isl_set_free(set);
   2075 	isl_set_free(set2);
   2076 
   2077 	if (equal < 0)
   2078 		return -1;
   2079 	if (!equal)
   2080 		isl_die(ctx, isl_error_unknown,
   2081 			"coalesced set not equal to input", return -1);
   2082 	if (check_one && !one)
   2083 		isl_die(ctx, isl_error_unknown,
   2084 			"coalesced set should not be a union", return -1);
   2085 
   2086 	return 0;
   2087 }
   2088 
   2089 /* Inputs for coalescing tests with unbounded wrapping.
   2090  * "str" is a string representation of the input set.
   2091  * "single_disjunct" is set if we expect the result to consist of
   2092  *	a single disjunct.
   2093  */
   2094 struct {
   2095 	int single_disjunct;
   2096 	const char *str;
   2097 } coalesce_unbounded_tests[] = {
   2098 	{ 1, "{ [x,y,z] : y + 2 >= 0 and x - y + 1 >= 0 and "
   2099 			"-x - y + 1 >= 0 and -3 <= z <= 3;"
   2100 		"[x,y,z] : -x+z + 20 >= 0 and -x-z + 20 >= 0 and "
   2101 			"x-z + 20 >= 0 and x+z + 20 >= 0 and "
   2102 			"-10 <= y <= 0}" },
   2103 	{ 1, "{ [x,y] : 0 <= x,y <= 10; [5,y]: 4 <= y <= 11 }" },
   2104 	{ 1, "{ [x,0,0] : -5 <= x <= 5; [0,y,1] : -5 <= y <= 5 }" },
   2105 	{ 1, "{ [x,y] : 0 <= x <= 10 and 0 >= y >= -1 and x+y >= 0; [0,1] }" },
   2106 	{ 1, "{ [x,y] : (0 <= x,y <= 4) or (2 <= x,y <= 5 and x + y <= 9) }" },
   2107 	{ 0, "{ [x, y, z] : 0 <= x,y,z <= 100 and 0 < z <= 2 + 2x + 2y; "
   2108 		"[x, y, 0] : x,y <= 100 and y <= 9 + 11x and x <= 9 + 11y }" },
   2109 	{ 1, "{ [0:1, 0:1]; [0, 2:3] }" },
   2110 	{ 1, "{ [0:1, 0:1]; [0, 2:3]; [1, -2:-1] }" },
   2111 	{ 1, "{ [0:3, 0:1]; [1:2, 2:5] }" },
   2112 	{ 1, "{ [0:3, 0:1]; [0:2, 2:5] }" },
   2113 	{ 1, "{ [0:3, 0:1]; [1:3, 2:5] }" },
   2114 	{ 0, "{ [0:3, 0:1]; [1:4, 2:5] }" },
   2115 	{ 0, "{ [0:3, 0:1]; [1:5, 2:5] }" },
   2116 };
   2117 
   2118 /* Test the functionality of isl_set_coalesce with the bounded wrapping
   2119  * option turned off.
   2120  */
   2121 int test_coalesce_unbounded_wrapping(isl_ctx *ctx)
   2122 {
   2123 	int i;
   2124 	int r = 0;
   2125 	int bounded;
   2126 
   2127 	bounded = isl_options_get_coalesce_bounded_wrapping(ctx);
   2128 	isl_options_set_coalesce_bounded_wrapping(ctx, 0);
   2129 
   2130 	for (i = 0; i < ARRAY_SIZE(coalesce_unbounded_tests); ++i) {
   2131 		const char *str = coalesce_unbounded_tests[i].str;
   2132 		int check_one = coalesce_unbounded_tests[i].single_disjunct;
   2133 		if (test_coalesce_set(ctx, str, check_one) >= 0)
   2134 			continue;
   2135 		r = -1;
   2136 		break;
   2137 	}
   2138 
   2139 	isl_options_set_coalesce_bounded_wrapping(ctx, bounded);
   2140 
   2141 	return r;
   2142 }
   2143 
   2144 /* Inputs for coalescing tests.
   2145  * "str" is a string representation of the input set.
   2146  * "single_disjunct" is set if we expect the result to consist of
   2147  *	a single disjunct.
   2148  */
   2149 struct {
   2150 	int single_disjunct;
   2151 	const char *str;
   2152 } coalesce_tests[] = {
   2153 	{ 1, "{[x,y]: x >= 0 & x <= 10 & y >= 0 & y <= 10 or "
   2154 		       "y >= x & x >= 2 & 5 >= y }" },
   2155 	{ 1, "{[x,y]: y >= 0 & 2x + y <= 30 & y <= 10 & x >= 0 or "
   2156 		       "x + y >= 10 & y <= x & x + y <= 20 & y >= 0}" },
   2157 	{ 0, "{[x,y]: y >= 0 & 2x + y <= 30 & y <= 10 & x >= 0 or "
   2158 		       "x + y >= 10 & y <= x & x + y <= 19 & y >= 0}" },
   2159 	{ 1, "{[x,y]: y >= 0 & x <= 5 & y <= x or "
   2160 		       "y >= 0 & x >= 6 & x <= 10 & y <= x}" },
   2161 	{ 0, "{[x,y]: y >= 0 & x <= 5 & y <= x or "
   2162 		       "y >= 0 & x >= 7 & x <= 10 & y <= x}" },
   2163 	{ 0, "{[x,y]: y >= 0 & x <= 5 & y <= x or "
   2164 		       "y >= 0 & x >= 6 & x <= 10 & y + 1 <= x}" },
   2165 	{ 1, "{[x,y]: y >= 0 & x <= 5 & y <= x or y >= 0 & x = 6 & y <= 6}" },
   2166 	{ 0, "{[x,y]: y >= 0 & x <= 5 & y <= x or y >= 0 & x = 7 & y <= 6}" },
   2167 	{ 1, "{[x,y]: y >= 0 & x <= 5 & y <= x or y >= 0 & x = 6 & y <= 5}" },
   2168 	{ 0, "{[x,y]: y >= 0 & x <= 5 & y <= x or y >= 0 & x = 6 & y <= 7}" },
   2169 	{ 1, "[n] -> { [i] : i = 1 and n >= 2 or 2 <= i and i <= n }" },
   2170 	{ 0, "{[x,y] : x >= 0 and y >= 0 or 0 <= y and y <= 5 and x = -1}" },
   2171 	{ 1, "[n] -> { [i] : 1 <= i and i <= n - 1 or 2 <= i and i <= n }" },
   2172 	{ 0, "[n] -> { [[i0] -> [o0]] : exists (e0 = [(i0)/4], e1 = [(o0)/4], "
   2173 		"e2 = [(n)/2], e3 = [(-2 + i0)/4], e4 = [(-2 + o0)/4], "
   2174 		"e5 = [(-2n + i0)/4]: 2e2 = n and 4e3 = -2 + i0 and "
   2175 		"4e4 = -2 + o0 and i0 >= 8 + 2n and o0 >= 2 + i0 and "
   2176 		"o0 <= 56 + 2n and o0 <= -12 + 4n and i0 <= 57 + 2n and "
   2177 		"i0 <= -11 + 4n and o0 >= 6 + 2n and 4e0 <= i0 and "
   2178 		"4e0 >= -3 + i0 and 4e1 <= o0 and 4e1 >= -3 + o0 and "
   2179 		"4e5 <= -2n + i0 and 4e5 >= -3 - 2n + i0);"
   2180 		"[[i0] -> [o0]] : exists (e0 = [(i0)/4], e1 = [(o0)/4], "
   2181 		"e2 = [(n)/2], e3 = [(-2 + i0)/4], e4 = [(-2 + o0)/4], "
   2182 		"e5 = [(-2n + i0)/4]: 2e2 = n and 4e3 = -2 + i0 and "
   2183 		"4e4 = -2 + o0 and 2e0 >= 3 + n and e0 <= -4 + n and "
   2184 		"2e0 <= 27 + n and e1 <= -4 + n and 2e1 <= 27 + n and "
   2185 		"2e1 >= 2 + n and e1 >= 1 + e0 and i0 >= 7 + 2n and "
   2186 		"i0 <= -11 + 4n and i0 <= 57 + 2n and 4e0 <= -2 + i0 and "
   2187 		"4e0 >= -3 + i0 and o0 >= 6 + 2n and o0 <= -11 + 4n and "
   2188 		"o0 <= 57 + 2n and 4e1 <= -2 + o0 and 4e1 >= -3 + o0 and "
   2189 		"4e5 <= -2n + i0 and 4e5 >= -3 - 2n + i0 ) }" },
   2190 	{ 0, "[n, m] -> { [o0, o2, o3] : (o3 = 1 and o0 >= 1 + m and "
   2191 	      "o0 <= n + m and o2 <= m and o0 >= 2 + n and o2 >= 3) or "
   2192 	      "(o0 >= 2 + n and o0 >= 1 + m and o0 <= n + m and n >= 1 and "
   2193 	      "o3 <= -1 + o2 and o3 >= 1 - m + o2 and o3 >= 2 and o3 <= n) }" },
   2194 	{ 0, "[M, N] -> { [[i0, i1, i2, i3, i4, i5, i6] -> "
   2195 	  "[o0, o1, o2, o3, o4, o5, o6]] : "
   2196 	  "(o6 <= -4 + 2M - 2N + i0 + i1 - i2 + i6 - o0 - o1 + o2 and "
   2197 	  "o3 <= -2 + i3 and o6 >= 2 + i0 + i3 + i6 - o0 - o3 and "
   2198 	  "o6 >= 2 - M + N + i3 + i4 + i6 - o3 - o4 and o0 <= -1 + i0 and "
   2199 	  "o4 >= 4 - 3M + 3N - i0 - i1 + i2 + 2i3 + i4 + o0 + o1 - o2 - 2o3 "
   2200 	  "and o6 <= -3 + 2M - 2N + i3 + i4 - i5 + i6 - o3 - o4 + o5 and "
   2201 	  "2o6 <= -5 + 5M - 5N + 2i0 + i1 - i2 - i5 + 2i6 - 2o0 - o1 + o2 + o5 "
   2202 	  "and o6 >= 2i0 + i1 + i6 - 2o0 - o1 and "
   2203 	  "3o6 <= -5 + 4M - 4N + 2i0 + i1 - i2 + 2i3 + i4 - i5 + 3i6 "
   2204 	  "- 2o0 - o1 + o2 - 2o3 - o4 + o5) or "
   2205 	  "(N >= 2 and o3 <= -1 + i3 and o0 <= -1 + i0 and "
   2206 	  "o6 >= i3 + i6 - o3 and M >= 0 and "
   2207 	  "2o6 >= 1 + i0 + i3 + 2i6 - o0 - o3 and "
   2208 	  "o6 >= 1 - M + i0 + i6 - o0 and N >= 2M and o6 >= i0 + i6 - o0) }" },
   2209 	{ 0, "[M, N] -> { [o0] : (o0 = 0 and M >= 1 and N >= 2) or "
   2210 		"(o0 = 0 and M >= 1 and N >= 2M and N >= 2 + M) or "
   2211 		"(o0 = 0 and M >= 2 and N >= 3) or "
   2212 		"(M = 0 and o0 = 0 and N >= 3) }" },
   2213 	{ 0, "{ [i0, i1, i2, i3] : (i1 = 10i0 and i0 >= 1 and 10i0 <= 100 and "
   2214 	    "i3 <= 9 + 10 i2 and i3 >= 1 + 10i2 and i3 >= 0) or "
   2215 	    "(i1 <= 9 + 10i0 and i1 >= 1 + 10i0 and i2 >= 0 and "
   2216 	    "i0 >= 0 and i1 <= 100 and i3 <= 9 + 10i2 and i3 >= 1 + 10i2) }" },
   2217 	{ 0, "[M] -> { [i1] : (i1 >= 2 and i1 <= M) or (i1 = M and M >= 1) }" },
   2218 	{ 0, "{[x,y] : x,y >= 0; [x,y] : 10 <= x <= 20 and y >= -1 }" },
   2219 	{ 1, "{ [x, y] : (x >= 1 and y >= 1 and x <= 2 and y <= 2) or "
   2220 		"(y = 3 and x = 1) }" },
   2221 	{ 1, "[M] -> { [i0, i1, i2, i3, i4] : (i1 >= 3 and i4 >= 2 + i2 and "
   2222 		"i2 >= 2 and i0 >= 2 and i3 >= 1 + i2 and i0 <= M and "
   2223 		"i1 <= M and i3 <= M and i4 <= M) or "
   2224 		"(i1 >= 2 and i4 >= 1 + i2 and i2 >= 2 and i0 >= 2 and "
   2225 		"i3 >= 1 + i2 and i0 <= M and i1 <= -1 + M and i3 <= M and "
   2226 		"i4 <= -1 + M) }" },
   2227 	{ 1, "{ [x, y] : (x >= 0 and y >= 0 and x <= 10 and y <= 10) or "
   2228 		"(x >= 1 and y >= 1 and x <= 11 and y <= 11) }" },
   2229 	{ 0, "{[x,0] : x >= 0; [x,1] : x <= 20}" },
   2230 	{ 1, "{ [x, 1 - x] : 0 <= x <= 1; [0,0] }" },
   2231 	{ 1, "{ [0,0]; [i,i] : 1 <= i <= 10 }" },
   2232 	{ 0, "{ [0,0]; [i,j] : 1 <= i,j <= 10 }" },
   2233 	{ 1, "{ [0,0]; [i,2i] : 1 <= i <= 10 }" },
   2234 	{ 0, "{ [0,0]; [i,2i] : 2 <= i <= 10 }" },
   2235 	{ 0, "{ [1,0]; [i,2i] : 1 <= i <= 10 }" },
   2236 	{ 0, "{ [0,1]; [i,2i] : 1 <= i <= 10 }" },
   2237 	{ 0, "{ [a, b] : exists e : 2e = a and "
   2238 		    "a >= 0 and (a <= 3 or (b <= 0 and b >= -4 + a)) }" },
   2239 	{ 0, "{ [i, j, i', j'] : i <= 2 and j <= 2 and "
   2240 			"j' >= -1 + 2i + j - 2i' and i' <= -1 + i and "
   2241 			"j >= 1 and j' <= i + j - i' and i >= 1; "
   2242 		"[1, 1, 1, 1] }" },
   2243 	{ 1, "{ [i,j] : exists a,b : i = 2a and j = 3b; "
   2244 		 "[i,j] : exists a : j = 3a }" },
   2245 	{ 1, "{ [a, b, c] : (c <= 7 - b and b <= 1 and b >= 0 and "
   2246 			"c >= 3 + b and b <= 3 + 8a and b >= -26 + 8a and "
   2247 			"a >= 3) or "
   2248 		    "(b <= 1 and c <= 7 and b >= 0 and c >= 4 + b and "
   2249 			"b <= 3 + 8a and b >= -26 + 8a and a >= 3) }" },
   2250 	{ 1, "{ [a, 0, c] : c >= 1 and c <= 29 and c >= -1 + 8a and "
   2251 				"c <= 6 + 8a and a >= 3; "
   2252 		"[a, -1, c] : c >= 1 and c <= 30 and c >= 8a and "
   2253 				"c <= 7 + 8a and a >= 3 and a <= 4 }" },
   2254 	{ 1, "{ [x,y] : 0 <= x <= 2 and y >= 0 and x + 2y <= 4; "
   2255 		"[x,0] : 3 <= x <= 4 }" },
   2256 	{ 1, "{ [x,y] : 0 <= x <= 3 and y >= 0 and x + 3y <= 6; "
   2257 		"[x,0] : 4 <= x <= 5 }" },
   2258 	{ 0, "{ [x,y] : 0 <= x <= 2 and y >= 0 and x + 2y <= 4; "
   2259 		"[x,0] : 3 <= x <= 5 }" },
   2260 	{ 0, "{ [x,y] : 0 <= x <= 2 and y >= 0 and x + y <= 4; "
   2261 		"[x,0] : 3 <= x <= 4 }" },
   2262 	{ 1, "{ [i0, i1] : i0 <= 122 and i0 >= 1 and 128i1 >= -249 + i0 and "
   2263 			"i1 <= 0; "
   2264 		"[i0, 0] : i0 >= 123 and i0 <= 124 }" },
   2265 	{ 1, "{ [0,0]; [1,1] }" },
   2266 	{ 1, "[n] -> { [k] : 16k <= -1 + n and k >= 1; [0] : n >= 2 }" },
   2267 	{ 1, "{ [k, ii, k - ii] : ii >= -6 + k and ii <= 6 and ii >= 1 and "
   2268 				"ii <= k;"
   2269 		"[k, 0, k] : k <= 6 and k >= 1 }" },
   2270 	{ 1, "{ [i,j] : i = 4 j and 0 <= i <= 100;"
   2271 		"[i,j] : 1 <= i <= 100 and i >= 4j + 1 and i <= 4j + 2 }" },
   2272 	{ 1, "{ [x,y] : x % 2 = 0 and y % 2 = 0; [x,x] : x % 2 = 0 }" },
   2273 	{ 1, "[n] -> { [1] : n >= 0;"
   2274 		    "[x] : exists (e0 = floor((x)/2): x >= 2 and "
   2275 			"2e0 >= -1 + x and 2e0 <= x and 2e0 <= n) }" },
   2276 	{ 1, "[n] -> { [x, y] : exists (e0 = floor((x)/2), e1 = floor((y)/3): "
   2277 			"3e1 = y and x >= 2 and 2e0 >= -1 + x and "
   2278 			"2e0 <= x and 2e0 <= n);"
   2279 		    "[1, y] : exists (e0 = floor((y)/3): 3e0 = y and "
   2280 			"n >= 0) }" },
   2281 	{ 1, "[t1] -> { [i0] : (exists (e0 = floor((63t1)/64): "
   2282 				"128e0 >= -134 + 127t1 and t1 >= 2 and "
   2283 				"64e0 <= 63t1 and 64e0 >= -63 + 63t1)) or "
   2284 				"t1 = 1 }" },
   2285 	{ 1, "{ [i, i] : exists (e0 = floor((1 + 2i)/3): 3e0 <= 2i and "
   2286 				"3e0 >= -1 + 2i and i <= 9 and i >= 1);"
   2287 		"[0, 0] }" },
   2288 	{ 1, "{ [t1] : exists (e0 = floor((-11 + t1)/2): 2e0 = -11 + t1 and "
   2289 				"t1 >= 13 and t1 <= 16);"
   2290 		"[t1] : t1 <= 15 and t1 >= 12 }" },
   2291 	{ 1, "{ [x,y] : x = 3y and 0 <= y <= 2; [-3,-1] }" },
   2292 	{ 1, "{ [x,y] : 2x = 3y and 0 <= y <= 4; [-3,-2] }" },
   2293 	{ 0, "{ [x,y] : 2x = 3y and 0 <= y <= 4; [-2,-2] }" },
   2294 	{ 0, "{ [x,y] : 2x = 3y and 0 <= y <= 4; [-3,-1] }" },
   2295 	{ 1, "{ [i] : exists j : i = 4 j and 0 <= i <= 100;"
   2296 		"[i] : exists j : 1 <= i <= 100 and i >= 4j + 1 and "
   2297 				"i <= 4j + 2 }" },
   2298 	{ 1, "{ [c0] : (exists (e0 : c0 - 1 <= 3e0 <= c0)) or "
   2299 		"(exists (e0 : 3e0 = -2 + c0)) }" },
   2300 	{ 0, "[n, b0, t0] -> "
   2301 		"{ [i0, i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11, i12] : "
   2302 		"(exists (e0 = floor((-32b0 + i4)/1048576), "
   2303 		"e1 = floor((i8)/32): 1048576e0 = -32b0 + i4 and 32e1 = i8 and "
   2304 		"n <= 2147483647 and b0 <= 32767 and b0 >= 0 and "
   2305 		"32b0 <= -2 + n and t0 <= 31 and t0 >= 0 and i0 >= 8 + n and "
   2306 		"3i4 <= -96 + 3t0 + i0 and 3i4 >= -95 - n + 3t0 + i0 and "
   2307 		"i8 >= -157 + i0 - 4i4 and i8 >= 0 and "
   2308 		"i8 <= -33 + i0 - 4i4 and 3i8 <= -91 + 4n - i0)) or "
   2309 		"(exists (e0 = floor((-32b0 + i4)/1048576), "
   2310 		"e1 = floor((i8)/32): 1048576e0 = -32b0 + i4 and 32e1 = i8 and "
   2311 		"n <= 2147483647 and b0 <= 32767 and b0 >= 0 and "
   2312 		"32b0 <= -2 + n and t0 <= 31 and t0 >= 0 and i0 <= 7 + n and "
   2313 		"4i4 <= -3 + i0 and 3i4 <= -96 + 3t0 + i0 and "
   2314 		"3i4 >= -95 - n + 3t0 + i0 and i8 >= -157 + i0 - 4i4 and "
   2315 		"i8 >= 0 and i8 <= -4 + i0 - 3i4 and i8 <= -41 + i0));"
   2316 		"[i0, i1, i2, i3, 0, i5, i6, i7, i8, i9, i10, i11, i12] : "
   2317 		"(exists (e0 = floor((i8)/32): b0 = 0 and 32e0 = i8 and "
   2318 		"n <= 2147483647 and t0 <= 31 and t0 >= 0 and i0 >= 11 and "
   2319 		"i0 >= 96 - 3t0 and i0 <= 95 + n - 3t0 and i0 <= 7 + n and "
   2320 		"i8 >= -40 + i0 and i8 <= -10 + i0)) }" },
   2321 	{ 0, "{ [i0, i1, i2] : "
   2322 		"(exists (e0, e1 = floor((i0)/32), e2 = floor((i1)/32): "
   2323 		"32e1 = i0 and 32e2 = i1 and i1 >= -31 + i0 and "
   2324 		"i1 <= 31 + i0 and i2 >= -30 + i0 and i2 >= -30 + i1 and "
   2325 		"32e0 >= -30 + i0 and 32e0 >= -30 + i1 and "
   2326 		"32e0 >= -31 + i2 and 32e0 <= 30 + i2 and 32e0 <= 31 + i1 and "
   2327 		"32e0 <= 31 + i0)) or "
   2328 		"i0 >= 0 }" },
   2329 	{ 1, "{ [a, b, c] : 2b = 1 + a and 2c = 2 + a; [0, 0, 0] }" },
   2330 	{ 1, "{ [a, a, b, c] : 32*floor((a)/32) = a and 2*floor((b)/2) = b and "
   2331 				"2*floor((c)/2) = c and 0 <= a <= 192;"
   2332 		"[224, 224, b, c] : 2*floor((b)/2) = b and 2*floor((c)/2) = c }"
   2333 	},
   2334 	{ 1, "[n] -> { [a,b] : (exists e : 1 <= a <= 7e and 9e <= b <= n) or "
   2335 				"(0 <= a <= b <= n) }" },
   2336 	{ 1, "{ [a, b] : 0 <= a <= 2 and b >= 0 and "
   2337 		"((0 < b <= 13) or (2*floor((a + b)/2) >= -5 + a + 2b)) }" },
   2338 	{ 1, "{ [a] : (2 <= a <= 5) or (a mod 2 = 1 and 1 <= a <= 5) }" },
   2339 	{ 1, "{ [a, b, c] : (b = -1 + a and 0 < a <= 3 and "
   2340 				"9*floor((-4a + 2c)/9) <= -3 - 4a + 2c) or "
   2341 			"(exists (e0 = floor((-16 + 2c)/9): a = 4 and "
   2342 				"b = 3 and 9e0 <= -19 + 2c)) }" },
   2343 	{ 1, "{ [a, b, c] : (b = -1 + a and 0 < a <= 3 and "
   2344 				"9*floor((-4a + 2c)/9) <= -3 - 4a + 2c) or "
   2345 			"(a = 4 and b = 3 and "
   2346 				"9*floor((-16 + 2c)/9) <= -19 + 2c) }" },
   2347 	{ 0, "{ [a, b, c] : (b <= 2 and b <= -2 + a) or "
   2348 			"(b = -1 + a and 0 < a <= 3 and "
   2349 				"9*floor((-4a + 2c)/9) <= -3 - 4a + 2c) or "
   2350 			"(exists (e0 = floor((-16 + 2c)/9): a = 4 and "
   2351 				"b = 3 and 9e0 <= -19 + 2c)) }" },
   2352 	{ 1, "{ [y, x] : (x - y) mod 3 = 2 and 2 <= y <= 200 and 0 <= x <= 2;"
   2353 		"[1, 0] }" },
   2354 	{ 1, "{ [x, y] : (x - y) mod 3 = 2 and 2 <= y <= 200 and 0 <= x <= 2;"
   2355 		"[0, 1] }" },
   2356 	{ 1, "{ [1, y] : -1 <= y <= 1; [x, -x] : 0 <= x <= 1 }" },
   2357 	{ 1, "{ [1, y] : 0 <= y <= 1; [x, -x] : 0 <= x <= 1 }" },
   2358 	{ 1, "{ [x, y] : 0 <= x <= 10 and x - 4*floor(x/4) <= 1 and y <= 0; "
   2359 	       "[x, y] : 0 <= x <= 10 and x - 4*floor(x/4) > 1 and y <= 0; "
   2360 	       "[x, y] : 0 <= x <= 10 and x - 5*floor(x/5) <= 1 and 0 < y; "
   2361 	       "[x, y] : 0 <= x <= 10 and x - 5*floor(x/5) > 1 and 0 < y }" },
   2362 	{ 1, "{ [x, 0] : 0 <= x <= 10 and x mod 2 = 0; "
   2363 	       "[x, 0] : 0 <= x <= 10 and x mod 2 = 1; "
   2364 	       "[x, y] : 0 <= x <= 10 and 1 <= y <= 10 }" },
   2365 	{ 1, "{ [a] : a <= 8 and "
   2366 			"(a mod 10 = 7 or a mod 10 = 8 or a mod 10 = 9) }" },
   2367 	{ 1, "{ [x, y] : 2y = -x and x <= 0 or "
   2368 			"x <= -1 and 2y <= -x - 1 and 2y >= x - 1 }" },
   2369 	{ 0, "{ [x, y] : 2y = -x and x <= 0 or "
   2370 			"x <= -2 and 2y <= -x - 1 and 2y >= x - 1 }" },
   2371 	{ 1, "{ [a] : (a <= 0 and 3*floor((a)/3) = a) or "
   2372 			"(a < 0 and 3*floor((a)/3) < a) }" },
   2373 	{ 1, "{ [a] : (a <= 0 and 3*floor((a)/3) = a) or "
   2374 			"(a < -1 and 3*floor((a)/3) < a) }" },
   2375 	{ 1, "{ [a, b] : a <= 1024 and b >= 0 and "
   2376 		"((-31 - a + b <= 32*floor((-1 - a)/32) <= -33 + b and "
   2377 		  "32*floor((-1 - a)/32) <= -16 + b + 16*floor((-1 - a)/16))"
   2378 		"or (2 <= a <= 15 and b < a)) }" },
   2379 	{ 1, "{ [a] : a > 0 and ((16*floor((a)/16) < a and "
   2380 			"32*floor((a)/32) < a) or a <= 15) }" },
   2381 	{ 1, "{ [a, b, c, d] : (-a + d) mod 64 = 0 and a <= 8 and b <= 1 and "
   2382 			"10 - a <= c <= 3 and d >= 5 and 9 - 64b <= d <= 70;"
   2383 	    "[a, b = 1, c, d] : (-a + d) mod 64 = 0 and a <= 8 and c >= 4 and "
   2384 			"10 - a <= c <= 5 and 5 <= d <= 73 - c }" },
   2385 	{ 1, "[n, m] -> { S_0[i] : (-n + i) mod 3 = 0 and m >= 3 + n and "
   2386 			    "i >= n and 3*floor((2 + n + 2m)/3) <= n + 3m - i; "
   2387 			 "S_0[n] : n <= m <= 2 + n }" },
   2388 	{ 1, "{ [a, b] : exists (e0: 0 <= a <= 1 and b >= 0 and "
   2389 			"2e0 >= -5 + a + 2b and 2e0 >= -1 + a + b and "
   2390 			"2e0 <= a + b); "
   2391 		"[a, b] : exists (e0: 0 <= a <= 1 and 2e0 >= -5 + a + 2b and "
   2392 			"2e0 >= -1 - a + b and 2e0 <= -a + b and "
   2393 			"2e0 < -a + 2b) }" },
   2394 	{ 1, "{ [i, j, i - 8j] : 8 <= i <= 63 and -7 + i <= 8j <= i; "
   2395 		"[i, 0, i] : 0 <= i <= 7 }" },
   2396 	{ 1, "{ [a, b] : a >= 0 and 0 <= b <= 1 - a; [1, 1] }" },
   2397 	{ 0, "{ [a, b] : a >= 0 and 0 <= b <= 1 - a; [0, 2] }" },
   2398 	{ 0, "{ [a, b] : a >= 0 and 0 <= b <= 1 - a; [-1, 3] }" },
   2399 	{ 1, "{ [a, b] : a, b >= 0 and a + 2b <= 2; [1, 1] }" },
   2400 	{ 0, "{ [a, b] : a, b >= 0 and a + 2b <= 2; [2, 1] }" },
   2401 	{ 0, "{ [a, c] : (2 + a) mod 4 = 0 or "
   2402 		"(c = 4 + a and 4 * floor((a)/4) = a and a >= 0 and a <= 4) or "
   2403 		"(c = 3 + a and 4 * floor((-1 + a)/4) = -1 + a and "
   2404 		    "a > 0 and a <= 5) }" },
   2405 	{ 1, "{ [1, 0, 0]; [a, b, c] : -1 <= -a < b <= 0 and 2c > b }" },
   2406 	{ 0, "{ [j, a, l] : a mod 2 = 0 and j <= 29 and a >= 2 and "
   2407 			"2a <= -5 + j and 32j + 2a + 2 <= 4l < 33j; "
   2408 		"[j, 0, l] : 4 <= j <= 29 and -3 + 33j <= 4l <= 33j }" },
   2409 	{ 0, "{ [0:1, 0:1]; [0, 2:3] }" },
   2410 	{ 1, "{ [a] : (a = 0 or ((1 + a) mod 2 = 0 and 0 < a <= 15) or "
   2411 		"((a) mod 2 = 0 and 0 < a <= 15)) }" },
   2412 	{ 1, "{ rat: [0:2]; rat: [1:3] }" },
   2413 };
   2414 
   2415 /* A specialized coalescing test case that would result
   2416  * in a segmentation fault or a failed assertion in earlier versions of isl.
   2417  */
   2418 static int test_coalesce_special(struct isl_ctx *ctx)
   2419 {
   2420 	const char *str;
   2421 	isl_map *map1, *map2;
   2422 
   2423 	str = "[y] -> { [S_L220_OUT[] -> T7[]] -> "
   2424 	    "[[S_L309_IN[] -> T11[]] -> ce_imag2[1, o1]] : "
   2425 	    "(y = 201 and o1 <= 239 and o1 >= 212) or "
   2426 	    "(exists (e0 = [(y)/3]: 3e0 = y and y <= 198 and y >= 3 and "
   2427 		"o1 <= 239 and o1 >= 212)) or "
   2428 	    "(exists (e0 = [(y)/3]: 3e0 = y and y <= 201 and y >= 3 and "
   2429 		"o1 <= 241 and o1 >= 240));"
   2430 	    "[S_L220_OUT[] -> T7[]] -> "
   2431 	    "[[S_L309_IN[] -> T11[]] -> ce_imag2[0, o1]] : "
   2432 	    "(y = 2 and o1 <= 241 and o1 >= 212) or "
   2433 	    "(exists (e0 = [(-2 + y)/3]: 3e0 = -2 + y and y <= 200 and "
   2434 		"y >= 5 and o1 <= 241 and o1 >= 212)) }";
   2435 	map1 = isl_map_read_from_str(ctx, str);
   2436 	map1 = isl_map_align_divs_internal(map1);
   2437 	map1 = isl_map_coalesce(map1);
   2438 	str = "[y] -> { [S_L220_OUT[] -> T7[]] -> "
   2439 	    "[[S_L309_IN[] -> T11[]] -> ce_imag2[o0, o1]] : "
   2440 	    "exists (e0 = [(-1 - y + o0)/3]: 3e0 = -1 - y + o0 and "
   2441 		"y <= 201 and o0 <= 2 and o1 >= 212 and o1 <= 241 and "
   2442 		"o0 >= 3 - y and o0 <= -2 + y and o0 >= 0) }";
   2443 	map2 = isl_map_read_from_str(ctx, str);
   2444 	map2 = isl_map_union(map2, map1);
   2445 	map2 = isl_map_align_divs_internal(map2);
   2446 	map2 = isl_map_coalesce(map2);
   2447 	isl_map_free(map2);
   2448 	if (!map2)
   2449 		return -1;
   2450 
   2451 	return 0;
   2452 }
   2453 
   2454 /* Check that the union of the basic sets described by "str1" and "str2"
   2455  * can be coalesced and that the result is equal to the union.
   2456  * The explicit call to isl_basic_set_union prevents the implicit
   2457  * equality constraints in the basic maps from being detected prior
   2458  * to the call to isl_set_coalesce, at least at the point
   2459  * where this function was introduced.
   2460  */
   2461 static isl_stat test_coalesce_union(isl_ctx *ctx, const char *str1,
   2462 	const char *str2)
   2463 {
   2464 	isl_basic_set *bset1, *bset2;
   2465 	isl_set *set, *set2;
   2466 	isl_bool equal;
   2467 
   2468 	bset1 = isl_basic_set_read_from_str(ctx, str1);
   2469 	bset2 = isl_basic_set_read_from_str(ctx, str2);
   2470 	set = isl_basic_set_union(bset1, bset2);
   2471 	set = isl_set_coalesce(set);
   2472 
   2473 	bset1 = isl_basic_set_read_from_str(ctx, str1);
   2474 	bset2 = isl_basic_set_read_from_str(ctx, str2);
   2475 	set2 = isl_basic_set_union(bset1, bset2);
   2476 
   2477 	equal = isl_set_is_equal(set, set2);
   2478 	isl_set_free(set);
   2479 	isl_set_free(set2);
   2480 
   2481 	if (equal < 0)
   2482 		return isl_stat_error;
   2483 	if (!equal)
   2484 		isl_die(ctx, isl_error_unknown,
   2485 			"coalesced set not equal to input",
   2486 			return isl_stat_error);
   2487 
   2488 	return isl_stat_non_null(set);
   2489 }
   2490 
   2491 /* A specialized coalescing test case that would result in an assertion
   2492  * in an earlier version of isl.  Use test_coalesce_union with
   2493  * an explicit call to isl_basic_set_union to prevent the implicit
   2494  * equality constraints in the first basic map from being detected prior
   2495  * to the call to isl_set_coalesce, at least at the point
   2496  * where this test case was introduced.
   2497  */
   2498 static isl_stat test_coalesce_special2(struct isl_ctx *ctx)
   2499 {
   2500 	const char *str1;
   2501 	const char *str2;
   2502 
   2503 	str1 = "{ [x, y] : x, y >= 0 and x + 2y <= 1 and 2x + y <= 1 }";
   2504 	str2 = "{ [x,0] : -1 <= x <= 1 and x mod 2 = 1 }";
   2505 	return test_coalesce_union(ctx, str1, str2);
   2506 }
   2507 
   2508 /* Check that calling isl_set_coalesce does not leave other sets
   2509  * that may share some information with the input to isl_set_coalesce
   2510  * in an inconsistent state.
   2511  * In particular, older versions of isl would modify all copies
   2512  * of the basic sets in the isl_set_coalesce input in a way
   2513  * that could leave them in an inconsistent state.
   2514  * The result of printing any other set containing one of these
   2515  * basic sets would then result in an invalid set description.
   2516  */
   2517 static int test_coalesce_special3(isl_ctx *ctx)
   2518 {
   2519 	const char *str;
   2520 	char *s;
   2521 	isl_set *set1, *set2;
   2522 	isl_printer *p;
   2523 
   2524 	set1 = isl_set_read_from_str(ctx, "{ [0, 0, 0] }");
   2525 	str = "{ [a, b, a + b] : a >= 0 and b >= 0 and 0 < a + b }";
   2526 	set2 = isl_set_read_from_str(ctx, str);
   2527 	set1 = isl_set_union(set1, isl_set_copy(set2));
   2528 	set1 = isl_set_coalesce(set1);
   2529 	isl_set_free(set1);
   2530 
   2531 	p = isl_printer_to_str(ctx);
   2532 	p = isl_printer_print_set(p, set2);
   2533 	isl_set_free(set2);
   2534 	s = isl_printer_get_str(p);
   2535 	isl_printer_free(p);
   2536 	set1 = isl_set_read_from_str(ctx, s);
   2537 	free(s);
   2538 	isl_set_free(set1);
   2539 
   2540 	if (!set1)
   2541 		return -1;
   2542 
   2543 	return 0;
   2544 }
   2545 
   2546 /* Check that calling isl_set_coalesce on the intersection of
   2547  * the sets described by "s1" and "s2" does not leave other sets
   2548  * that may share some information with the input to isl_set_coalesce
   2549  * in an inconsistent state.
   2550  * In particular, when isl_set_coalesce detects equality constraints,
   2551  * it does not immediately perform Gaussian elimination on them,
   2552  * but then it needs to ensure that it is performed at some point.
   2553  * The input set has implicit equality constraints in the first disjunct.
   2554  * It is constructed as an intersection, because otherwise
   2555  * those equality constraints would already be detected during parsing.
   2556  */
   2557 static isl_stat test_coalesce_intersection(isl_ctx *ctx,
   2558 	const char *s1, const char *s2)
   2559 {
   2560 	isl_set *set1, *set2;
   2561 
   2562 	set1 = isl_set_read_from_str(ctx, s1);
   2563 	set2 = isl_set_read_from_str(ctx, s2);
   2564 	set1 = isl_set_intersect(set1, set2);
   2565 	isl_set_free(isl_set_coalesce(isl_set_copy(set1)));
   2566 	set1 = isl_set_coalesce(set1);
   2567 	isl_set_free(set1);
   2568 
   2569 	if (!set1)
   2570 		return isl_stat_error;
   2571 
   2572 	return isl_stat_ok;
   2573 }
   2574 
   2575 /* Check that calling isl_set_coalesce does not leave other sets
   2576  * that may share some information with the input to isl_set_coalesce
   2577  * in an inconsistent state, for the case where one disjunct
   2578  * is a subset of the other.
   2579  */
   2580 static isl_stat test_coalesce_special4(isl_ctx *ctx)
   2581 {
   2582 	const char *s1, *s2;
   2583 
   2584 	s1 = "{ [a, b] : b <= 0 or a <= 1 }";
   2585 	s2 = "{ [a, b] : -1 <= -a < b }";
   2586 	return test_coalesce_intersection(ctx, s1, s2);
   2587 }
   2588 
   2589 /* Check that calling isl_set_coalesce does not leave other sets
   2590  * that may share some information with the input to isl_set_coalesce
   2591  * in an inconsistent state, for the case where two disjuncts
   2592  * can be fused.
   2593  */
   2594 static isl_stat test_coalesce_special5(isl_ctx *ctx)
   2595 {
   2596 	const char *s1, *s2;
   2597 
   2598 	s1 = "{ [a, b, c] : b <= 0 }";
   2599 	s2 = "{ [a, b, c] : -1 <= -a < b and (c >= 0 or c < 0) }";
   2600 	return test_coalesce_intersection(ctx, s1, s2);
   2601 }
   2602 
   2603 /* Check that calling isl_set_coalesce does not leave other sets
   2604  * that may share some information with the input to isl_set_coalesce
   2605  * in an inconsistent state, for the case where two disjuncts
   2606  * can be fused and where both disjuncts have implicit equality constraints.
   2607  */
   2608 static isl_stat test_coalesce_special6(isl_ctx *ctx)
   2609 {
   2610 	const char *s1, *s2;
   2611 
   2612 	s1 = "{ [a, b, c] : c <= 0 }";
   2613 	s2 = "{ [a, b, c] : 0 <= a <= b <= c or (0 <= b <= c and a > 0) }";
   2614 	return test_coalesce_intersection(ctx, s1, s2);
   2615 }
   2616 
   2617 /* A specialized coalescing test case that would result in an assertion failure
   2618  * in an earlier version of isl.  Use test_coalesce_union with
   2619  * an explicit call to isl_basic_set_union to prevent the implicit
   2620  * equality constraints in the basic maps from being detected prior
   2621  * to the call to isl_set_coalesce, at least at the point
   2622  * where this test case was introduced.
   2623  */
   2624 static isl_stat test_coalesce_special7(isl_ctx *ctx)
   2625 {
   2626 	const char *str1;
   2627 	const char *str2;
   2628 
   2629 	str1 = "{ [a, b, c=0:17] : a <= 7 and 2b <= 11 - a and "
   2630 			"c <= -7 + 2a and 2c >= - 3 + 3a - 2b }";
   2631 	str2 = "{ [a, b, c] : c > -15a and c >= -7 + 2a and c < 0 and "
   2632 			"3c <= -5 + 5a - 3b and 2b >= 11 - a }";
   2633 	return test_coalesce_union(ctx, str1, str2);
   2634 }
   2635 
   2636 /* A specialized coalescing test case that would result in a disjunct
   2637  * getting dropped in an earlier version of isl.  Use test_coalesce_union with
   2638  * an explicit call to isl_basic_set_union to prevent the implicit
   2639  * equality constraints in the basic maps from being detected prior
   2640  * to the call to isl_set_coalesce, at least at the point
   2641  * where this test case was introduced.
   2642  */
   2643 static isl_stat test_coalesce_special8(isl_ctx *ctx)
   2644 {
   2645 	const char *str1;
   2646 	const char *str2;
   2647 
   2648 	str1 = "{ [a, b, c] : 2c <= -a and b >= -a and b <= 5 and "
   2649 			"6c > -7a and 11c >= -5a - b and a <= 3 }";
   2650 	str2 = "{ [a, b, c] : 6c > -7a and b >= -a and b <= 5 and "
   2651 			"11c >= -5a - b and a >= 4 and 2b <= a and 2c <= -a }";
   2652 	return test_coalesce_union(ctx, str1, str2);
   2653 }
   2654 
   2655 /* Test the functionality of isl_set_coalesce.
   2656  * That is, check that the output is always equal to the input
   2657  * and in some cases that the result consists of a single disjunct.
   2658  */
   2659 static int test_coalesce(struct isl_ctx *ctx)
   2660 {
   2661 	int i;
   2662 
   2663 	for (i = 0; i < ARRAY_SIZE(coalesce_tests); ++i) {
   2664 		const char *str = coalesce_tests[i].str;
   2665 		int check_one = coalesce_tests[i].single_disjunct;
   2666 		if (test_coalesce_set(ctx, str, check_one) < 0)
   2667 			return -1;
   2668 	}
   2669 
   2670 	if (test_coalesce_unbounded_wrapping(ctx) < 0)
   2671 		return -1;
   2672 	if (test_coalesce_special(ctx) < 0)
   2673 		return -1;
   2674 	if (test_coalesce_special2(ctx) < 0)
   2675 		return -1;
   2676 	if (test_coalesce_special3(ctx) < 0)
   2677 		return -1;
   2678 	if (test_coalesce_special4(ctx) < 0)
   2679 		return -1;
   2680 	if (test_coalesce_special5(ctx) < 0)
   2681 		return -1;
   2682 	if (test_coalesce_special6(ctx) < 0)
   2683 		return -1;
   2684 	if (test_coalesce_special7(ctx) < 0)
   2685 		return -1;
   2686 	if (test_coalesce_special8(ctx) < 0)
   2687 		return -1;
   2688 
   2689 	return 0;
   2690 }
   2691 
   2692 /* Construct a representation of the graph on the right of Figure 1
   2693  * in "Computing the Transitive Closure of a Union of
   2694  * Affine Integer Tuple Relations".
   2695  */
   2696 static __isl_give isl_map *cocoa_fig_1_right_graph(isl_ctx *ctx)
   2697 {
   2698 	isl_set *dom;
   2699 	isl_map *up, *right;
   2700 
   2701 	dom = isl_set_read_from_str(ctx,
   2702 		"{ [x,y] : x >= 0 and -2 x + 3 y >= 0 and x <= 3 and "
   2703 			"2 x - 3 y + 3 >= 0 }");
   2704 	right = isl_map_read_from_str(ctx,
   2705 		"{ [x,y] -> [x2,y2] : x2 = x + 1 and y2 = y }");
   2706 	up = isl_map_read_from_str(ctx,
   2707 		"{ [x,y] -> [x2,y2] : x2 = x and y2 = y + 1 }");
   2708 	right = isl_map_intersect_domain(right, isl_set_copy(dom));
   2709 	right = isl_map_intersect_range(right, isl_set_copy(dom));
   2710 	up = isl_map_intersect_domain(up, isl_set_copy(dom));
   2711 	up = isl_map_intersect_range(up, dom);
   2712 	return isl_map_union(up, right);
   2713 }
   2714 
   2715 /* Construct a representation of the power of the graph
   2716  * on the right of Figure 1 in "Computing the Transitive Closure of
   2717  * a Union of Affine Integer Tuple Relations".
   2718  */
   2719 static __isl_give isl_map *cocoa_fig_1_right_power(isl_ctx *ctx)
   2720 {
   2721 	return isl_map_read_from_str(ctx,
   2722 		"{ [1] -> [[0,0] -> [0,1]]; [2] -> [[0,0] -> [1,1]]; "
   2723 		"  [1] -> [[0,1] -> [1,1]]; [1] -> [[2,2] -> [3,2]]; "
   2724 		"  [2] -> [[2,2] -> [3,3]]; [1] -> [[3,2] -> [3,3]] }");
   2725 }
   2726 
   2727 /* Construct a representation of the transitive closure of the graph
   2728  * on the right of Figure 1 in "Computing the Transitive Closure of
   2729  * a Union of Affine Integer Tuple Relations".
   2730  */
   2731 static __isl_give isl_map *cocoa_fig_1_right_tc(isl_ctx *ctx)
   2732 {
   2733 	return isl_set_unwrap(isl_map_range(cocoa_fig_1_right_power(ctx)));
   2734 }
   2735 
   2736 static int test_closure(isl_ctx *ctx)
   2737 {
   2738 	const char *str;
   2739 	isl_map *map, *map2;
   2740 	isl_bool exact, equal;
   2741 
   2742 	/* COCOA example 1 */
   2743 	map = isl_map_read_from_str(ctx,
   2744 		"[n] -> { [i,j] -> [i2,j2] : i2 = i + 1 and j2 = j + 1 and "
   2745 			"1 <= i and i < n and 1 <= j and j < n or "
   2746 			"i2 = i + 1 and j2 = j - 1 and "
   2747 			"1 <= i and i < n and 2 <= j and j <= n }");
   2748 	map = isl_map_power(map, &exact);
   2749 	assert(exact);
   2750 	isl_map_free(map);
   2751 
   2752 	/* COCOA example 1 */
   2753 	map = isl_map_read_from_str(ctx,
   2754 		"[n] -> { [i,j] -> [i2,j2] : i2 = i + 1 and j2 = j + 1 and "
   2755 			"1 <= i and i < n and 1 <= j and j < n or "
   2756 			"i2 = i + 1 and j2 = j - 1 and "
   2757 			"1 <= i and i < n and 2 <= j and j <= n }");
   2758 	map = isl_map_transitive_closure(map, &exact);
   2759 	assert(exact);
   2760 	map2 = isl_map_read_from_str(ctx,
   2761 		"[n] -> { [i,j] -> [i2,j2] : exists (k1,k2,k : "
   2762 			"1 <= i and i < n and 1 <= j and j <= n and "
   2763 			"2 <= i2 and i2 <= n and 1 <= j2 and j2 <= n and "
   2764 			"i2 = i + k1 + k2 and j2 = j + k1 - k2 and "
   2765 			"k1 >= 0 and k2 >= 0 and k1 + k2 = k and k >= 1 )}");
   2766 	assert(isl_map_is_equal(map, map2));
   2767 	isl_map_free(map2);
   2768 	isl_map_free(map);
   2769 
   2770 	map = isl_map_read_from_str(ctx,
   2771 		"[n] -> { [x] -> [y] : y = x + 1 and 0 <= x and x <= n and "
   2772 				     " 0 <= y and y <= n }");
   2773 	map = isl_map_transitive_closure(map, &exact);
   2774 	map2 = isl_map_read_from_str(ctx,
   2775 		"[n] -> { [x] -> [y] : y > x and 0 <= x and x <= n and "
   2776 				     " 0 <= y and y <= n }");
   2777 	assert(isl_map_is_equal(map, map2));
   2778 	isl_map_free(map2);
   2779 	isl_map_free(map);
   2780 
   2781 	/* COCOA example 2 */
   2782 	map = isl_map_read_from_str(ctx,
   2783 		"[n] -> { [i,j] -> [i2,j2] : i2 = i + 2 and j2 = j + 2 and "
   2784 			"1 <= i and i < n - 1 and 1 <= j and j < n - 1 or "
   2785 			"i2 = i + 2 and j2 = j - 2 and "
   2786 			"1 <= i and i < n - 1 and 3 <= j and j <= n }");
   2787 	map = isl_map_transitive_closure(map, &exact);
   2788 	assert(exact);
   2789 	map2 = isl_map_read_from_str(ctx,
   2790 		"[n] -> { [i,j] -> [i2,j2] : exists (k1,k2,k : "
   2791 			"1 <= i and i < n - 1 and 1 <= j and j <= n and "
   2792 			"3 <= i2 and i2 <= n and 1 <= j2 and j2 <= n and "
   2793 			"i2 = i + 2 k1 + 2 k2 and j2 = j + 2 k1 - 2 k2 and "
   2794 			"k1 >= 0 and k2 >= 0 and k1 + k2 = k and k >= 1) }");
   2795 	assert(isl_map_is_equal(map, map2));
   2796 	isl_map_free(map);
   2797 	isl_map_free(map2);
   2798 
   2799 	/* COCOA Fig.2 left */
   2800 	map = isl_map_read_from_str(ctx,
   2801 		"[n] -> { [i,j] -> [i2,j2] : i2 = i + 2 and j2 = j and "
   2802 			"i <= 2 j - 3 and i <= n - 2 and j <= 2 i - 1 and "
   2803 			"j <= n or "
   2804 			"i2 = i and j2 = j + 2 and i <= 2 j - 1 and i <= n and "
   2805 			"j <= 2 i - 3 and j <= n - 2 or "
   2806 			"i2 = i + 1 and j2 = j + 1 and i <= 2 j - 1 and "
   2807 			"i <= n - 1 and j <= 2 i - 1 and j <= n - 1 }");
   2808 	map = isl_map_transitive_closure(map, &exact);
   2809 	assert(exact);
   2810 	isl_map_free(map);
   2811 
   2812 	/* COCOA Fig.2 right */
   2813 	map = isl_map_read_from_str(ctx,
   2814 		"[n] -> { [i,j] -> [i2,j2] : i2 = i + 3 and j2 = j and "
   2815 			"i <= 2 j - 4 and i <= n - 3 and j <= 2 i - 1 and "
   2816 			"j <= n or "
   2817 			"i2 = i and j2 = j + 3 and i <= 2 j - 1 and i <= n and "
   2818 			"j <= 2 i - 4 and j <= n - 3 or "
   2819 			"i2 = i + 1 and j2 = j + 1 and i <= 2 j - 1 and "
   2820 			"i <= n - 1 and j <= 2 i - 1 and j <= n - 1 }");
   2821 	map = isl_map_power(map, &exact);
   2822 	assert(exact);
   2823 	isl_map_free(map);
   2824 
   2825 	/* COCOA Fig.2 right */
   2826 	map = isl_map_read_from_str(ctx,
   2827 		"[n] -> { [i,j] -> [i2,j2] : i2 = i + 3 and j2 = j and "
   2828 			"i <= 2 j - 4 and i <= n - 3 and j <= 2 i - 1 and "
   2829 			"j <= n or "
   2830 			"i2 = i and j2 = j + 3 and i <= 2 j - 1 and i <= n and "
   2831 			"j <= 2 i - 4 and j <= n - 3 or "
   2832 			"i2 = i + 1 and j2 = j + 1 and i <= 2 j - 1 and "
   2833 			"i <= n - 1 and j <= 2 i - 1 and j <= n - 1 }");
   2834 	map = isl_map_transitive_closure(map, &exact);
   2835 	assert(exact);
   2836 	map2 = isl_map_read_from_str(ctx,
   2837 		"[n] -> { [i,j] -> [i2,j2] : exists (k1,k2,k3,k : "
   2838 			"i <= 2 j - 1 and i <= n and j <= 2 i - 1 and "
   2839 			"j <= n and 3 + i + 2 j <= 3 n and "
   2840 			"3 + 2 i + j <= 3n and i2 <= 2 j2 -1 and i2 <= n and "
   2841 			"i2 <= 3 j2 - 4 and j2 <= 2 i2 -1 and j2 <= n and "
   2842 			"13 + 4 j2 <= 11 i2 and i2 = i + 3 k1 + k3 and "
   2843 			"j2 = j + 3 k2 + k3 and k1 >= 0 and k2 >= 0 and "
   2844 			"k3 >= 0 and k1 + k2 + k3 = k and k > 0) }");
   2845 	assert(isl_map_is_equal(map, map2));
   2846 	isl_map_free(map2);
   2847 	isl_map_free(map);
   2848 
   2849 	map = cocoa_fig_1_right_graph(ctx);
   2850 	map = isl_map_transitive_closure(map, &exact);
   2851 	assert(exact);
   2852 	map2 = cocoa_fig_1_right_tc(ctx);
   2853 	assert(isl_map_is_equal(map, map2));
   2854 	isl_map_free(map2);
   2855 	isl_map_free(map);
   2856 
   2857 	map = cocoa_fig_1_right_graph(ctx);
   2858 	map = isl_map_power(map, &exact);
   2859 	map2 = cocoa_fig_1_right_power(ctx);
   2860 	equal = isl_map_is_equal(map, map2);
   2861 	isl_map_free(map2);
   2862 	isl_map_free(map);
   2863 	if (equal < 0)
   2864 		return -1;
   2865 	if (!exact)
   2866 		isl_die(ctx, isl_error_unknown, "power not exact", return -1);
   2867 	if (!equal)
   2868 		isl_die(ctx, isl_error_unknown, "unexpected power", return -1);
   2869 
   2870 	/* COCOA Theorem 1 counter example */
   2871 	map = isl_map_read_from_str(ctx,
   2872 		"{ [i,j] -> [i2,j2] : i = 0 and 0 <= j and j <= 1 and "
   2873 			"i2 = 1 and j2 = j or "
   2874 			"i = 0 and j = 0 and i2 = 0 and j2 = 1 }");
   2875 	map = isl_map_transitive_closure(map, &exact);
   2876 	assert(exact);
   2877 	isl_map_free(map);
   2878 
   2879 	map = isl_map_read_from_str(ctx,
   2880 		"[m,n] -> { [i,j] -> [i2,j2] : i2 = i and j2 = j + 2 and "
   2881 			"1 <= i,i2 <= n and 1 <= j,j2 <= m or "
   2882 			"i2 = i + 1 and 3 <= j2 - j <= 4 and "
   2883 			"1 <= i,i2 <= n and 1 <= j,j2 <= m }");
   2884 	map = isl_map_transitive_closure(map, &exact);
   2885 	assert(exact);
   2886 	isl_map_free(map);
   2887 
   2888 	/* Kelly et al 1996, fig 12 */
   2889 	map = isl_map_read_from_str(ctx,
   2890 		"[n] -> { [i,j] -> [i2,j2] : i2 = i and j2 = j + 1 and "
   2891 			"1 <= i,j,j+1 <= n or "
   2892 			"j = n and j2 = 1 and i2 = i + 1 and "
   2893 			"1 <= i,i+1 <= n }");
   2894 	map = isl_map_transitive_closure(map, &exact);
   2895 	assert(exact);
   2896 	map2 = isl_map_read_from_str(ctx,
   2897 		"[n] -> { [i,j] -> [i2,j2] : 1 <= j < j2 <= n and "
   2898 			"1 <= i <= n and i = i2 or "
   2899 			"1 <= i < i2 <= n and 1 <= j <= n and "
   2900 			"1 <= j2 <= n }");
   2901 	assert(isl_map_is_equal(map, map2));
   2902 	isl_map_free(map2);
   2903 	isl_map_free(map);
   2904 
   2905 	/* Omega's closure4 */
   2906 	map = isl_map_read_from_str(ctx,
   2907 		"[m,n] -> { [x,y] -> [x2,y2] : x2 = x and y2 = y + 1 and "
   2908 			"1 <= x,y <= 10 or "
   2909 			"x2 = x + 1 and y2 = y and "
   2910 			"1 <= x <= 20 && 5 <= y <= 15 }");
   2911 	map = isl_map_transitive_closure(map, &exact);
   2912 	assert(exact);
   2913 	isl_map_free(map);
   2914 
   2915 	map = isl_map_read_from_str(ctx,
   2916 		"[n] -> { [x] -> [y]: 1 <= n <= y - x <= 10 }");
   2917 	map = isl_map_transitive_closure(map, &exact);
   2918 	assert(!exact);
   2919 	map2 = isl_map_read_from_str(ctx,
   2920 		"[n] -> { [x] -> [y] : 1 <= n <= 10 and y >= n + x }");
   2921 	assert(isl_map_is_equal(map, map2));
   2922 	isl_map_free(map);
   2923 	isl_map_free(map2);
   2924 
   2925 	str = "[n, m] -> { [i0, i1, i2, i3] -> [o0, o1, o2, o3] : "
   2926 	    "i3 = 1 and o0 = i0 and o1 = -1 + i1 and o2 = -1 + i2 and "
   2927 	    "o3 = -2 + i2 and i1 <= -1 + i0 and i1 >= 1 - m + i0 and "
   2928 	    "i1 >= 2 and i1 <= n and i2 >= 3 and i2 <= 1 + n and i2 <= m }";
   2929 	map = isl_map_read_from_str(ctx, str);
   2930 	map = isl_map_transitive_closure(map, &exact);
   2931 	assert(exact);
   2932 	map2 = isl_map_read_from_str(ctx, str);
   2933 	assert(isl_map_is_equal(map, map2));
   2934 	isl_map_free(map);
   2935 	isl_map_free(map2);
   2936 
   2937 	str = "{[0] -> [1]; [2] -> [3]}";
   2938 	map = isl_map_read_from_str(ctx, str);
   2939 	map = isl_map_transitive_closure(map, &exact);
   2940 	assert(exact);
   2941 	map2 = isl_map_read_from_str(ctx, str);
   2942 	assert(isl_map_is_equal(map, map2));
   2943 	isl_map_free(map);
   2944 	isl_map_free(map2);
   2945 
   2946 	str = "[n] -> { [[i0, i1, 1, 0, i0] -> [i5, 1]] -> "
   2947 	    "[[i0, -1 + i1, 2, 0, i0] -> [-1 + i5, 2]] : "
   2948 	    "exists (e0 = [(3 - n)/3]: i5 >= 2 and i1 >= 2 and "
   2949 	    "3i0 <= -1 + n and i1 <= -1 + n and i5 <= -1 + n and "
   2950 	    "3e0 >= 1 - n and 3e0 <= 2 - n and 3i0 >= -2 + n); "
   2951 	    "[[i0, i1, 2, 0, i0] -> [i5, 1]] -> "
   2952 	    "[[i0, i1, 1, 0, i0] -> [-1 + i5, 2]] : "
   2953 	    "exists (e0 = [(3 - n)/3]: i5 >= 2 and i1 >= 1 and "
   2954 	    "3i0 <= -1 + n and i1 <= -1 + n and i5 <= -1 + n and "
   2955 	    "3e0 >= 1 - n and 3e0 <= 2 - n and 3i0 >= -2 + n); "
   2956 	    "[[i0, i1, 1, 0, i0] -> [i5, 2]] -> "
   2957 	    "[[i0, -1 + i1, 2, 0, i0] -> [i5, 1]] : "
   2958 	    "exists (e0 = [(3 - n)/3]: i1 >= 2 and i5 >= 1 and "
   2959 	    "3i0 <= -1 + n and i1 <= -1 + n and i5 <= -1 + n and "
   2960 	    "3e0 >= 1 - n and 3e0 <= 2 - n and 3i0 >= -2 + n); "
   2961 	    "[[i0, i1, 2, 0, i0] -> [i5, 2]] -> "
   2962 	    "[[i0, i1, 1, 0, i0] -> [i5, 1]] : "
   2963 	    "exists (e0 = [(3 - n)/3]: i5 >= 1 and i1 >= 1 and "
   2964 	    "3i0 <= -1 + n and i1 <= -1 + n and i5 <= -1 + n and "
   2965 	    "3e0 >= 1 - n and 3e0 <= 2 - n and 3i0 >= -2 + n) }";
   2966 	map = isl_map_read_from_str(ctx, str);
   2967 	map = isl_map_transitive_closure(map, NULL);
   2968 	assert(map);
   2969 	isl_map_free(map);
   2970 
   2971 	return 0;
   2972 }
   2973 
   2974 /* Check that the actual result of a boolean operation is equal
   2975  * to the expected result.
   2976  */
   2977 static isl_stat check_bool(isl_ctx *ctx, isl_bool actual, isl_bool expected)
   2978 {
   2979 	if (actual != expected)
   2980 		isl_die(ctx, isl_error_unknown,
   2981 			"incorrect boolean operation", return isl_stat_error);
   2982 	return isl_stat_ok;
   2983 }
   2984 
   2985 /* Test operations on isl_bool values.
   2986  *
   2987  * This tests:
   2988  *
   2989  * 	isl_bool_not
   2990  * 	isl_bool_ok
   2991  */
   2992 static int test_isl_bool(isl_ctx *ctx)
   2993 {
   2994 	if (check_bool(ctx, isl_bool_not(isl_bool_true), isl_bool_false) < 0)
   2995 		return -1;
   2996 	if (check_bool(ctx, isl_bool_not(isl_bool_false), isl_bool_true) < 0)
   2997 		return -1;
   2998 	if (check_bool(ctx, isl_bool_not(isl_bool_error), isl_bool_error) < 0)
   2999 		return -1;
   3000 	if (check_bool(ctx, isl_bool_ok(0), isl_bool_false) < 0)
   3001 		return -1;
   3002 	if (check_bool(ctx, isl_bool_ok(1), isl_bool_true) < 0)
   3003 		return -1;
   3004 	if (check_bool(ctx, isl_bool_ok(-1), isl_bool_true) < 0)
   3005 		return -1;
   3006 	if (check_bool(ctx, isl_bool_ok(2), isl_bool_true) < 0)
   3007 		return -1;
   3008 	if (check_bool(ctx, isl_bool_ok(-2), isl_bool_true) < 0)
   3009 		return -1;
   3010 
   3011 	return 0;
   3012 }
   3013 
   3014 static int test_lex(struct isl_ctx *ctx)
   3015 {
   3016 	isl_space *space;
   3017 	isl_map *map;
   3018 	int empty;
   3019 
   3020 	space = isl_space_set_alloc(ctx, 0, 0);
   3021 	map = isl_map_lex_le(space);
   3022 	empty = isl_map_is_empty(map);
   3023 	isl_map_free(map);
   3024 
   3025 	if (empty < 0)
   3026 		return -1;
   3027 	if (empty)
   3028 		isl_die(ctx, isl_error_unknown,
   3029 			"expecting non-empty result", return -1);
   3030 
   3031 	return 0;
   3032 }
   3033 
   3034 /* Inputs for isl_map_lexmin tests.
   3035  * "map" is the input and "lexmin" is the expected result.
   3036  */
   3037 struct {
   3038 	const char *map;
   3039 	const char *lexmin;
   3040 } lexmin_tests [] = {
   3041 	{ "{ [x] -> [y] : x <= y <= 10; [x] -> [5] : -8 <= x <= 8 }",
   3042 	  "{ [x] -> [5] : 6 <= x <= 8; "
   3043 	    "[x] -> [x] : x <= 5 or (9 <= x <= 10) }" },
   3044 	{ "{ [x] -> [y] : 4y = x or 4y = -1 + x or 4y = -2 + x }",
   3045 	  "{ [x] -> [y] : 4y = x or 4y = -1 + x or 4y = -2 + x }" },
   3046 	{ "{ [x] -> [y] : x = 4y; [x] -> [y] : x = 2y }",
   3047 	  "{ [x] -> [y] : (4y = x and x >= 0) or "
   3048 		"(exists (e0 = [(x)/4], e1 = [(-2 + x)/4]: 2y = x and "
   3049 		"4e1 = -2 + x and 4e0 <= -1 + x and 4e0 >= -3 + x)) or "
   3050 		"(exists (e0 = [(x)/4]: 2y = x and 4e0 = x and x <= -4)) }" },
   3051 	{ "{ T[a] -> S[b, c] : a = 4b-2c and c >= b }",
   3052 	  "{ T[a] -> S[b, c] : 2b = a and 2c = a }" },
   3053 	/* Check that empty pieces are properly combined. */
   3054 	{ "[K, N] -> { [x, y] -> [a, b] : K+2<=N<=K+4 and x>=4 and "
   3055 		"2N-6<=x<K+N and N-1<=a<=K+N-1 and N+b-6<=a<=2N-4 and "
   3056 		"b<=2N-3K+a and 3b<=4N-K+1 and b>=N and a>=x+1 }",
   3057 	  "[K, N] -> { [x, y] -> [1 + x, N] : x >= -6 + 2N and "
   3058 		"x <= -5 + 2N and x >= -1 + 3K - N and x <= -2 + K + N and "
   3059 		"x >= 4 }" },
   3060 	{ "{ [i, k, j] -> [a, b, c, d] : 8*floor((b)/8) = b and k <= 255 and "
   3061 		"a <= 255 and c <= 255 and d <= 255 - j and "
   3062 		"255 - j <= 7d <= 7 - i and 240d <= 239 + a and "
   3063 		"247d <= 247 + k - j and 247d <= 247 + k - b and "
   3064 		"247d <= 247 + i and 248 - b <= 248d <= c and "
   3065 		"254d >= i - a + b and 254d >= -a + b and "
   3066 		"255d >= -i + a - b and 1792d >= -63736 + 257b }",
   3067 	  "{ [i, k, j] -> "
   3068 	    "[-127762 + i + 502j, -62992 + 248j, 63240 - 248j, 255 - j] : "
   3069 		"k <= 255 and 7j >= 1778 + i and 246j >= 62738 - k and "
   3070 		"247j >= 62738 - i and 509j <= 129795 + i and "
   3071 		"742j >= 188724 - i; "
   3072 	    "[0, k, j] -> [1, 0, 248, 1] : k <= 255 and 248 <= j <= 254, k }" },
   3073 	{ "{ [a] -> [b] : 0 <= b <= 255 and -509 + a <= 512b < a and "
   3074 			"16*floor((8 + b)/16) <= 7 + b; "
   3075 	    "[a] -> [1] }",
   3076 	  "{ [a] -> [b = 1] : a >= 510 or a <= 0; "
   3077 	    "[a] -> [b = 0] : 0 < a <= 509 }" },
   3078 	{ "{ rat: [i] : 1 <= 2i <= 9 }", "{ rat: [i] : 2i = 1 }" },
   3079 	{ "{ rat: [i] : 1 <= 2i <= 9 or i >= 10 }", "{ rat: [i] : 2i = 1 }" },
   3080 	{ "{ rat: [i] : 21 <= 2i <= 29 or i = 5 }", "{ rat: [5] }" },
   3081 };
   3082 
   3083 static int test_lexmin(struct isl_ctx *ctx)
   3084 {
   3085 	int i;
   3086 	int equal;
   3087 	const char *str;
   3088 	isl_basic_map *bmap;
   3089 	isl_map *map, *map2;
   3090 	isl_set *set;
   3091 	isl_set *set2;
   3092 	isl_pw_multi_aff *pma;
   3093 
   3094 	str = "[p0, p1] -> { [] -> [] : "
   3095 	    "exists (e0 = [(2p1)/3], e1, e2, e3 = [(3 - p1 + 3e0)/3], "
   3096 	    "e4 = [(p1)/3], e5 = [(p1 + 3e4)/3]: "
   3097 	    "3e0 >= -2 + 2p1 and 3e0 >= p1 and 3e3 >= 1 - p1 + 3e0 and "
   3098 	    "3e0 <= 2p1 and 3e3 >= -2 + p1 and 3e3 <= -1 + p1 and p1 >= 3 and "
   3099 	    "3e5 >= -2 + 2p1 and 3e5 >= p1 and 3e5 <= -1 + p1 + 3e4 and "
   3100 	    "3e4 <= p1 and 3e4 >= -2 + p1 and e3 <= -1 + e0 and "
   3101 	    "3e4 >= 6 - p1 + 3e1 and 3e1 >= p1 and 3e5 >= -2 + p1 + 3e4 and "
   3102 	    "2e4 >= 3 - p1 + 2e1 and e4 <= e1 and 3e3 <= 2 - p1 + 3e0 and "
   3103 	    "e5 >= 1 + e1 and 3e4 >= 6 - 2p1 + 3e1 and "
   3104 	    "p0 >= 2 and p1 >= p0 and 3e2 >= p1 and 3e4 >= 6 - p1 + 3e2 and "
   3105 	    "e2 <= e1 and e3 >= 1 and e4 <= e2) }";
   3106 	map = isl_map_read_from_str(ctx, str);
   3107 	map = isl_map_lexmin(map);
   3108 	isl_map_free(map);
   3109 	if (!map)
   3110 		return -1;
   3111 
   3112 	str = "[C] -> { [obj,a,b,c] : obj <= 38 a + 7 b + 10 c and "
   3113 	    "a + b <= 1 and c <= 10 b and c <= C and a,b,c,C >= 0 }";
   3114 	set = isl_set_read_from_str(ctx, str);
   3115 	set = isl_set_lexmax(set);
   3116 	str = "[C] -> { [obj,a,b,c] : C = 8 }";
   3117 	set2 = isl_set_read_from_str(ctx, str);
   3118 	set = isl_set_intersect(set, set2);
   3119 	assert(!isl_set_is_empty(set));
   3120 	isl_set_free(set);
   3121 
   3122 	for (i = 0; i < ARRAY_SIZE(lexmin_tests); ++i) {
   3123 		map = isl_map_read_from_str(ctx, lexmin_tests[i].map);
   3124 		map = isl_map_lexmin(map);
   3125 		map2 = isl_map_read_from_str(ctx, lexmin_tests[i].lexmin);
   3126 		equal = isl_map_is_equal(map, map2);
   3127 		isl_map_free(map);
   3128 		isl_map_free(map2);
   3129 
   3130 		if (equal < 0)
   3131 			return -1;
   3132 		if (!equal)
   3133 			isl_die(ctx, isl_error_unknown,
   3134 				"unexpected result", return -1);
   3135 	}
   3136 
   3137 	str = "{ [i] -> [i', j] : j = i - 8i' and i' >= 0 and i' <= 7 and "
   3138 				" 8i' <= i and 8i' >= -7 + i }";
   3139 	bmap = isl_basic_map_read_from_str(ctx, str);
   3140 	pma = isl_basic_map_lexmin_pw_multi_aff(isl_basic_map_copy(bmap));
   3141 	map2 = isl_map_from_pw_multi_aff(pma);
   3142 	map = isl_map_from_basic_map(bmap);
   3143 	assert(isl_map_is_equal(map, map2));
   3144 	isl_map_free(map);
   3145 	isl_map_free(map2);
   3146 
   3147 	str = "[i] -> { [i', j] : j = i - 8i' and i' >= 0 and i' <= 7 and "
   3148 				" 8i' <= i and 8i' >= -7 + i }";
   3149 	set = isl_set_read_from_str(ctx, str);
   3150 	pma = isl_set_lexmin_pw_multi_aff(isl_set_copy(set));
   3151 	set2 = isl_set_from_pw_multi_aff(pma);
   3152 	equal = isl_set_is_equal(set, set2);
   3153 	isl_set_free(set);
   3154 	isl_set_free(set2);
   3155 	if (equal < 0)
   3156 		return -1;
   3157 	if (!equal)
   3158 		isl_die(ctx, isl_error_unknown,
   3159 			"unexpected difference between set and "
   3160 			"piecewise affine expression", return -1);
   3161 
   3162 	return 0;
   3163 }
   3164 
   3165 /* Inputs for isl_pw_multi_aff_max_multi_val tests.
   3166  * "pma" is the input.
   3167  * "res" is the expected result.
   3168  */
   3169 static struct {
   3170 	const char *pma;
   3171 	const char *res;
   3172 } opt_pw_tests[] = {
   3173 	{ "{ [-1] -> [-1]; [1] -> [1] }", "{ [1] }" },
   3174 	{ "{ [a, b] -> [floor((b - 2*floor((-a)/4))/5)] : "
   3175 	    "0 <= a, b <= 100 and b mod 2 = 0}", "{ [30] }" },
   3176 	{ "[N] -> { [i,j] -> A[i, -i, i + j] : 0 <= i,j <= N <= 10 }",
   3177 	  "{ A[10, 0, 20] }" },
   3178 	{ "[N] -> {A[N, -N, 2N] : 0 <= N }", "{ A[infty, 0, infty] }" },
   3179 };
   3180 
   3181 /* Perform basic isl_pw_multi_aff_max_multi_val tests.
   3182  */
   3183 static isl_stat test_pw_max(struct isl_ctx *ctx)
   3184 {
   3185 	int i;
   3186 	isl_pw_multi_aff *pma;
   3187 	isl_multi_val *mv;
   3188 	isl_stat r;
   3189 
   3190 	for (i = 0; i < ARRAY_SIZE(opt_pw_tests); ++i) {
   3191 		pma = isl_pw_multi_aff_read_from_str(ctx, opt_pw_tests[i].pma);
   3192 		mv = isl_pw_multi_aff_max_multi_val(pma);
   3193 		r = multi_val_check_plain_equal(mv, opt_pw_tests[i].res);
   3194 		isl_multi_val_free(mv);
   3195 
   3196 		if (r < 0)
   3197 			return isl_stat_error;
   3198 	}
   3199 
   3200 	return isl_stat_ok;
   3201 }
   3202 
   3203 /* A specialized isl_set_min_val test case that would return the wrong result
   3204  * in earlier versions of isl.
   3205  * The explicit call to isl_basic_set_union prevents the second basic set
   3206  * from being determined to be empty prior to the call to isl_set_min_val,
   3207  * at least at the point where this test case was introduced.
   3208  */
   3209 static int test_min_special(isl_ctx *ctx)
   3210 {
   3211 	const char *str;
   3212 	isl_basic_set *bset1, *bset2;
   3213 	isl_set *set;
   3214 	isl_aff *obj;
   3215 	isl_val *res;
   3216 	int ok;
   3217 
   3218 	str = "{ [a, b] : a >= 2 and b >= 0 and 14 - a <= b <= 9 }";
   3219 	bset1 = isl_basic_set_read_from_str(ctx, str);
   3220 	str = "{ [a, b] : 1 <= a, b and a + b <= 1 }";
   3221 	bset2 = isl_basic_set_read_from_str(ctx, str);
   3222 	set = isl_basic_set_union(bset1, bset2);
   3223 	obj = isl_aff_read_from_str(ctx, "{ [a, b] -> [a] }");
   3224 
   3225 	res = isl_set_min_val(set, obj);
   3226 	ok = isl_val_cmp_si(res, 5) == 0;
   3227 
   3228 	isl_aff_free(obj);
   3229 	isl_set_free(set);
   3230 	isl_val_free(res);
   3231 
   3232 	if (!res)
   3233 		return -1;
   3234 	if (!ok)
   3235 		isl_die(ctx, isl_error_unknown, "unexpected minimum",
   3236 			return -1);
   3237 
   3238 	return 0;
   3239 }
   3240 
   3241 /* A specialized isl_set_min_val test case that would return an error
   3242  * in earlier versions of isl.
   3243  */
   3244 static int test_min_special2(isl_ctx *ctx)
   3245 {
   3246 	const char *str;
   3247 	isl_basic_set *bset;
   3248 	isl_aff *obj;
   3249 	isl_val *res;
   3250 
   3251 	str = "{ [i, j, k] : 2j = i and 2k = i + 1 and i >= 2 }";
   3252 	bset = isl_basic_set_read_from_str(ctx, str);
   3253 
   3254 	obj = isl_aff_read_from_str(ctx, "{ [i, j, k] -> [i] }");
   3255 
   3256 	res = isl_basic_set_max_val(bset, obj);
   3257 
   3258 	isl_basic_set_free(bset);
   3259 	isl_aff_free(obj);
   3260 	isl_val_free(res);
   3261 
   3262 	if (!res)
   3263 		return -1;
   3264 
   3265 	return 0;
   3266 }
   3267 
   3268 /* Check that the result of isl_set_min_multi_pw_aff
   3269  * on the union of the sets with string descriptions "s1" and "s2"
   3270  * consists of a single expression (on a single cell).
   3271  */
   3272 static isl_stat check_single_expr_min(isl_ctx *ctx, const char *s1,
   3273 	const char *s2)
   3274 {
   3275 	isl_size n;
   3276 	isl_set *set1, *set2;
   3277 	isl_multi_pw_aff *mpa;
   3278 	isl_pw_multi_aff *pma;
   3279 
   3280 	set1 = isl_set_read_from_str(ctx, s1);
   3281 	set2 = isl_set_read_from_str(ctx, s2);
   3282 	set1 = isl_set_union(set1, set2);
   3283 	mpa = isl_set_min_multi_pw_aff(set1);
   3284 	pma = isl_pw_multi_aff_from_multi_pw_aff(mpa);
   3285 	n = isl_pw_multi_aff_n_piece(pma);
   3286 	isl_pw_multi_aff_free(pma);
   3287 
   3288 	if (n < 0)
   3289 		return isl_stat_error;
   3290 	if (n != 1)
   3291 		isl_die(ctx, isl_error_unknown, "expecting single expression",
   3292 			return isl_stat_error);
   3293 	return isl_stat_ok;
   3294 }
   3295 
   3296 /* A specialized isl_set_min_multi_pw_aff test that checks
   3297  * that the minimum of 2N and 3N for N >= 0 is represented
   3298  * by a single expression, without splitting off the special case N = 0.
   3299  * Do this for both orderings.
   3300  */
   3301 static int test_min_mpa(isl_ctx *ctx)
   3302 {
   3303 	const char *s1, *s2;
   3304 
   3305 	s1 = "[N=0:] -> { [1, 3N:] }";
   3306 	s2 = "[N=0:] -> { [10, 2N:] }";
   3307 	if (check_single_expr_min(ctx, s1, s2) < 0)
   3308 		return -1;
   3309 	if (check_single_expr_min(ctx, s2, s1) < 0)
   3310 		return -1;
   3311 
   3312 	return 0;
   3313 }
   3314 
   3315 struct {
   3316 	const char *set;
   3317 	const char *obj;
   3318 	__isl_give isl_val *(*fn)(__isl_keep isl_set *set,
   3319 		__isl_keep isl_aff *obj);
   3320 	const char *res;
   3321 } opt_tests[] = {
   3322 	{ "{ [-1]; [1] }", "{ [x] -> [x] }", &isl_set_min_val, "-1" },
   3323 	{ "{ [-1]; [1] }", "{ [x] -> [x] }", &isl_set_max_val, "1" },
   3324 	{ "{ [a, b] : 0 <= a, b <= 100 and b mod 2 = 0}",
   3325 	  "{ [a, b] -> [floor((b - 2*floor((-a)/4))/5)] }",
   3326 	  &isl_set_max_val, "30" },
   3327 
   3328 };
   3329 
   3330 /* Perform basic isl_set_min_val and isl_set_max_val tests.
   3331  * In particular, check the results on non-convex inputs.
   3332  */
   3333 static int test_min(struct isl_ctx *ctx)
   3334 {
   3335 	int i;
   3336 	isl_set *set;
   3337 	isl_aff *obj;
   3338 	isl_val *val, *res;
   3339 	isl_bool ok;
   3340 
   3341 	for (i = 0; i < ARRAY_SIZE(opt_tests); ++i) {
   3342 		set = isl_set_read_from_str(ctx, opt_tests[i].set);
   3343 		obj = isl_aff_read_from_str(ctx, opt_tests[i].obj);
   3344 		res = isl_val_read_from_str(ctx, opt_tests[i].res);
   3345 		val = opt_tests[i].fn(set, obj);
   3346 		ok = isl_val_eq(res, val);
   3347 		isl_val_free(res);
   3348 		isl_val_free(val);
   3349 		isl_aff_free(obj);
   3350 		isl_set_free(set);
   3351 
   3352 		if (ok < 0)
   3353 			return -1;
   3354 		if (!ok)
   3355 			isl_die(ctx, isl_error_unknown,
   3356 				"unexpected optimum", return -1);
   3357 	}
   3358 
   3359 	if (test_pw_max(ctx) < 0)
   3360 		return -1;
   3361 	if (test_min_special(ctx) < 0)
   3362 		return -1;
   3363 	if (test_min_special2(ctx) < 0)
   3364 		return -1;
   3365 
   3366 	return 0;
   3367 }
   3368 
   3369 struct must_may {
   3370 	isl_map *must;
   3371 	isl_map *may;
   3372 };
   3373 
   3374 static isl_stat collect_must_may(__isl_take isl_map *dep, int must,
   3375 	void *dep_user, void *user)
   3376 {
   3377 	struct must_may *mm = (struct must_may *)user;
   3378 
   3379 	if (must)
   3380 		mm->must = isl_map_union(mm->must, dep);
   3381 	else
   3382 		mm->may = isl_map_union(mm->may, dep);
   3383 
   3384 	return isl_stat_ok;
   3385 }
   3386 
   3387 static int common_space(void *first, void *second)
   3388 {
   3389 	int depth = *(int *)first;
   3390 	return 2 * depth;
   3391 }
   3392 
   3393 static int map_is_equal(__isl_keep isl_map *map, const char *str)
   3394 {
   3395 	isl_map *map2;
   3396 	int equal;
   3397 
   3398 	if (!map)
   3399 		return -1;
   3400 
   3401 	map2 = isl_map_read_from_str(map->ctx, str);
   3402 	equal = isl_map_is_equal(map, map2);
   3403 	isl_map_free(map2);
   3404 
   3405 	return equal;
   3406 }
   3407 
   3408 static int map_check_equal(__isl_keep isl_map *map, const char *str)
   3409 {
   3410 	int equal;
   3411 
   3412 	equal = map_is_equal(map, str);
   3413 	if (equal < 0)
   3414 		return -1;
   3415 	if (!equal)
   3416 		isl_die(isl_map_get_ctx(map), isl_error_unknown,
   3417 			"result not as expected", return -1);
   3418 	return 0;
   3419 }
   3420 
   3421 /* Is "set" equal to the set described by "str"?
   3422  */
   3423 static isl_bool set_is_equal(__isl_keep isl_set *set, const char *str)
   3424 {
   3425 	isl_set *set2;
   3426 	isl_bool equal;
   3427 
   3428 	if (!set)
   3429 		return isl_bool_error;
   3430 
   3431 	set2 = isl_set_read_from_str(isl_set_get_ctx(set), str);
   3432 	equal = isl_set_is_equal(set, set2);
   3433 	isl_set_free(set2);
   3434 
   3435 	return equal;
   3436 }
   3437 
   3438 /* Check that "set" is equal to the set described by "str".
   3439  */
   3440 static isl_stat set_check_equal(__isl_keep isl_set *set, const char *str)
   3441 {
   3442 	isl_bool equal;
   3443 
   3444 	equal = set_is_equal(set, str);
   3445 	if (equal < 0)
   3446 		return isl_stat_error;
   3447 	if (!equal)
   3448 		isl_die(isl_set_get_ctx(set), isl_error_unknown,
   3449 			"result not as expected", return isl_stat_error);
   3450 	return isl_stat_ok;
   3451 }
   3452 
   3453 /* Is "uset" equal to the union set described by "str"?
   3454  */
   3455 static isl_bool uset_is_equal(__isl_keep isl_union_set *uset, const char *str)
   3456 {
   3457 	isl_union_set *uset2;
   3458 	isl_bool equal;
   3459 
   3460 	if (!uset)
   3461 		return isl_bool_error;
   3462 
   3463 	uset2 = isl_union_set_read_from_str(isl_union_set_get_ctx(uset), str);
   3464 	equal = isl_union_set_is_equal(uset, uset2);
   3465 	isl_union_set_free(uset2);
   3466 
   3467 	return equal;
   3468 }
   3469 
   3470 /* Check that "uset" is equal to the union set described by "str".
   3471  */
   3472 static isl_stat uset_check_equal(__isl_keep isl_union_set *uset,
   3473 	const char *str)
   3474 {
   3475 	isl_bool equal;
   3476 
   3477 	equal = uset_is_equal(uset, str);
   3478 	if (equal < 0)
   3479 		return isl_stat_error;
   3480 	if (!equal)
   3481 		isl_die(isl_union_set_get_ctx(uset), isl_error_unknown,
   3482 			"result not as expected", return isl_stat_error);
   3483 	return isl_stat_ok;
   3484 }
   3485 
   3486 static int test_dep(struct isl_ctx *ctx)
   3487 {
   3488 	const char *str;
   3489 	isl_space *space;
   3490 	isl_map *map;
   3491 	isl_access_info *ai;
   3492 	isl_flow *flow;
   3493 	int depth;
   3494 	struct must_may mm;
   3495 
   3496 	depth = 3;
   3497 
   3498 	str = "{ [2,i,0] -> [i] : 0 <= i <= 10 }";
   3499 	map = isl_map_read_from_str(ctx, str);
   3500 	ai = isl_access_info_alloc(map, &depth, &common_space, 2);
   3501 
   3502 	str = "{ [0,i,0] -> [i] : 0 <= i <= 10 }";
   3503 	map = isl_map_read_from_str(ctx, str);
   3504 	ai = isl_access_info_add_source(ai, map, 1, &depth);
   3505 
   3506 	str = "{ [1,i,0] -> [5] : 0 <= i <= 10 }";
   3507 	map = isl_map_read_from_str(ctx, str);
   3508 	ai = isl_access_info_add_source(ai, map, 1, &depth);
   3509 
   3510 	flow = isl_access_info_compute_flow(ai);
   3511 	space = isl_space_alloc(ctx, 0, 3, 3);
   3512 	mm.must = isl_map_empty(isl_space_copy(space));
   3513 	mm.may = isl_map_empty(space);
   3514 
   3515 	isl_flow_foreach(flow, collect_must_may, &mm);
   3516 
   3517 	str = "{ [0,i,0] -> [2,i,0] : (0 <= i <= 4) or (6 <= i <= 10); "
   3518 	      "  [1,10,0] -> [2,5,0] }";
   3519 	assert(map_is_equal(mm.must, str));
   3520 	str = "{ [i,j,k] -> [l,m,n] : 1 = 0 }";
   3521 	assert(map_is_equal(mm.may, str));
   3522 
   3523 	isl_map_free(mm.must);
   3524 	isl_map_free(mm.may);
   3525 	isl_flow_free(flow);
   3526 
   3527 
   3528 	str = "{ [2,i,0] -> [i] : 0 <= i <= 10 }";
   3529 	map = isl_map_read_from_str(ctx, str);
   3530 	ai = isl_access_info_alloc(map, &depth, &common_space, 2);
   3531 
   3532 	str = "{ [0,i,0] -> [i] : 0 <= i <= 10 }";
   3533 	map = isl_map_read_from_str(ctx, str);
   3534 	ai = isl_access_info_add_source(ai, map, 1, &depth);
   3535 
   3536 	str = "{ [1,i,0] -> [5] : 0 <= i <= 10 }";
   3537 	map = isl_map_read_from_str(ctx, str);
   3538 	ai = isl_access_info_add_source(ai, map, 0, &depth);
   3539 
   3540 	flow = isl_access_info_compute_flow(ai);
   3541 	space = isl_space_alloc(ctx, 0, 3, 3);
   3542 	mm.must = isl_map_empty(isl_space_copy(space));
   3543 	mm.may = isl_map_empty(space);
   3544 
   3545 	isl_flow_foreach(flow, collect_must_may, &mm);
   3546 
   3547 	str = "{ [0,i,0] -> [2,i,0] : (0 <= i <= 4) or (6 <= i <= 10) }";
   3548 	assert(map_is_equal(mm.must, str));
   3549 	str = "{ [0,5,0] -> [2,5,0]; [1,i,0] -> [2,5,0] : 0 <= i <= 10 }";
   3550 	assert(map_is_equal(mm.may, str));
   3551 
   3552 	isl_map_free(mm.must);
   3553 	isl_map_free(mm.may);
   3554 	isl_flow_free(flow);
   3555 
   3556 
   3557 	str = "{ [2,i,0] -> [i] : 0 <= i <= 10 }";
   3558 	map = isl_map_read_from_str(ctx, str);
   3559 	ai = isl_access_info_alloc(map, &depth, &common_space, 2);
   3560 
   3561 	str = "{ [0,i,0] -> [i] : 0 <= i <= 10 }";
   3562 	map = isl_map_read_from_str(ctx, str);
   3563 	ai = isl_access_info_add_source(ai, map, 0, &depth);
   3564 
   3565 	str = "{ [1,i,0] -> [5] : 0 <= i <= 10 }";
   3566 	map = isl_map_read_from_str(ctx, str);
   3567 	ai = isl_access_info_add_source(ai, map, 0, &depth);
   3568 
   3569 	flow = isl_access_info_compute_flow(ai);
   3570 	space = isl_space_alloc(ctx, 0, 3, 3);
   3571 	mm.must = isl_map_empty(isl_space_copy(space));
   3572 	mm.may = isl_map_empty(space);
   3573 
   3574 	isl_flow_foreach(flow, collect_must_may, &mm);
   3575 
   3576 	str = "{ [0,i,0] -> [2,i,0] : 0 <= i <= 10; "
   3577 	      "  [1,i,0] -> [2,5,0] : 0 <= i <= 10 }";
   3578 	assert(map_is_equal(mm.may, str));
   3579 	str = "{ [i,j,k] -> [l,m,n] : 1 = 0 }";
   3580 	assert(map_is_equal(mm.must, str));
   3581 
   3582 	isl_map_free(mm.must);
   3583 	isl_map_free(mm.may);
   3584 	isl_flow_free(flow);
   3585 
   3586 
   3587 	str = "{ [0,i,2] -> [i] : 0 <= i <= 10 }";
   3588 	map = isl_map_read_from_str(ctx, str);
   3589 	ai = isl_access_info_alloc(map, &depth, &common_space, 2);
   3590 
   3591 	str = "{ [0,i,0] -> [i] : 0 <= i <= 10 }";
   3592 	map = isl_map_read_from_str(ctx, str);
   3593 	ai = isl_access_info_add_source(ai, map, 0, &depth);
   3594 
   3595 	str = "{ [0,i,1] -> [5] : 0 <= i <= 10 }";
   3596 	map = isl_map_read_from_str(ctx, str);
   3597 	ai = isl_access_info_add_source(ai, map, 0, &depth);
   3598 
   3599 	flow = isl_access_info_compute_flow(ai);
   3600 	space = isl_space_alloc(ctx, 0, 3, 3);
   3601 	mm.must = isl_map_empty(isl_space_copy(space));
   3602 	mm.may = isl_map_empty(space);
   3603 
   3604 	isl_flow_foreach(flow, collect_must_may, &mm);
   3605 
   3606 	str = "{ [0,i,0] -> [0,i,2] : 0 <= i <= 10; "
   3607 	      "  [0,i,1] -> [0,5,2] : 0 <= i <= 5 }";
   3608 	assert(map_is_equal(mm.may, str));
   3609 	str = "{ [i,j,k] -> [l,m,n] : 1 = 0 }";
   3610 	assert(map_is_equal(mm.must, str));
   3611 
   3612 	isl_map_free(mm.must);
   3613 	isl_map_free(mm.may);
   3614 	isl_flow_free(flow);
   3615 
   3616 
   3617 	str = "{ [0,i,1] -> [i] : 0 <= i <= 10 }";
   3618 	map = isl_map_read_from_str(ctx, str);
   3619 	ai = isl_access_info_alloc(map, &depth, &common_space, 2);
   3620 
   3621 	str = "{ [0,i,0] -> [i] : 0 <= i <= 10 }";
   3622 	map = isl_map_read_from_str(ctx, str);
   3623 	ai = isl_access_info_add_source(ai, map, 0, &depth);
   3624 
   3625 	str = "{ [0,i,2] -> [5] : 0 <= i <= 10 }";
   3626 	map = isl_map_read_from_str(ctx, str);
   3627 	ai = isl_access_info_add_source(ai, map, 0, &depth);
   3628 
   3629 	flow = isl_access_info_compute_flow(ai);
   3630 	space = isl_space_alloc(ctx, 0, 3, 3);
   3631 	mm.must = isl_map_empty(isl_space_copy(space));
   3632 	mm.may = isl_map_empty(space);
   3633 
   3634 	isl_flow_foreach(flow, collect_must_may, &mm);
   3635 
   3636 	str = "{ [0,i,0] -> [0,i,1] : 0 <= i <= 10; "
   3637 	      "  [0,i,2] -> [0,5,1] : 0 <= i <= 4 }";
   3638 	assert(map_is_equal(mm.may, str));
   3639 	str = "{ [i,j,k] -> [l,m,n] : 1 = 0 }";
   3640 	assert(map_is_equal(mm.must, str));
   3641 
   3642 	isl_map_free(mm.must);
   3643 	isl_map_free(mm.may);
   3644 	isl_flow_free(flow);
   3645 
   3646 
   3647 	depth = 5;
   3648 
   3649 	str = "{ [1,i,0,0,0] -> [i,j] : 0 <= i <= 10 and 0 <= j <= 10 }";
   3650 	map = isl_map_read_from_str(ctx, str);
   3651 	ai = isl_access_info_alloc(map, &depth, &common_space, 1);
   3652 
   3653 	str = "{ [0,i,0,j,0] -> [i,j] : 0 <= i <= 10 and 0 <= j <= 10 }";
   3654 	map = isl_map_read_from_str(ctx, str);
   3655 	ai = isl_access_info_add_source(ai, map, 1, &depth);
   3656 
   3657 	flow = isl_access_info_compute_flow(ai);
   3658 	space = isl_space_alloc(ctx, 0, 5, 5);
   3659 	mm.must = isl_map_empty(isl_space_copy(space));
   3660 	mm.may = isl_map_empty(space);
   3661 
   3662 	isl_flow_foreach(flow, collect_must_may, &mm);
   3663 
   3664 	str = "{ [0,i,0,j,0] -> [1,i,0,0,0] : 0 <= i,j <= 10 }";
   3665 	assert(map_is_equal(mm.must, str));
   3666 	str = "{ [0,0,0,0,0] -> [0,0,0,0,0] : 1 = 0 }";
   3667 	assert(map_is_equal(mm.may, str));
   3668 
   3669 	isl_map_free(mm.must);
   3670 	isl_map_free(mm.may);
   3671 	isl_flow_free(flow);
   3672 
   3673 	return 0;
   3674 }
   3675 
   3676 /* Check that the dependence analysis proceeds without errors.
   3677  * Earlier versions of isl would break down during the analysis
   3678  * due to the use of the wrong spaces.
   3679  */
   3680 static int test_flow(isl_ctx *ctx)
   3681 {
   3682 	const char *str;
   3683 	isl_union_map *access, *schedule;
   3684 	isl_union_map *must_dep, *may_dep;
   3685 	int r;
   3686 
   3687 	str = "{ S0[j] -> i[]; S1[j,i] -> i[]; S2[] -> i[]; S3[] -> i[] }";
   3688 	access = isl_union_map_read_from_str(ctx, str);
   3689 	str = "{ S0[j] -> [0,j,0,0] : 0 <= j < 10; "
   3690 		"S1[j,i] -> [0,j,1,i] : 0 <= j < i < 10; "
   3691 		"S2[] -> [1,0,0,0]; "
   3692 		"S3[] -> [-1,0,0,0] }";
   3693 	schedule = isl_union_map_read_from_str(ctx, str);
   3694 	r = isl_union_map_compute_flow(access, isl_union_map_copy(access),
   3695 					isl_union_map_copy(access), schedule,
   3696 					&must_dep, &may_dep, NULL, NULL);
   3697 	isl_union_map_free(may_dep);
   3698 	isl_union_map_free(must_dep);
   3699 
   3700 	return r;
   3701 }
   3702 
   3703 struct {
   3704 	const char *map;
   3705 	int sv;
   3706 } sv_tests[] = {
   3707 	{ "[N] -> { [i] -> [f] : 0 <= i <= N and 0 <= i - 10 f <= 9 }", 1 },
   3708 	{ "[N] -> { [i] -> [f] : 0 <= i <= N and 0 <= i - 10 f <= 10 }", 0 },
   3709 	{ "{ [i] -> [3*floor(i/2) + 5*floor(i/3)] }", 1 },
   3710 	{ "{ S1[i] -> [i] : 0 <= i <= 9; S2[i] -> [i] : 0 <= i <= 9 }", 1 },
   3711 	{ "{ [i] -> S1[i] : 0 <= i <= 9; [i] -> S2[i] : 0 <= i <= 9 }", 0 },
   3712 	{ "{ A[i] -> [i]; B[i] -> [i]; B[i] -> [i + 1] }", 0 },
   3713 	{ "{ A[i] -> [i]; B[i] -> [i] : i < 0; B[i] -> [i + 1] : i > 0 }", 1 },
   3714 	{ "{ A[i] -> [i]; B[i] -> A[i] : i < 0; B[i] -> [i + 1] : i > 0 }", 1 },
   3715 	{ "{ A[i] -> [i]; B[i] -> [j] : i - 1 <= j <= i }", 0 },
   3716 };
   3717 
   3718 int test_sv(isl_ctx *ctx)
   3719 {
   3720 	isl_union_map *umap;
   3721 	int i;
   3722 	int sv;
   3723 
   3724 	for (i = 0; i < ARRAY_SIZE(sv_tests); ++i) {
   3725 		umap = isl_union_map_read_from_str(ctx, sv_tests[i].map);
   3726 		sv = isl_union_map_is_single_valued(umap);
   3727 		isl_union_map_free(umap);
   3728 		if (sv < 0)
   3729 			return -1;
   3730 		if (sv_tests[i].sv && !sv)
   3731 			isl_die(ctx, isl_error_internal,
   3732 				"map not detected as single valued", return -1);
   3733 		if (!sv_tests[i].sv && sv)
   3734 			isl_die(ctx, isl_error_internal,
   3735 				"map detected as single valued", return -1);
   3736 	}
   3737 
   3738 	return 0;
   3739 }
   3740 
   3741 struct {
   3742 	const char *str;
   3743 	int bijective;
   3744 } bijective_tests[] = {
   3745 	{ "[N,M]->{[i,j] -> [i]}", 0 },
   3746 	{ "[N,M]->{[i,j] -> [i] : j=i}", 1 },
   3747 	{ "[N,M]->{[i,j] -> [i] : j=0}", 1 },
   3748 	{ "[N,M]->{[i,j] -> [i] : j=N}", 1 },
   3749 	{ "[N,M]->{[i,j] -> [j,i]}", 1 },
   3750 	{ "[N,M]->{[i,j] -> [i+j]}", 0 },
   3751 	{ "[N,M]->{[i,j] -> []}", 0 },
   3752 	{ "[N,M]->{[i,j] -> [i,j,N]}", 1 },
   3753 	{ "[N,M]->{[i,j] -> [2i]}", 0 },
   3754 	{ "[N,M]->{[i,j] -> [i,i]}", 0 },
   3755 	{ "[N,M]->{[i,j] -> [2i,i]}", 0 },
   3756 	{ "[N,M]->{[i,j] -> [2i,j]}", 1 },
   3757 	{ "[N,M]->{[i,j] -> [x,y] : 2x=i & y =j}", 1 },
   3758 };
   3759 
   3760 static int test_bijective(struct isl_ctx *ctx)
   3761 {
   3762 	isl_map *map;
   3763 	int i;
   3764 	int bijective;
   3765 
   3766 	for (i = 0; i < ARRAY_SIZE(bijective_tests); ++i) {
   3767 		map = isl_map_read_from_str(ctx, bijective_tests[i].str);
   3768 		bijective = isl_map_is_bijective(map);
   3769 		isl_map_free(map);
   3770 		if (bijective < 0)
   3771 			return -1;
   3772 		if (bijective_tests[i].bijective && !bijective)
   3773 			isl_die(ctx, isl_error_internal,
   3774 				"map not detected as bijective", return -1);
   3775 		if (!bijective_tests[i].bijective && bijective)
   3776 			isl_die(ctx, isl_error_internal,
   3777 				"map detected as bijective", return -1);
   3778 	}
   3779 
   3780 	return 0;
   3781 }
   3782 
   3783 /* Inputs for isl_pw_qpolynomial_gist tests.
   3784  * "pwqp" is the input, "set" is the context and "gist" is the expected result.
   3785  */
   3786 struct {
   3787 	const char *pwqp;
   3788 	const char *set;
   3789 	const char *gist;
   3790 } pwqp_gist_tests[] = {
   3791 	{ "{ [i] -> i }", "{ [k] : exists a : k = 2a }", "{ [i] -> i }" },
   3792 	{ "{ [i] -> i + [ (i + [i/3])/2 ] }", "{ [10] }", "{ [i] -> 16 }" },
   3793 	{ "{ [i] -> ([(i)/2]) }", "{ [k] : exists a : k = 2a+1 }",
   3794 	  "{ [i] -> -1/2 + 1/2 * i }" },
   3795 	{ "{ [i] -> i^2 : i != 0 }", "{ [i] : i != 0 }", "{ [i] -> i^2 }" },
   3796 	{ "{ [i] -> i^2 : i > 0; [i] -> i^2 : i < 0 }", "{ [i] : i != 0 }",
   3797 	  "{ [i] -> i^2 }" },
   3798 };
   3799 
   3800 /* Perform some basic isl_pw_qpolynomial_gist tests.
   3801  */
   3802 static isl_stat test_pwqp_gist(isl_ctx *ctx)
   3803 {
   3804 	int i;
   3805 	const char *str;
   3806 	isl_set *set;
   3807 	isl_pw_qpolynomial *pwqp1, *pwqp2;
   3808 	isl_bool equal;
   3809 
   3810 	for (i = 0; i < ARRAY_SIZE(pwqp_gist_tests); ++i) {
   3811 		str = pwqp_gist_tests[i].pwqp;
   3812 		pwqp1 = isl_pw_qpolynomial_read_from_str(ctx, str);
   3813 		str = pwqp_gist_tests[i].set;
   3814 		set = isl_set_read_from_str(ctx, str);
   3815 		pwqp1 = isl_pw_qpolynomial_gist(pwqp1, set);
   3816 		str = pwqp_gist_tests[i].gist;
   3817 		pwqp2 = isl_pw_qpolynomial_read_from_str(ctx, str);
   3818 		pwqp1 = isl_pw_qpolynomial_sub(pwqp1, pwqp2);
   3819 		equal = isl_pw_qpolynomial_is_zero(pwqp1);
   3820 		isl_pw_qpolynomial_free(pwqp1);
   3821 
   3822 		if (equal < 0)
   3823 			return isl_stat_error;
   3824 		if (!equal)
   3825 			isl_die(ctx, isl_error_unknown,
   3826 				"unexpected result", return isl_stat_error);
   3827 	}
   3828 
   3829 	return isl_stat_ok;
   3830 }
   3831 
   3832 /* Perform a basic isl_pw_qpolynomial_max test.
   3833  */
   3834 static isl_stat test_pwqp_max(isl_ctx *ctx)
   3835 {
   3836 	const char *str;
   3837 	isl_pw_qpolynomial *pwqp;
   3838 	isl_val *v;
   3839 	int ok;
   3840 
   3841 	str = "{ [x=2:9, y] -> floor((x + 1)/4)^3 - floor((2x)/3)^2 }";
   3842 	pwqp = isl_pw_qpolynomial_read_from_str(ctx, str);
   3843 	v = isl_pw_qpolynomial_max(pwqp);
   3844 	ok = isl_val_cmp_si(v, -1) == 0;
   3845 	isl_val_free(v);
   3846 
   3847 	if (!v)
   3848 		return isl_stat_error;
   3849 	if (!ok)
   3850 		isl_die(ctx, isl_error_unknown, "unexpected maximum",
   3851 			return isl_stat_error);
   3852 
   3853 	return isl_stat_ok;
   3854 }
   3855 
   3856 static int test_pwqp(struct isl_ctx *ctx)
   3857 {
   3858 	const char *str;
   3859 	isl_set *set;
   3860 	isl_pw_qpolynomial *pwqp1, *pwqp2;
   3861 	int equal;
   3862 
   3863 	str = "{ [i,j,k] -> 1 + 9 * [i/5] + 7 * [j/11] + 4 * [k/13] }";
   3864 	pwqp1 = isl_pw_qpolynomial_read_from_str(ctx, str);
   3865 
   3866 	pwqp1 = isl_pw_qpolynomial_move_dims(pwqp1, isl_dim_param, 0,
   3867 						isl_dim_in, 1, 1);
   3868 
   3869 	str = "[j] -> { [i,k] -> 1 + 9 * [i/5] + 7 * [j/11] + 4 * [k/13] }";
   3870 	pwqp2 = isl_pw_qpolynomial_read_from_str(ctx, str);
   3871 
   3872 	pwqp1 = isl_pw_qpolynomial_sub(pwqp1, pwqp2);
   3873 
   3874 	assert(isl_pw_qpolynomial_is_zero(pwqp1));
   3875 
   3876 	isl_pw_qpolynomial_free(pwqp1);
   3877 
   3878 	if (test_pwqp_gist(ctx) < 0)
   3879 		return -1;
   3880 
   3881 	str = "{ [i] -> ([([i/2] + [i/2])/5]) }";
   3882 	pwqp1 = isl_pw_qpolynomial_read_from_str(ctx, str);
   3883 	str = "{ [i] -> ([(2 * [i/2])/5]) }";
   3884 	pwqp2 = isl_pw_qpolynomial_read_from_str(ctx, str);
   3885 
   3886 	pwqp1 = isl_pw_qpolynomial_sub(pwqp1, pwqp2);
   3887 
   3888 	assert(isl_pw_qpolynomial_is_zero(pwqp1));
   3889 
   3890 	isl_pw_qpolynomial_free(pwqp1);
   3891 
   3892 	str = "{ [x] -> ([x/2] + [(x+1)/2]) }";
   3893 	pwqp1 = isl_pw_qpolynomial_read_from_str(ctx, str);
   3894 	str = "{ [x] -> x }";
   3895 	pwqp2 = isl_pw_qpolynomial_read_from_str(ctx, str);
   3896 
   3897 	pwqp1 = isl_pw_qpolynomial_sub(pwqp1, pwqp2);
   3898 
   3899 	assert(isl_pw_qpolynomial_is_zero(pwqp1));
   3900 
   3901 	isl_pw_qpolynomial_free(pwqp1);
   3902 
   3903 	str = "{ [i] -> ([i/2]) : i >= 0; [i] -> ([i/3]) : i < 0 }";
   3904 	pwqp1 = isl_pw_qpolynomial_read_from_str(ctx, str);
   3905 	pwqp2 = isl_pw_qpolynomial_read_from_str(ctx, str);
   3906 	pwqp1 = isl_pw_qpolynomial_coalesce(pwqp1);
   3907 	pwqp1 = isl_pw_qpolynomial_sub(pwqp1, pwqp2);
   3908 	assert(isl_pw_qpolynomial_is_zero(pwqp1));
   3909 	isl_pw_qpolynomial_free(pwqp1);
   3910 
   3911 	str = "{ [a,b,a] -> (([(2*[a/3]+b)/5]) * ([(2*[a/3]+b)/5])) }";
   3912 	pwqp2 = isl_pw_qpolynomial_read_from_str(ctx, str);
   3913 	str = "{ [a,b,c] -> (([(2*[a/3]+b)/5]) * ([(2*[c/3]+b)/5])) }";
   3914 	pwqp1 = isl_pw_qpolynomial_read_from_str(ctx, str);
   3915 	set = isl_set_read_from_str(ctx, "{ [a,b,a] }");
   3916 	pwqp1 = isl_pw_qpolynomial_intersect_domain(pwqp1, set);
   3917 	equal = isl_pw_qpolynomial_plain_is_equal(pwqp1, pwqp2);
   3918 	isl_pw_qpolynomial_free(pwqp1);
   3919 	isl_pw_qpolynomial_free(pwqp2);
   3920 	if (equal < 0)
   3921 		return -1;
   3922 	if (!equal)
   3923 		isl_die(ctx, isl_error_unknown, "unexpected result", return -1);
   3924 
   3925 	str = "{ [a,b,c] -> (([(2*[a/3]+1)/5]) * ([(2*[c/3]+1)/5])) : b = 1 }";
   3926 	pwqp2 = isl_pw_qpolynomial_read_from_str(ctx, str);
   3927 	str = "{ [a,b,c] -> (([(2*[a/3]+b)/5]) * ([(2*[c/3]+b)/5])) }";
   3928 	pwqp1 = isl_pw_qpolynomial_read_from_str(ctx, str);
   3929 	pwqp1 = isl_pw_qpolynomial_fix_val(pwqp1, isl_dim_set, 1,
   3930 						isl_val_one(ctx));
   3931 	equal = isl_pw_qpolynomial_plain_is_equal(pwqp1, pwqp2);
   3932 	isl_pw_qpolynomial_free(pwqp1);
   3933 	isl_pw_qpolynomial_free(pwqp2);
   3934 	if (equal < 0)
   3935 		return -1;
   3936 	if (!equal)
   3937 		isl_die(ctx, isl_error_unknown, "unexpected result", return -1);
   3938 
   3939 	if (test_pwqp_max(ctx) < 0)
   3940 		return -1;
   3941 
   3942 	return 0;
   3943 }
   3944 
   3945 static int test_split_periods(isl_ctx *ctx)
   3946 {
   3947 	const char *str;
   3948 	isl_pw_qpolynomial *pwqp;
   3949 
   3950 	str = "{ [U,V] -> 1/3 * U + 2/3 * V - [(U + 2V)/3] + [U/2] : "
   3951 		"U + 2V + 3 >= 0 and - U -2V  >= 0 and - U + 10 >= 0 and "
   3952 		"U  >= 0; [U,V] -> U^2 : U >= 100 }";
   3953 	pwqp = isl_pw_qpolynomial_read_from_str(ctx, str);
   3954 
   3955 	pwqp = isl_pw_qpolynomial_split_periods(pwqp, 2);
   3956 
   3957 	isl_pw_qpolynomial_free(pwqp);
   3958 
   3959 	if (!pwqp)
   3960 		return -1;
   3961 
   3962 	return 0;
   3963 }
   3964 
   3965 static int test_union(isl_ctx *ctx)
   3966 {
   3967 	const char *str;
   3968 	isl_union_set *uset1, *uset2;
   3969 	isl_union_map *umap1, *umap2;
   3970 	int equal;
   3971 
   3972 	str = "{ [i] : 0 <= i <= 1 }";
   3973 	uset1 = isl_union_set_read_from_str(ctx, str);
   3974 	str = "{ [1] -> [0] }";
   3975 	umap1 = isl_union_map_read_from_str(ctx, str);
   3976 
   3977 	umap2 = isl_union_set_lex_gt_union_set(isl_union_set_copy(uset1), uset1);
   3978 	equal = isl_union_map_is_equal(umap1, umap2);
   3979 
   3980 	isl_union_map_free(umap1);
   3981 	isl_union_map_free(umap2);
   3982 
   3983 	if (equal < 0)
   3984 		return -1;
   3985 	if (!equal)
   3986 		isl_die(ctx, isl_error_unknown, "union maps not equal",
   3987 			return -1);
   3988 
   3989 	str = "{ A[i] -> B[i]; B[i] -> C[i]; A[0] -> C[1] }";
   3990 	umap1 = isl_union_map_read_from_str(ctx, str);
   3991 	str = "{ A[i]; B[i] }";
   3992 	uset1 = isl_union_set_read_from_str(ctx, str);
   3993 
   3994 	uset2 = isl_union_map_domain(umap1);
   3995 
   3996 	equal = isl_union_set_is_equal(uset1, uset2);
   3997 
   3998 	isl_union_set_free(uset1);
   3999 	isl_union_set_free(uset2);
   4000 
   4001 	if (equal < 0)
   4002 		return -1;
   4003 	if (!equal)
   4004 		isl_die(ctx, isl_error_unknown, "union sets not equal",
   4005 			return -1);
   4006 
   4007 	return 0;
   4008 }
   4009 
   4010 /* Inputs for basic isl_pw_qpolynomial_bound tests.
   4011  * "type" is the type of bound that should be computed.
   4012  * "poly" is a string representation of the input.
   4013  * "bound" is a string representation of the expected result.
   4014  * "tight" is set if the result is expected to be tight.
   4015  */
   4016 static struct {
   4017 	int tight;
   4018 	enum isl_fold type;
   4019 	const char *poly;
   4020 	const char *bound;
   4021 } bound_tests[] = {
   4022 	/* Check that computing a bound of a non-zero polynomial
   4023 	 * over an unbounded domain does not produce a rational value.
   4024 	 * In particular, check that the upper bound is infinity.
   4025 	 */
   4026 	{ 0, isl_fold_max, "{ [m, n] -> -m * n }", "{ max(infty) }" },
   4027 	{ 1, isl_fold_max, "{ [[a, b, c, d] -> [e]] -> 0 }",
   4028 	  "{ [a, b, c, d] -> max(0) }" },
   4029 	{ 1, isl_fold_max, "{ [[x] -> [x]] -> 1 : exists a : x = 2 a }",
   4030 	  "{ [x] -> max(1) : x mod 2 = 0 }" },
   4031 	{ 1, isl_fold_min, "{ [x=5:10] -> (x + 2)^2 }", "{ min(49) }" },
   4032 	{ 1, isl_fold_max, "{ [0:10] -> 1 }", "{ max(1) }" },
   4033 	{ 1, isl_fold_max, "{ [[m] -> [0:m]] -> m^2 }",
   4034 	  "{ [m] -> max(m^2) : m >= 0 }" },
   4035 };
   4036 
   4037 /* Check that the bound computation can handle differences
   4038  * in domain dimension names of the input polynomial and its domain.
   4039  */
   4040 static isl_stat test_bound_space(isl_ctx *ctx)
   4041 {
   4042 	const char *str;
   4043 	isl_set *set;
   4044 	isl_pw_qpolynomial *pwqp;
   4045 	isl_pw_qpolynomial_fold *pwf;
   4046 
   4047 	str = "{ [[c] -> [c]] }";
   4048 	set = isl_set_read_from_str(ctx, str);
   4049 	str = "{ [[a] -> [b]] -> 1 }";
   4050 	pwqp = isl_pw_qpolynomial_read_from_str(ctx, str);
   4051 	pwqp = isl_pw_qpolynomial_intersect_domain(pwqp, set);
   4052 	pwf = isl_pw_qpolynomial_bound(pwqp, isl_fold_max, NULL);
   4053 	isl_pw_qpolynomial_fold_free(pwf);
   4054 
   4055 	return isl_stat_non_null(pwf);
   4056 }
   4057 
   4058 /* Perform basic isl_pw_qpolynomial_bound tests.
   4059  */
   4060 static int test_bound(isl_ctx *ctx)
   4061 {
   4062 	int i;
   4063 
   4064 	if (test_bound_space(ctx) < 0)
   4065 		return -1;
   4066 
   4067 	for (i = 0; i < ARRAY_SIZE(bound_tests); ++i) {
   4068 		const char *str;
   4069 		enum isl_fold type;
   4070 		isl_bool equal, tight;
   4071 		isl_pw_qpolynomial *pwqp;
   4072 		isl_pw_qpolynomial_fold *pwf1, *pwf2;
   4073 
   4074 		str = bound_tests[i].poly;
   4075 		pwqp = isl_pw_qpolynomial_read_from_str(ctx, str);
   4076 		type = bound_tests[i].type;
   4077 		pwf1 = isl_pw_qpolynomial_bound(pwqp, type, &tight);
   4078 		str = bound_tests[i].bound;
   4079 		pwf2 = isl_pw_qpolynomial_fold_read_from_str(ctx, str);
   4080 		equal = isl_pw_qpolynomial_fold_plain_is_equal(pwf1, pwf2);
   4081 		isl_pw_qpolynomial_fold_free(pwf2);
   4082 		isl_pw_qpolynomial_fold_free(pwf1);
   4083 		if (equal < 0)
   4084 			return -1;
   4085 		if (!equal)
   4086 			isl_die(ctx, isl_error_unknown,
   4087 				"incorrect bound result", return -1);
   4088 		if (bound_tests[i].tight && !tight)
   4089 			isl_die(ctx, isl_error_unknown,
   4090 				"bound unexpectedly not tight", return -1);
   4091 	}
   4092 
   4093 	return 0;
   4094 }
   4095 
   4096 /* isl_set is defined to isl_map internally, so the corresponding elements
   4097  * are isl_basic_map objects.
   4098  */
   4099 #undef EL_BASE
   4100 #undef SET_BASE
   4101 #define EL_BASE		basic_map
   4102 #define SET_BASE	set
   4103 #include "isl_test_list_templ.c"
   4104 
   4105 #undef EL_BASE
   4106 #undef SET_BASE
   4107 #define EL_BASE		basic_set
   4108 #define SET_BASE	union_set
   4109 #include "isl_test_list_templ.c"
   4110 
   4111 #undef EL_BASE
   4112 #undef SET_BASE
   4113 #define EL_BASE		set
   4114 #define SET_BASE	union_set
   4115 #include "isl_test_list_templ.c"
   4116 
   4117 #undef EL_BASE
   4118 #undef SET_BASE
   4119 #define EL_BASE		basic_map
   4120 #define SET_BASE	map
   4121 #include "isl_test_list_templ.c"
   4122 
   4123 #undef EL_BASE
   4124 #undef SET_BASE
   4125 #define EL_BASE		map
   4126 #define SET_BASE	union_map
   4127 #include "isl_test_list_templ.c"
   4128 
   4129 /* Check that the conversion from isl objects to lists works as expected.
   4130  */
   4131 static int test_get_list(isl_ctx *ctx)
   4132 {
   4133 	if (test_get_list_basic_map_from_set(ctx, "{ [0]; [2]; [3] }"))
   4134 		return -1;
   4135 	if (test_get_list_basic_set_from_union_set(ctx, "{ A[0]; B[2]; B[3] }"))
   4136 		return -1;
   4137 	if (test_get_list_set_from_union_set(ctx, "{ A[0]; A[2]; B[3] }"))
   4138 		return -1;
   4139 	if (test_get_list_basic_map_from_map(ctx,
   4140 				"{ [0] -> [0]; [2] -> [0]; [3] -> [0] }"))
   4141 		return -1;
   4142 	if (test_get_list_map_from_union_map(ctx,
   4143 				"{ A[0] -> [0]; A[2] -> [0]; B[3] -> [0] }"))
   4144 		return -1;
   4145 
   4146 	return 0;
   4147 }
   4148 
   4149 static int test_lift(isl_ctx *ctx)
   4150 {
   4151 	const char *str;
   4152 	isl_basic_map *bmap;
   4153 	isl_basic_set *bset;
   4154 
   4155 	str = "{ [i0] : exists e0 : i0 = 4e0 }";
   4156 	bset = isl_basic_set_read_from_str(ctx, str);
   4157 	bset = isl_basic_set_lift(bset);
   4158 	bmap = isl_basic_map_from_range(bset);
   4159 	bset = isl_basic_map_domain(bmap);
   4160 	isl_basic_set_free(bset);
   4161 
   4162 	return 0;
   4163 }
   4164 
   4165 /* Check that isl_set_is_subset is not confused by identical
   4166  * integer divisions.
   4167  * The call to isl_set_normalize ensures that the equality constraints
   4168  * a = b = 0 are discovered, turning e0 and e1 into identical
   4169  * integer divisions.  Any further simplification would remove
   4170  * the duplicate integer divisions.
   4171  */
   4172 static isl_stat test_subset_duplicate_integer_divisions(isl_ctx *ctx)
   4173 {
   4174 	const char *str;
   4175 	isl_bool is_subset;
   4176 	isl_set *set1, *set2;
   4177 
   4178 	str = "{ [a, b, c, d] : "
   4179 	    "exists (e0 = floor((a + d)/4), e1 = floor((d)/4), "
   4180 		    "e2 = floor((-a - d + 4 *floor((a + d)/4))/10), "
   4181 		    "e3 = floor((-d + 4*floor((d)/4))/10): "
   4182 		"10e2 = -a - 2c - d + 4e0 and 10e3 = -2c - d + 4e1 and "
   4183 		"b >= 0 and a <= 0 and b <= a) }";
   4184 	set1 = isl_set_read_from_str(ctx, str);
   4185 	set2 = isl_set_read_from_str(ctx, str);
   4186 	set2 = isl_set_normalize(set2);
   4187 
   4188 	is_subset = isl_set_is_subset(set1, set2);
   4189 
   4190 	isl_set_free(set1);
   4191 	isl_set_free(set2);
   4192 
   4193 	if (is_subset < 0)
   4194 		return isl_stat_error;
   4195 	if (!is_subset)
   4196 		isl_die(ctx, isl_error_unknown,
   4197 			"set is not considered to be a subset of itself",
   4198 			return isl_stat_error);
   4199 
   4200 	return isl_stat_ok;
   4201 }
   4202 
   4203 struct {
   4204 	const char *set1;
   4205 	const char *set2;
   4206 	int subset;
   4207 } subset_tests[] = {
   4208 	{ "{ [112, 0] }",
   4209 	  "{ [i0, i1] : exists (e0 = [(i0 - i1)/16], e1: "
   4210 		"16e0 <= i0 - i1 and 16e0 >= -15 + i0 - i1 and "
   4211 		"16e1 <= i1 and 16e0 >= -i1 and 16e1 >= -i0 + i1) }", 1 },
   4212 	{ "{ [65] }",
   4213 	  "{ [i] : exists (e0 = [(255i)/256], e1 = [(127i + 65e0)/191], "
   4214 		"e2 = [(3i + 61e1)/65], e3 = [(52i + 12e2)/61], "
   4215 		"e4 = [(2i + e3)/3], e5 = [(4i + e3)/4], e6 = [(8i + e3)/12]: "
   4216 		    "3e4 = 2i + e3 and 4e5 = 4i + e3 and 12e6 = 8i + e3 and "
   4217 		    "i <= 255 and 64e3 >= -45 + 67i and i >= 0 and "
   4218 		    "256e0 <= 255i and 256e0 >= -255 + 255i and "
   4219 		    "191e1 <= 127i + 65e0 and 191e1 >= -190 + 127i + 65e0 and "
   4220 		    "65e2 <= 3i + 61e1 and 65e2 >= -64 + 3i + 61e1 and "
   4221 		    "61e3 <= 52i + 12e2 and 61e3 >= -60 + 52i + 12e2) }", 1 },
   4222 	{ "{ [i] : 0 <= i <= 10 }", "{ rat: [i] : 0 <= i <= 10 }", 1 },
   4223 	{ "{ rat: [i] : 0 <= i <= 10 }", "{ [i] : 0 <= i <= 10 }", 0 },
   4224 	{ "{ rat: [0] }", "{ [i] : 0 <= i <= 10 }", 1 },
   4225 	{ "{ rat: [(1)/2] }", "{ [i] : 0 <= i <= 10 }", 0 },
   4226 	{ "{ [t, i] : (exists (e0 = [(2 + t)/4]: 4e0 <= 2 + t and "
   4227 			"4e0 >= -1 + t and i >= 57 and i <= 62 and "
   4228 			"4e0 <= 62 + t - i and 4e0 >= -61 + t + i and "
   4229 			"t >= 0 and t <= 511 and 4e0 <= -57 + t + i and "
   4230 			"4e0 >= 58 + t - i and i >= 58 + t and i >= 62 - t)) }",
   4231 	  "{ [i0, i1] : (exists (e0 = [(4 + i0)/4]: 4e0 <= 62 + i0 - i1 and "
   4232 			"4e0 >= 1 + i0 and i0 >= 0 and i0 <= 511 and "
   4233 			"4e0 <= -57 + i0 + i1)) or "
   4234 		"(exists (e0 = [(2 + i0)/4]: 4e0 <= i0 and "
   4235 			"4e0 >= 58 + i0 - i1 and i0 >= 2 and i0 <= 511 and "
   4236 			"4e0 >= -61 + i0 + i1)) or "
   4237 		"(i1 <= 66 - i0 and i0 >= 2 and i1 >= 59 + i0) }", 1 },
   4238 	{ "[a, b] -> { : a = 0 and b = -1 }", "[b, a] -> { : b >= -10 }", 1 },
   4239 };
   4240 
   4241 static int test_subset(isl_ctx *ctx)
   4242 {
   4243 	int i;
   4244 	isl_set *set1, *set2;
   4245 	int subset;
   4246 
   4247 	if (test_subset_duplicate_integer_divisions(ctx) < 0)
   4248 		return -1;
   4249 
   4250 	for (i = 0; i < ARRAY_SIZE(subset_tests); ++i) {
   4251 		set1 = isl_set_read_from_str(ctx, subset_tests[i].set1);
   4252 		set2 = isl_set_read_from_str(ctx, subset_tests[i].set2);
   4253 		subset = isl_set_is_subset(set1, set2);
   4254 		isl_set_free(set1);
   4255 		isl_set_free(set2);
   4256 		if (subset < 0)
   4257 			return -1;
   4258 		if (subset != subset_tests[i].subset)
   4259 			isl_die(ctx, isl_error_unknown,
   4260 				"incorrect subset result", return -1);
   4261 	}
   4262 
   4263 	return 0;
   4264 }
   4265 
   4266 /* Perform a set subtraction with a set that has a non-obviously empty disjunct.
   4267  * Older versions of isl would fail on such cases.
   4268  */
   4269 static isl_stat test_subtract_empty(isl_ctx *ctx)
   4270 {
   4271 	const char *str;
   4272 	isl_set *s1, *s2;
   4273 
   4274 	s1 = isl_set_read_from_str(ctx, "{ [0] }");
   4275 	str = "{ [a] : (exists (e0, e1, e2: 1056e1 <= 32 + a - 33e0 and "
   4276 			"1089e1 >= a - 33e0 and 1089e1 <= 1 + a - 33e0 and "
   4277 			"33e2 >= -a + 33e0 + 1056e1 and "
   4278 			"33e2 < -2a + 66e0 + 2112e1)) or a = 0 }";
   4279 	s2 = isl_set_read_from_str(ctx, str);
   4280 	s1 = isl_set_subtract(s1, s2);
   4281 	isl_set_free(s1);
   4282 
   4283 	return isl_stat_non_null(s1);
   4284 }
   4285 
   4286 struct {
   4287 	const char *minuend;
   4288 	const char *subtrahend;
   4289 	const char *difference;
   4290 } subtract_domain_tests[] = {
   4291 	{ "{ A[i] -> B[i] }", "{ A[i] }", "{ }" },
   4292 	{ "{ A[i] -> B[i] }", "{ B[i] }", "{ A[i] -> B[i] }" },
   4293 	{ "{ A[i] -> B[i] }", "{ A[i] : i > 0 }", "{ A[i] -> B[i] : i <= 0 }" },
   4294 };
   4295 
   4296 static int test_subtract(isl_ctx *ctx)
   4297 {
   4298 	int i;
   4299 	isl_union_map *umap1, *umap2;
   4300 	isl_union_pw_multi_aff *upma1, *upma2;
   4301 	isl_union_set *uset;
   4302 	int equal;
   4303 
   4304 	if (test_subtract_empty(ctx) < 0)
   4305 		return -1;
   4306 
   4307 	for (i = 0; i < ARRAY_SIZE(subtract_domain_tests); ++i) {
   4308 		umap1 = isl_union_map_read_from_str(ctx,
   4309 				subtract_domain_tests[i].minuend);
   4310 		uset = isl_union_set_read_from_str(ctx,
   4311 				subtract_domain_tests[i].subtrahend);
   4312 		umap2 = isl_union_map_read_from_str(ctx,
   4313 				subtract_domain_tests[i].difference);
   4314 		umap1 = isl_union_map_subtract_domain(umap1, uset);
   4315 		equal = isl_union_map_is_equal(umap1, umap2);
   4316 		isl_union_map_free(umap1);
   4317 		isl_union_map_free(umap2);
   4318 		if (equal < 0)
   4319 			return -1;
   4320 		if (!equal)
   4321 			isl_die(ctx, isl_error_unknown,
   4322 				"incorrect subtract domain result", return -1);
   4323 	}
   4324 
   4325 	for (i = 0; i < ARRAY_SIZE(subtract_domain_tests); ++i) {
   4326 		upma1 = isl_union_pw_multi_aff_read_from_str(ctx,
   4327 				subtract_domain_tests[i].minuend);
   4328 		uset = isl_union_set_read_from_str(ctx,
   4329 				subtract_domain_tests[i].subtrahend);
   4330 		upma2 = isl_union_pw_multi_aff_read_from_str(ctx,
   4331 				subtract_domain_tests[i].difference);
   4332 		upma1 = isl_union_pw_multi_aff_subtract_domain(upma1, uset);
   4333 		equal = isl_union_pw_multi_aff_plain_is_equal(upma1, upma2);
   4334 		isl_union_pw_multi_aff_free(upma1);
   4335 		isl_union_pw_multi_aff_free(upma2);
   4336 		if (equal < 0)
   4337 			return -1;
   4338 		if (!equal)
   4339 			isl_die(ctx, isl_error_unknown,
   4340 				"incorrect subtract domain result", return -1);
   4341 	}
   4342 
   4343 	return 0;
   4344 }
   4345 
   4346 /* Check that intersecting the empty basic set with another basic set
   4347  * does not increase the number of constraints.  In particular,
   4348  * the empty basic set should maintain its canonical representation.
   4349  */
   4350 static int test_intersect_1(isl_ctx *ctx)
   4351 {
   4352 	isl_size n1, n2;
   4353 	isl_basic_set *bset1, *bset2;
   4354 
   4355 	bset1 = isl_basic_set_read_from_str(ctx, "{ [a,b,c] : 1 = 0 }");
   4356 	bset2 = isl_basic_set_read_from_str(ctx, "{ [1,2,3] }");
   4357 	n1 = isl_basic_set_n_constraint(bset1);
   4358 	bset1 = isl_basic_set_intersect(bset1, bset2);
   4359 	n2 = isl_basic_set_n_constraint(bset1);
   4360 	isl_basic_set_free(bset1);
   4361 	if (n1 < 0 || n2 < 0)
   4362 		return -1;
   4363 	if (n1 != n2)
   4364 		isl_die(ctx, isl_error_unknown,
   4365 			"number of constraints of empty set changed",
   4366 			return -1);
   4367 
   4368 	return 0;
   4369 }
   4370 
   4371 /* Check that intersecting a set with itself does not cause
   4372  * an explosion in the number of disjuncts.
   4373  */
   4374 static isl_stat test_intersect_2(isl_ctx *ctx)
   4375 {
   4376 	int i;
   4377 	isl_set *set;
   4378 
   4379 	set = isl_set_read_from_str(ctx, "{ [x,y] : x >= 0 or y >= 0 }");
   4380 	for (i = 0; i < 100; ++i)
   4381 		set = isl_set_intersect(set, isl_set_copy(set));
   4382 	isl_set_free(set);
   4383 	if (!set)
   4384 		return isl_stat_error;
   4385 	return isl_stat_ok;
   4386 }
   4387 
   4388 /* Perform some intersection tests.
   4389  */
   4390 static int test_intersect(isl_ctx *ctx)
   4391 {
   4392 	if (test_intersect_1(ctx) < 0)
   4393 		return -1;
   4394 	if (test_intersect_2(ctx) < 0)
   4395 		return -1;
   4396 
   4397 	return 0;
   4398 }
   4399 
   4400 int test_factorize(isl_ctx *ctx)
   4401 {
   4402 	const char *str;
   4403 	isl_basic_set *bset;
   4404 	isl_factorizer *f;
   4405 
   4406 	str = "{ [i0, i1, i2, i3, i4, i5, i6, i7] : 3i5 <= 2 - 2i0 and "
   4407 	    "i0 >= -2 and i6 >= 1 + i3 and i7 >= 0 and 3i5 >= -2i0 and "
   4408 	    "2i4 <= i2 and i6 >= 1 + 2i0 + 3i1 and i4 <= -1 and "
   4409 	    "i6 >= 1 + 2i0 + 3i5 and i6 <= 2 + 2i0 + 3i5 and "
   4410 	    "3i5 <= 2 - 2i0 - i2 + 3i4 and i6 <= 2 + 2i0 + 3i1 and "
   4411 	    "i0 <= -1 and i7 <= i2 + i3 - 3i4 - i6 and "
   4412 	    "3i5 >= -2i0 - i2 + 3i4 }";
   4413 	bset = isl_basic_set_read_from_str(ctx, str);
   4414 	f = isl_basic_set_factorizer(bset);
   4415 	isl_basic_set_free(bset);
   4416 	isl_factorizer_free(f);
   4417 	if (!f)
   4418 		isl_die(ctx, isl_error_unknown,
   4419 			"failed to construct factorizer", return -1);
   4420 
   4421 	str = "{ [i0, i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11, i12] : "
   4422 	    "i12 <= 2 + i0 - i11 and 2i8 >= -i4 and i11 >= i1 and "
   4423 	    "3i5 <= -i2 and 2i11 >= -i4 - 2i7 and i11 <= 3 + i0 + 3i9 and "
   4424 	    "i11 <= -i4 - 2i7 and i12 >= -i10 and i2 >= -2 and "
   4425 	    "i11 >= i1 + 3i10 and i11 >= 1 + i0 + 3i9 and "
   4426 	    "i11 <= 1 - i4 - 2i8 and 6i6 <= 6 - i2 and 3i6 >= 1 - i2 and "
   4427 	    "i11 <= 2 + i1 and i12 <= i4 + i11 and i12 >= i0 - i11 and "
   4428 	    "3i5 >= -2 - i2 and i12 >= -1 + i4 + i11 and 3i3 <= 3 - i2 and "
   4429 	    "9i6 <= 11 - i2 + 6i5 and 3i3 >= 1 - i2 and "
   4430 	    "9i6 <= 5 - i2 + 6i3 and i12 <= -1 and i2 <= 0 }";
   4431 	bset = isl_basic_set_read_from_str(ctx, str);
   4432 	f = isl_basic_set_factorizer(bset);
   4433 	isl_basic_set_free(bset);
   4434 	isl_factorizer_free(f);
   4435 	if (!f)
   4436 		isl_die(ctx, isl_error_unknown,
   4437 			"failed to construct factorizer", return -1);
   4438 
   4439 	return 0;
   4440 }
   4441 
   4442 static isl_stat check_injective(__isl_take isl_map *map, void *user)
   4443 {
   4444 	int *injective = user;
   4445 
   4446 	*injective = isl_map_is_injective(map);
   4447 	isl_map_free(map);
   4448 
   4449 	if (*injective < 0 || !*injective)
   4450 		return isl_stat_error;
   4451 
   4452 	return isl_stat_ok;
   4453 }
   4454 
   4455 int test_one_schedule(isl_ctx *ctx, const char *d, const char *w,
   4456 	const char *r, const char *s, int tilable, int parallel)
   4457 {
   4458 	int i;
   4459 	isl_union_set *D;
   4460 	isl_union_map *W, *R, *S;
   4461 	isl_union_map *empty;
   4462 	isl_union_map *dep_raw, *dep_war, *dep_waw, *dep;
   4463 	isl_union_map *validity, *proximity, *coincidence;
   4464 	isl_union_map *schedule;
   4465 	isl_union_map *test;
   4466 	isl_union_set *delta;
   4467 	isl_union_set *domain;
   4468 	isl_set *delta_set;
   4469 	isl_set *slice;
   4470 	isl_set *origin;
   4471 	isl_schedule_constraints *sc;
   4472 	isl_schedule *sched;
   4473 	int is_nonneg, is_parallel, is_tilable, is_injection, is_complete;
   4474 	isl_size n;
   4475 
   4476 	D = isl_union_set_read_from_str(ctx, d);
   4477 	W = isl_union_map_read_from_str(ctx, w);
   4478 	R = isl_union_map_read_from_str(ctx, r);
   4479 	S = isl_union_map_read_from_str(ctx, s);
   4480 
   4481 	W = isl_union_map_intersect_domain(W, isl_union_set_copy(D));
   4482 	R = isl_union_map_intersect_domain(R, isl_union_set_copy(D));
   4483 
   4484 	empty = isl_union_map_empty(isl_union_map_get_space(S));
   4485         isl_union_map_compute_flow(isl_union_map_copy(R),
   4486 				   isl_union_map_copy(W), empty,
   4487 				   isl_union_map_copy(S),
   4488 				   &dep_raw, NULL, NULL, NULL);
   4489         isl_union_map_compute_flow(isl_union_map_copy(W),
   4490 				   isl_union_map_copy(W),
   4491 				   isl_union_map_copy(R),
   4492 				   isl_union_map_copy(S),
   4493 				   &dep_waw, &dep_war, NULL, NULL);
   4494 
   4495 	dep = isl_union_map_union(dep_waw, dep_war);
   4496 	dep = isl_union_map_union(dep, dep_raw);
   4497 	validity = isl_union_map_copy(dep);
   4498 	coincidence = isl_union_map_copy(dep);
   4499 	proximity = isl_union_map_copy(dep);
   4500 
   4501 	sc = isl_schedule_constraints_on_domain(isl_union_set_copy(D));
   4502 	sc = isl_schedule_constraints_set_validity(sc, validity);
   4503 	sc = isl_schedule_constraints_set_coincidence(sc, coincidence);
   4504 	sc = isl_schedule_constraints_set_proximity(sc, proximity);
   4505 	sched = isl_schedule_constraints_compute_schedule(sc);
   4506 	schedule = isl_schedule_get_map(sched);
   4507 	isl_schedule_free(sched);
   4508 	isl_union_map_free(W);
   4509 	isl_union_map_free(R);
   4510 	isl_union_map_free(S);
   4511 
   4512 	is_injection = 1;
   4513 	isl_union_map_foreach_map(schedule, &check_injective, &is_injection);
   4514 
   4515 	domain = isl_union_map_domain(isl_union_map_copy(schedule));
   4516 	is_complete = isl_union_set_is_subset(D, domain);
   4517 	isl_union_set_free(D);
   4518 	isl_union_set_free(domain);
   4519 
   4520 	test = isl_union_map_reverse(isl_union_map_copy(schedule));
   4521 	test = isl_union_map_apply_range(test, dep);
   4522 	test = isl_union_map_apply_range(test, schedule);
   4523 
   4524 	delta = isl_union_map_deltas(test);
   4525 	n = isl_union_set_n_set(delta);
   4526 	if (n < 0) {
   4527 		isl_union_set_free(delta);
   4528 		return -1;
   4529 	}
   4530 	if (n == 0) {
   4531 		is_tilable = 1;
   4532 		is_parallel = 1;
   4533 		is_nonneg = 1;
   4534 		isl_union_set_free(delta);
   4535 	} else {
   4536 		isl_size dim;
   4537 
   4538 		delta_set = isl_set_from_union_set(delta);
   4539 
   4540 		slice = isl_set_universe(isl_set_get_space(delta_set));
   4541 		for (i = 0; i < tilable; ++i)
   4542 			slice = isl_set_lower_bound_si(slice, isl_dim_set, i, 0);
   4543 		is_tilable = isl_set_is_subset(delta_set, slice);
   4544 		isl_set_free(slice);
   4545 
   4546 		slice = isl_set_universe(isl_set_get_space(delta_set));
   4547 		for (i = 0; i < parallel; ++i)
   4548 			slice = isl_set_fix_si(slice, isl_dim_set, i, 0);
   4549 		is_parallel = isl_set_is_subset(delta_set, slice);
   4550 		isl_set_free(slice);
   4551 
   4552 		origin = isl_set_universe(isl_set_get_space(delta_set));
   4553 		dim = isl_set_dim(origin, isl_dim_set);
   4554 		if (dim < 0)
   4555 			origin = isl_set_free(origin);
   4556 		for (i = 0; i < dim; ++i)
   4557 			origin = isl_set_fix_si(origin, isl_dim_set, i, 0);
   4558 
   4559 		delta_set = isl_set_union(delta_set, isl_set_copy(origin));
   4560 		delta_set = isl_set_lexmin(delta_set);
   4561 
   4562 		is_nonneg = isl_set_is_equal(delta_set, origin);
   4563 
   4564 		isl_set_free(origin);
   4565 		isl_set_free(delta_set);
   4566 	}
   4567 
   4568 	if (is_nonneg < 0 || is_parallel < 0 || is_tilable < 0 ||
   4569 	    is_injection < 0 || is_complete < 0)
   4570 		return -1;
   4571 	if (!is_complete)
   4572 		isl_die(ctx, isl_error_unknown,
   4573 			"generated schedule incomplete", return -1);
   4574 	if (!is_injection)
   4575 		isl_die(ctx, isl_error_unknown,
   4576 			"generated schedule not injective on each statement",
   4577 			return -1);
   4578 	if (!is_nonneg)
   4579 		isl_die(ctx, isl_error_unknown,
   4580 			"negative dependences in generated schedule",
   4581 			return -1);
   4582 	if (!is_tilable)
   4583 		isl_die(ctx, isl_error_unknown,
   4584 			"generated schedule not as tilable as expected",
   4585 			return -1);
   4586 	if (!is_parallel)
   4587 		isl_die(ctx, isl_error_unknown,
   4588 			"generated schedule not as parallel as expected",
   4589 			return -1);
   4590 
   4591 	return 0;
   4592 }
   4593 
   4594 /* Compute a schedule for the given instance set, validity constraints,
   4595  * proximity constraints and context and return a corresponding union map
   4596  * representation.
   4597  */
   4598 static __isl_give isl_union_map *compute_schedule_with_context(isl_ctx *ctx,
   4599 	const char *domain, const char *validity, const char *proximity,
   4600 	const char *context)
   4601 {
   4602 	isl_set *con;
   4603 	isl_union_set *dom;
   4604 	isl_union_map *dep;
   4605 	isl_union_map *prox;
   4606 	isl_schedule_constraints *sc;
   4607 	isl_schedule *schedule;
   4608 	isl_union_map *sched;
   4609 
   4610 	con = isl_set_read_from_str(ctx, context);
   4611 	dom = isl_union_set_read_from_str(ctx, domain);
   4612 	dep = isl_union_map_read_from_str(ctx, validity);
   4613 	prox = isl_union_map_read_from_str(ctx, proximity);
   4614 	sc = isl_schedule_constraints_on_domain(dom);
   4615 	sc = isl_schedule_constraints_set_context(sc, con);
   4616 	sc = isl_schedule_constraints_set_validity(sc, dep);
   4617 	sc = isl_schedule_constraints_set_proximity(sc, prox);
   4618 	schedule = isl_schedule_constraints_compute_schedule(sc);
   4619 	sched = isl_schedule_get_map(schedule);
   4620 	isl_schedule_free(schedule);
   4621 
   4622 	return sched;
   4623 }
   4624 
   4625 /* Compute a schedule for the given instance set, validity constraints and
   4626  * proximity constraints and return a corresponding union map representation.
   4627  */
   4628 static __isl_give isl_union_map *compute_schedule(isl_ctx *ctx,
   4629 	const char *domain, const char *validity, const char *proximity)
   4630 {
   4631 	return compute_schedule_with_context(ctx, domain, validity, proximity,
   4632 						"{ : }");
   4633 }
   4634 
   4635 /* Check that a schedule can be constructed on the given domain
   4636  * with the given validity and proximity constraints.
   4637  */
   4638 static int test_has_schedule(isl_ctx *ctx, const char *domain,
   4639 	const char *validity, const char *proximity)
   4640 {
   4641 	isl_union_map *sched;
   4642 
   4643 	sched = compute_schedule(ctx, domain, validity, proximity);
   4644 	if (!sched)
   4645 		return -1;
   4646 
   4647 	isl_union_map_free(sched);
   4648 	return 0;
   4649 }
   4650 
   4651 int test_special_schedule(isl_ctx *ctx, const char *domain,
   4652 	const char *validity, const char *proximity, const char *expected_sched)
   4653 {
   4654 	isl_union_map *sched1, *sched2;
   4655 	int equal;
   4656 
   4657 	sched1 = compute_schedule(ctx, domain, validity, proximity);
   4658 	sched2 = isl_union_map_read_from_str(ctx, expected_sched);
   4659 
   4660 	equal = isl_union_map_is_equal(sched1, sched2);
   4661 	isl_union_map_free(sched1);
   4662 	isl_union_map_free(sched2);
   4663 
   4664 	if (equal < 0)
   4665 		return -1;
   4666 	if (!equal)
   4667 		isl_die(ctx, isl_error_unknown, "unexpected schedule",
   4668 			return -1);
   4669 
   4670 	return 0;
   4671 }
   4672 
   4673 /* Check that the schedule map is properly padded, i.e., that the range
   4674  * lives in a single space.
   4675  */
   4676 static int test_padded_schedule(isl_ctx *ctx)
   4677 {
   4678 	const char *str;
   4679 	isl_union_set *D;
   4680 	isl_union_map *validity, *proximity;
   4681 	isl_schedule_constraints *sc;
   4682 	isl_schedule *sched;
   4683 	isl_union_map *umap;
   4684 	isl_union_set *range;
   4685 	isl_set *set;
   4686 
   4687 	str = "[N] -> { S0[i] : 0 <= i <= N; S1[i, j] : 0 <= i, j <= N }";
   4688 	D = isl_union_set_read_from_str(ctx, str);
   4689 	validity = isl_union_map_empty(isl_union_set_get_space(D));
   4690 	proximity = isl_union_map_copy(validity);
   4691 	sc = isl_schedule_constraints_on_domain(D);
   4692 	sc = isl_schedule_constraints_set_validity(sc, validity);
   4693 	sc = isl_schedule_constraints_set_proximity(sc, proximity);
   4694 	sched = isl_schedule_constraints_compute_schedule(sc);
   4695 	umap = isl_schedule_get_map(sched);
   4696 	isl_schedule_free(sched);
   4697 	range = isl_union_map_range(umap);
   4698 	set = isl_set_from_union_set(range);
   4699 	isl_set_free(set);
   4700 
   4701 	if (!set)
   4702 		return -1;
   4703 
   4704 	return 0;
   4705 }
   4706 
   4707 /* Check that conditional validity constraints are also taken into
   4708  * account across bands.
   4709  * In particular, try to make sure that live ranges D[1,0]->C[2,1] and
   4710  * D[2,0]->C[3,0] are not local in the outer band of the generated schedule
   4711  * and then check that the adjacent order constraint C[2,1]->D[2,0]
   4712  * is enforced by the rest of the schedule.
   4713  */
   4714 static int test_special_conditional_schedule_constraints(isl_ctx *ctx)
   4715 {
   4716 	const char *str;
   4717 	isl_union_set *domain;
   4718 	isl_union_map *validity, *proximity, *condition;
   4719 	isl_union_map *sink, *source, *dep;
   4720 	isl_schedule_constraints *sc;
   4721 	isl_schedule *schedule;
   4722 	isl_union_access_info *access;
   4723 	isl_union_flow *flow;
   4724 	int empty;
   4725 
   4726 	str = "[n] -> { C[k, i] : k <= -1 + n and i >= 0 and i <= -1 + k; "
   4727 	    "A[k] : k >= 1 and k <= -1 + n; "
   4728 	    "B[k, i] : k <= -1 + n and i >= 0 and i <= -1 + k; "
   4729 	    "D[k, i] : k <= -1 + n and i >= 0 and i <= -1 + k }";
   4730 	domain = isl_union_set_read_from_str(ctx, str);
   4731 	sc = isl_schedule_constraints_on_domain(domain);
   4732 	str = "[n] -> { D[k, i] -> C[1 + k, k - i] : "
   4733 		"k <= -2 + n and i >= 1 and i <= -1 + k; "
   4734 		"D[k, i] -> C[1 + k, i] : "
   4735 		"k <= -2 + n and i >= 1 and i <= -1 + k; "
   4736 		"D[k, 0] -> C[1 + k, k] : k >= 1 and k <= -2 + n; "
   4737 		"D[k, 0] -> C[1 + k, 0] : k >= 1 and k <= -2 + n }";
   4738 	validity = isl_union_map_read_from_str(ctx, str);
   4739 	sc = isl_schedule_constraints_set_validity(sc, validity);
   4740 	str = "[n] -> { C[k, i] -> D[k, i] : "
   4741 		"0 <= i <= -1 + k and k <= -1 + n }";
   4742 	proximity = isl_union_map_read_from_str(ctx, str);
   4743 	sc = isl_schedule_constraints_set_proximity(sc, proximity);
   4744 	str = "[n] -> { [D[k, i] -> a[]] -> [C[1 + k, k - i] -> b[]] : "
   4745 		"i <= -1 + k and i >= 1 and k <= -2 + n; "
   4746 		"[B[k, i] -> c[]] -> [B[k, 1 + i] -> c[]] : "
   4747 		"k <= -1 + n and i >= 0 and i <= -2 + k }";
   4748 	condition = isl_union_map_read_from_str(ctx, str);
   4749 	str = "[n] -> { [B[k, i] -> e[]] -> [D[k, i] -> a[]] : "
   4750 		"i >= 0 and i <= -1 + k and k <= -1 + n; "
   4751 		"[C[k, i] -> b[]] -> [D[k', -1 + k - i] -> a[]] : "
   4752 		"i >= 0 and i <= -1 + k and k <= -1 + n and "
   4753 		"k' <= -1 + n and k' >= k - i and k' >= 1 + k; "
   4754 		"[C[k, i] -> b[]] -> [D[k, -1 + k - i] -> a[]] : "
   4755 		"i >= 0 and i <= -1 + k and k <= -1 + n; "
   4756 		"[B[k, i] -> c[]] -> [A[k'] -> d[]] : "
   4757 		"k <= -1 + n and i >= 0 and i <= -1 + k and "
   4758 		"k' >= 1 and k' <= -1 + n and k' >= 1 + k }";
   4759 	validity = isl_union_map_read_from_str(ctx, str);
   4760 	sc = isl_schedule_constraints_set_conditional_validity(sc, condition,
   4761 								validity);
   4762 	schedule = isl_schedule_constraints_compute_schedule(sc);
   4763 	str = "{ D[2,0] -> [] }";
   4764 	sink = isl_union_map_read_from_str(ctx, str);
   4765 	access = isl_union_access_info_from_sink(sink);
   4766 	str = "{ C[2,1] -> [] }";
   4767 	source = isl_union_map_read_from_str(ctx, str);
   4768 	access = isl_union_access_info_set_must_source(access, source);
   4769 	access = isl_union_access_info_set_schedule(access, schedule);
   4770 	flow = isl_union_access_info_compute_flow(access);
   4771 	dep = isl_union_flow_get_must_dependence(flow);
   4772 	isl_union_flow_free(flow);
   4773 	empty = isl_union_map_is_empty(dep);
   4774 	isl_union_map_free(dep);
   4775 
   4776 	if (empty < 0)
   4777 		return -1;
   4778 	if (empty)
   4779 		isl_die(ctx, isl_error_unknown,
   4780 			"conditional validity not respected", return -1);
   4781 
   4782 	return 0;
   4783 }
   4784 
   4785 /* Check that the test for violated conditional validity constraints
   4786  * is not confused by domain compression.
   4787  * In particular, earlier versions of isl would apply
   4788  * a schedule on the compressed domains to the original domains,
   4789  * resulting in a failure to detect that the default schedule
   4790  * violates the conditional validity constraints.
   4791  */
   4792 static int test_special_conditional_schedule_constraints_2(isl_ctx *ctx)
   4793 {
   4794 	const char *str;
   4795 	isl_bool empty;
   4796 	isl_union_set *domain;
   4797 	isl_union_map *validity, *condition;
   4798 	isl_schedule_constraints *sc;
   4799 	isl_schedule *schedule;
   4800 	isl_union_map *umap;
   4801 	isl_map *map, *ge;
   4802 
   4803 	str = "{ A[0, i] : 0 <= i <= 10; B[1, i] : 0 <= i <= 10 }";
   4804 	domain = isl_union_set_read_from_str(ctx, str);
   4805 	sc = isl_schedule_constraints_on_domain(domain);
   4806 	str = "{ B[1, i] -> A[0, i + 1] }";
   4807 	condition = isl_union_map_read_from_str(ctx, str);
   4808 	str = "{ A[0, i] -> B[1, i - 1] }";
   4809 	validity = isl_union_map_read_from_str(ctx, str);
   4810 	sc = isl_schedule_constraints_set_conditional_validity(sc, condition,
   4811 						isl_union_map_copy(validity));
   4812 	schedule = isl_schedule_constraints_compute_schedule(sc);
   4813 	umap = isl_schedule_get_map(schedule);
   4814 	isl_schedule_free(schedule);
   4815 	validity = isl_union_map_apply_domain(validity,
   4816 						isl_union_map_copy(umap));
   4817 	validity = isl_union_map_apply_range(validity, umap);
   4818 	map = isl_map_from_union_map(validity);
   4819 	ge = isl_map_lex_ge(isl_space_domain(isl_map_get_space(map)));
   4820 	map = isl_map_intersect(map, ge);
   4821 	empty = isl_map_is_empty(map);
   4822 	isl_map_free(map);
   4823 
   4824 	if (empty < 0)
   4825 		return -1;
   4826 	if (!empty)
   4827 		isl_die(ctx, isl_error_unknown,
   4828 			"conditional validity constraints not satisfied",
   4829 			return -1);
   4830 
   4831 	return 0;
   4832 }
   4833 
   4834 /* Input for testing of schedule construction based on
   4835  * conditional constraints.
   4836  *
   4837  * domain is the iteration domain
   4838  * flow are the flow dependences, which determine the validity and
   4839  * 	proximity constraints
   4840  * condition are the conditions on the conditional validity constraints
   4841  * conditional_validity are the conditional validity constraints
   4842  * outer_band_n is the expected number of members in the outer band
   4843  */
   4844 struct {
   4845 	const char *domain;
   4846 	const char *flow;
   4847 	const char *condition;
   4848 	const char *conditional_validity;
   4849 	int outer_band_n;
   4850 } live_range_tests[] = {
   4851 	/* Contrived example that illustrates that we need to keep
   4852 	 * track of tagged condition dependences and
   4853 	 * tagged conditional validity dependences
   4854 	 * in isl_sched_edge separately.
   4855 	 * In particular, the conditional validity constraints on A
   4856 	 * cannot be satisfied,
   4857 	 * but they can be ignored because there are no corresponding
   4858 	 * condition constraints.  However, we do have an additional
   4859 	 * conditional validity constraint that maps to the same
   4860 	 * dependence relation
   4861 	 * as the condition constraint on B.  If we did not make a distinction
   4862 	 * between tagged condition and tagged conditional validity
   4863 	 * dependences, then we
   4864 	 * could end up treating this shared dependence as an condition
   4865 	 * constraint on A, forcing a localization of the conditions,
   4866 	 * which is impossible.
   4867 	 */
   4868 	{ "{ S[i] : 0 <= 1 < 100; T[i] : 0 <= 1 < 100 }",
   4869 	  "{ S[i] -> S[i+1] : 0 <= i < 99 }",
   4870 	  "{ [S[i] -> B[]] -> [S[i+1] -> B[]] : 0 <= i < 99 }",
   4871 	  "{ [S[i] -> A[]] -> [T[i'] -> A[]] : 0 <= i', i < 100 and i != i';"
   4872 	    "[T[i] -> A[]] -> [S[i'] -> A[]] : 0 <= i', i < 100 and i != i';"
   4873 	    "[S[i] -> A[]] -> [S[i+1] -> A[]] : 0 <= i < 99 }",
   4874 	  1
   4875 	},
   4876 	/* TACO 2013 Fig. 7 */
   4877 	{ "[n] -> { S1[i,j] : 0 <= i,j < n; S2[i,j] : 0 <= i,j < n }",
   4878 	  "[n] -> { S1[i,j] -> S2[i,j] : 0 <= i,j < n;"
   4879 		   "S2[i,j] -> S2[i,j+1] : 0 <= i < n and 0 <= j < n - 1 }",
   4880 	  "[n] -> { [S1[i,j] -> t[]] -> [S2[i,j] -> t[]] : 0 <= i,j < n;"
   4881 		   "[S2[i,j] -> x1[]] -> [S2[i,j+1] -> x1[]] : "
   4882 				"0 <= i < n and 0 <= j < n - 1 }",
   4883 	  "[n] -> { [S2[i,j] -> t[]] -> [S1[i,j'] -> t[]] : "
   4884 				"0 <= i < n and 0 <= j < j' < n;"
   4885 		   "[S2[i,j] -> t[]] -> [S1[i',j'] -> t[]] : "
   4886 				"0 <= i < i' < n and 0 <= j,j' < n;"
   4887 		   "[S2[i,j] -> x1[]] -> [S2[i,j'] -> x1[]] : "
   4888 				"0 <= i,j,j' < n and j < j' }",
   4889 	    2
   4890 	},
   4891 	/* TACO 2013 Fig. 7, without tags */
   4892 	{ "[n] -> { S1[i,j] : 0 <= i,j < n; S2[i,j] : 0 <= i,j < n }",
   4893 	  "[n] -> { S1[i,j] -> S2[i,j] : 0 <= i,j < n;"
   4894 		   "S2[i,j] -> S2[i,j+1] : 0 <= i < n and 0 <= j < n - 1 }",
   4895 	  "[n] -> { S1[i,j] -> S2[i,j] : 0 <= i,j < n;"
   4896 		   "S2[i,j] -> S2[i,j+1] : 0 <= i < n and 0 <= j < n - 1 }",
   4897 	  "[n] -> { S2[i,j] -> S1[i,j'] : 0 <= i < n and 0 <= j < j' < n;"
   4898 		   "S2[i,j] -> S1[i',j'] : 0 <= i < i' < n and 0 <= j,j' < n;"
   4899 		   "S2[i,j] -> S2[i,j'] : 0 <= i,j,j' < n and j < j' }",
   4900 	   1
   4901 	},
   4902 	/* TACO 2013 Fig. 12 */
   4903 	{ "{ S1[i,0] : 0 <= i <= 1; S2[i,j] : 0 <= i <= 1 and 1 <= j <= 2;"
   4904 	    "S3[i,3] : 0 <= i <= 1 }",
   4905 	  "{ S1[i,0] -> S2[i,1] : 0 <= i <= 1;"
   4906 	    "S2[i,1] -> S2[i,2] : 0 <= i <= 1;"
   4907 	    "S2[i,2] -> S3[i,3] : 0 <= i <= 1 }",
   4908 	  "{ [S1[i,0]->t[]] -> [S2[i,1]->t[]] : 0 <= i <= 1;"
   4909 	    "[S2[i,1]->t[]] -> [S2[i,2]->t[]] : 0 <= i <= 1;"
   4910 	    "[S2[i,2]->t[]] -> [S3[i,3]->t[]] : 0 <= i <= 1 }",
   4911 	  "{ [S2[i,1]->t[]] -> [S2[i,2]->t[]] : 0 <= i <= 1;"
   4912 	    "[S2[0,j]->t[]] -> [S2[1,j']->t[]] : 1 <= j,j' <= 2;"
   4913 	    "[S2[0,j]->t[]] -> [S1[1,0]->t[]] : 1 <= j <= 2;"
   4914 	    "[S3[0,3]->t[]] -> [S2[1,j]->t[]] : 1 <= j <= 2;"
   4915 	    "[S3[0,3]->t[]] -> [S1[1,0]->t[]] }",
   4916 	   1
   4917 	}
   4918 };
   4919 
   4920 /* Test schedule construction based on conditional constraints.
   4921  * In particular, check the number of members in the outer band node
   4922  * as an indication of whether tiling is possible or not.
   4923  */
   4924 static int test_conditional_schedule_constraints(isl_ctx *ctx)
   4925 {
   4926 	int i;
   4927 	isl_union_set *domain;
   4928 	isl_union_map *condition;
   4929 	isl_union_map *flow;
   4930 	isl_union_map *validity;
   4931 	isl_schedule_constraints *sc;
   4932 	isl_schedule *schedule;
   4933 	isl_schedule_node *node;
   4934 	isl_size n_member;
   4935 
   4936 	if (test_special_conditional_schedule_constraints(ctx) < 0)
   4937 		return -1;
   4938 	if (test_special_conditional_schedule_constraints_2(ctx) < 0)
   4939 		return -1;
   4940 
   4941 	for (i = 0; i < ARRAY_SIZE(live_range_tests); ++i) {
   4942 		domain = isl_union_set_read_from_str(ctx,
   4943 				live_range_tests[i].domain);
   4944 		flow = isl_union_map_read_from_str(ctx,
   4945 				live_range_tests[i].flow);
   4946 		condition = isl_union_map_read_from_str(ctx,
   4947 				live_range_tests[i].condition);
   4948 		validity = isl_union_map_read_from_str(ctx,
   4949 				live_range_tests[i].conditional_validity);
   4950 		sc = isl_schedule_constraints_on_domain(domain);
   4951 		sc = isl_schedule_constraints_set_validity(sc,
   4952 				isl_union_map_copy(flow));
   4953 		sc = isl_schedule_constraints_set_proximity(sc, flow);
   4954 		sc = isl_schedule_constraints_set_conditional_validity(sc,
   4955 				condition, validity);
   4956 		schedule = isl_schedule_constraints_compute_schedule(sc);
   4957 		node = isl_schedule_get_root(schedule);
   4958 		while (node &&
   4959 		    isl_schedule_node_get_type(node) != isl_schedule_node_band)
   4960 			node = isl_schedule_node_first_child(node);
   4961 		n_member = isl_schedule_node_band_n_member(node);
   4962 		isl_schedule_node_free(node);
   4963 		isl_schedule_free(schedule);
   4964 
   4965 		if (!schedule || n_member < 0)
   4966 			return -1;
   4967 		if (n_member != live_range_tests[i].outer_band_n)
   4968 			isl_die(ctx, isl_error_unknown,
   4969 				"unexpected number of members in outer band",
   4970 				return -1);
   4971 	}
   4972 	return 0;
   4973 }
   4974 
   4975 /* Check that the schedule computed for the given instance set and
   4976  * dependence relation strongly satisfies the dependences.
   4977  * In particular, check that no instance is scheduled before
   4978  * or together with an instance on which it depends.
   4979  * Earlier versions of isl would produce a schedule that
   4980  * only weakly satisfies the dependences.
   4981  */
   4982 static int test_strongly_satisfying_schedule(isl_ctx *ctx)
   4983 {
   4984 	const char *domain, *dep;
   4985 	isl_union_map *D, *schedule;
   4986 	isl_map *map, *ge;
   4987 	int empty;
   4988 
   4989 	domain = "{ B[i0, i1] : 0 <= i0 <= 1 and 0 <= i1 <= 11; "
   4990 		    "A[i0] : 0 <= i0 <= 1 }";
   4991 	dep = "{ B[i0, i1] -> B[i0, 1 + i1] : 0 <= i0 <= 1 and 0 <= i1 <= 10; "
   4992 		"B[0, 11] -> A[1]; A[i0] -> B[i0, 0] : 0 <= i0 <= 1 }";
   4993 	schedule = compute_schedule(ctx, domain, dep, dep);
   4994 	D = isl_union_map_read_from_str(ctx, dep);
   4995 	D = isl_union_map_apply_domain(D, isl_union_map_copy(schedule));
   4996 	D = isl_union_map_apply_range(D, schedule);
   4997 	map = isl_map_from_union_map(D);
   4998 	ge = isl_map_lex_ge(isl_space_domain(isl_map_get_space(map)));
   4999 	map = isl_map_intersect(map, ge);
   5000 	empty = isl_map_is_empty(map);
   5001 	isl_map_free(map);
   5002 
   5003 	if (empty < 0)
   5004 		return -1;
   5005 	if (!empty)
   5006 		isl_die(ctx, isl_error_unknown,
   5007 			"dependences not strongly satisfied", return -1);
   5008 
   5009 	return 0;
   5010 }
   5011 
   5012 /* Compute a schedule for input where the instance set constraints
   5013  * conflict with the context constraints.
   5014  * Earlier versions of isl did not properly handle this situation.
   5015  */
   5016 static int test_conflicting_context_schedule(isl_ctx *ctx)
   5017 {
   5018 	isl_union_map *schedule;
   5019 	const char *domain, *context;
   5020 
   5021 	domain = "[n] -> { A[] : n >= 0 }";
   5022 	context = "[n] -> { : n < 0 }";
   5023 	schedule = compute_schedule_with_context(ctx,
   5024 						domain, "{}", "{}", context);
   5025 	isl_union_map_free(schedule);
   5026 
   5027 	if (!schedule)
   5028 		return -1;
   5029 
   5030 	return 0;
   5031 }
   5032 
   5033 /* Check that a set of schedule constraints that only allow for
   5034  * a coalescing schedule still produces a schedule even if the user
   5035  * request a non-coalescing schedule.  Earlier versions of isl
   5036  * would not handle this case correctly.
   5037  */
   5038 static int test_coalescing_schedule(isl_ctx *ctx)
   5039 {
   5040 	const char *domain, *dep;
   5041 	isl_union_set *I;
   5042 	isl_union_map *D;
   5043 	isl_schedule_constraints *sc;
   5044 	isl_schedule *schedule;
   5045 	int treat_coalescing;
   5046 
   5047 	domain = "{ S[a, b] : 0 <= a <= 1 and 0 <= b <= 1 }";
   5048 	dep = "{ S[a, b] -> S[a + b, 1 - b] }";
   5049 	I = isl_union_set_read_from_str(ctx, domain);
   5050 	D = isl_union_map_read_from_str(ctx, dep);
   5051 	sc = isl_schedule_constraints_on_domain(I);
   5052 	sc = isl_schedule_constraints_set_validity(sc, D);
   5053 	treat_coalescing = isl_options_get_schedule_treat_coalescing(ctx);
   5054 	isl_options_set_schedule_treat_coalescing(ctx, 1);
   5055 	schedule = isl_schedule_constraints_compute_schedule(sc);
   5056 	isl_options_set_schedule_treat_coalescing(ctx, treat_coalescing);
   5057 	isl_schedule_free(schedule);
   5058 	if (!schedule)
   5059 		return -1;
   5060 	return 0;
   5061 }
   5062 
   5063 /* Check that the scheduler does not perform any needless
   5064  * compound skewing.  Earlier versions of isl would compute
   5065  * schedules in terms of transformed schedule coefficients and
   5066  * would not accurately keep track of the sum of the original
   5067  * schedule coefficients.  It could then produce the schedule
   5068  * S[t,i,j,k] -> [t, 2t + i, 2t + i + j, 2t + i + j + k]
   5069  * for the input below instead of the schedule below.
   5070  */
   5071 static int test_skewing_schedule(isl_ctx *ctx)
   5072 {
   5073 	const char *D, *V, *P, *S;
   5074 
   5075 	D = "[n] -> { S[t,i,j,k] : 0 <= t,i,j,k < n }";
   5076 	V = "[n] -> { S[t,i,j,k] -> S[t+1,a,b,c] : 0 <= t,i,j,k,a,b,c < n and "
   5077 		"-2 <= a-i <= 2 and -1 <= a-i + b-j <= 1 and "
   5078 		"-1 <= a-i + b-j + c-k <= 1 }";
   5079 	P = "{ }";
   5080 	S = "{ S[t,i,j,k] -> [t, 2t + i, t + i + j, 2t + k] }";
   5081 
   5082 	return test_special_schedule(ctx, D, V, P, S);
   5083 }
   5084 
   5085 int test_schedule(isl_ctx *ctx)
   5086 {
   5087 	const char *D, *W, *R, *V, *P, *S;
   5088 	int max_coincidence;
   5089 	int treat_coalescing;
   5090 
   5091 	/* Handle resulting schedule with zero bands. */
   5092 	if (test_one_schedule(ctx, "{[]}", "{}", "{}", "{[] -> []}", 0, 0) < 0)
   5093 		return -1;
   5094 
   5095 	/* Jacobi */
   5096 	D = "[T,N] -> { S1[t,i] : 1 <= t <= T and 2 <= i <= N - 1 }";
   5097 	W = "{ S1[t,i] -> a[t,i] }";
   5098 	R = "{ S1[t,i] -> a[t-1,i]; S1[t,i] -> a[t-1,i-1]; "
   5099 	    	"S1[t,i] -> a[t-1,i+1] }";
   5100 	S = "{ S1[t,i] -> [t,i] }";
   5101 	if (test_one_schedule(ctx, D, W, R, S, 2, 0) < 0)
   5102 		return -1;
   5103 
   5104 	/* Fig. 5 of CC2008 */
   5105 	D = "[N] -> { S_0[i, j] : i >= 0 and i <= -1 + N and j >= 2 and "
   5106 				"j <= -1 + N }";
   5107 	W = "[N] -> { S_0[i, j] -> a[i, j] : i >= 0 and i <= -1 + N and "
   5108 				"j >= 2 and j <= -1 + N }";
   5109 	R = "[N] -> { S_0[i, j] -> a[j, i] : i >= 0 and i <= -1 + N and "
   5110 				"j >= 2 and j <= -1 + N; "
   5111 		    "S_0[i, j] -> a[i, -1 + j] : i >= 0 and i <= -1 + N and "
   5112 				"j >= 2 and j <= -1 + N }";
   5113 	S = "[N] -> { S_0[i, j] -> [0, i, 0, j, 0] }";
   5114 	if (test_one_schedule(ctx, D, W, R, S, 2, 0) < 0)
   5115 		return -1;
   5116 
   5117 	D = "{ S1[i] : 0 <= i <= 10; S2[i] : 0 <= i <= 9 }";
   5118 	W = "{ S1[i] -> a[i] }";
   5119 	R = "{ S2[i] -> a[i+1] }";
   5120 	S = "{ S1[i] -> [0,i]; S2[i] -> [1,i] }";
   5121 	if (test_one_schedule(ctx, D, W, R, S, 1, 1) < 0)
   5122 		return -1;
   5123 
   5124 	D = "{ S1[i] : 0 <= i < 10; S2[i] : 0 <= i < 10 }";
   5125 	W = "{ S1[i] -> a[i] }";
   5126 	R = "{ S2[i] -> a[9-i] }";
   5127 	S = "{ S1[i] -> [0,i]; S2[i] -> [1,i] }";
   5128 	if (test_one_schedule(ctx, D, W, R, S, 1, 1) < 0)
   5129 		return -1;
   5130 
   5131 	D = "[N] -> { S1[i] : 0 <= i < N; S2[i] : 0 <= i < N }";
   5132 	W = "{ S1[i] -> a[i] }";
   5133 	R = "[N] -> { S2[i] -> a[N-1-i] }";
   5134 	S = "{ S1[i] -> [0,i]; S2[i] -> [1,i] }";
   5135 	if (test_one_schedule(ctx, D, W, R, S, 1, 1) < 0)
   5136 		return -1;
   5137 
   5138 	D = "{ S1[i] : 0 < i < 10; S2[i] : 0 <= i < 10 }";
   5139 	W = "{ S1[i] -> a[i]; S2[i] -> b[i] }";
   5140 	R = "{ S2[i] -> a[i]; S1[i] -> b[i-1] }";
   5141 	S = "{ S1[i] -> [i,0]; S2[i] -> [i,1] }";
   5142 	if (test_one_schedule(ctx, D, W, R, S, 0, 0) < 0)
   5143 		return -1;
   5144 
   5145 	D = "[N] -> { S1[i] : 1 <= i <= N; S2[i,j] : 1 <= i,j <= N }";
   5146 	W = "{ S1[i] -> a[0,i]; S2[i,j] -> a[i,j] }";
   5147 	R = "{ S2[i,j] -> a[i-1,j] }";
   5148 	S = "{ S1[i] -> [0,i,0]; S2[i,j] -> [1,i,j] }";
   5149 	if (test_one_schedule(ctx, D, W, R, S, 2, 1) < 0)
   5150 		return -1;
   5151 
   5152 	D = "[N] -> { S1[i] : 1 <= i <= N; S2[i,j] : 1 <= i,j <= N }";
   5153 	W = "{ S1[i] -> a[i,0]; S2[i,j] -> a[i,j] }";
   5154 	R = "{ S2[i,j] -> a[i,j-1] }";
   5155 	S = "{ S1[i] -> [0,i,0]; S2[i,j] -> [1,i,j] }";
   5156 	if (test_one_schedule(ctx, D, W, R, S, 2, 1) < 0)
   5157 		return -1;
   5158 
   5159 	D = "[N] -> { S_0[]; S_1[i] : i >= 0 and i <= -1 + N; S_2[] }";
   5160 	W = "[N] -> { S_0[] -> a[0]; S_2[] -> b[0]; "
   5161 		    "S_1[i] -> a[1 + i] : i >= 0 and i <= -1 + N }";
   5162 	R = "[N] -> { S_2[] -> a[N]; S_1[i] -> a[i] : i >= 0 and i <= -1 + N }";
   5163 	S = "[N] -> { S_1[i] -> [1, i, 0]; S_2[] -> [2, 0, 1]; "
   5164 		    "S_0[] -> [0, 0, 0] }";
   5165 	if (test_one_schedule(ctx, D, W, R, S, 1, 0) < 0)
   5166 		return -1;
   5167 	ctx->opt->schedule_parametric = 0;
   5168 	if (test_one_schedule(ctx, D, W, R, S, 0, 0) < 0)
   5169 		return -1;
   5170 	ctx->opt->schedule_parametric = 1;
   5171 
   5172 	D = "[N] -> { S1[i] : 1 <= i <= N; S2[i] : 1 <= i <= N; "
   5173 		    "S3[i,j] : 1 <= i,j <= N; S4[i] : 1 <= i <= N }";
   5174 	W = "{ S1[i] -> a[i,0]; S2[i] -> a[0,i]; S3[i,j] -> a[i,j] }";
   5175 	R = "[N] -> { S3[i,j] -> a[i-1,j]; S3[i,j] -> a[i,j-1]; "
   5176 		    "S4[i] -> a[i,N] }";
   5177 	S = "{ S1[i] -> [0,i,0]; S2[i] -> [1,i,0]; S3[i,j] -> [2,i,j]; "
   5178 		"S4[i] -> [4,i,0] }";
   5179 	max_coincidence = isl_options_get_schedule_maximize_coincidence(ctx);
   5180 	isl_options_set_schedule_maximize_coincidence(ctx, 0);
   5181 	if (test_one_schedule(ctx, D, W, R, S, 2, 0) < 0)
   5182 		return -1;
   5183 	isl_options_set_schedule_maximize_coincidence(ctx, max_coincidence);
   5184 
   5185 	D = "[N] -> { S_0[i, j] : i >= 1 and i <= N and j >= 1 and j <= N }";
   5186 	W = "[N] -> { S_0[i, j] -> s[0] : i >= 1 and i <= N and j >= 1 and "
   5187 					"j <= N }";
   5188 	R = "[N] -> { S_0[i, j] -> s[0] : i >= 1 and i <= N and j >= 1 and "
   5189 					"j <= N; "
   5190 		    "S_0[i, j] -> a[i, j] : i >= 1 and i <= N and j >= 1 and "
   5191 					"j <= N }";
   5192 	S = "[N] -> { S_0[i, j] -> [0, i, 0, j, 0] }";
   5193 	if (test_one_schedule(ctx, D, W, R, S, 0, 0) < 0)
   5194 		return -1;
   5195 
   5196 	D = "[N] -> { S_0[t] : t >= 0 and t <= -1 + N; "
   5197 		    " S_2[t] : t >= 0 and t <= -1 + N; "
   5198 		    " S_1[t, i] : t >= 0 and t <= -1 + N and i >= 0 and "
   5199 				"i <= -1 + N }";
   5200 	W = "[N] -> { S_0[t] -> a[t, 0] : t >= 0 and t <= -1 + N; "
   5201 		    " S_2[t] -> b[t] : t >= 0 and t <= -1 + N; "
   5202 		    " S_1[t, i] -> a[t, 1 + i] : t >= 0 and t <= -1 + N and "
   5203 						"i >= 0 and i <= -1 + N }";
   5204 	R = "[N] -> { S_1[t, i] -> a[t, i] : t >= 0 and t <= -1 + N and "
   5205 					    "i >= 0 and i <= -1 + N; "
   5206 		    " S_2[t] -> a[t, N] : t >= 0 and t <= -1 + N }";
   5207 	S = "[N] -> { S_2[t] -> [0, t, 2]; S_1[t, i] -> [0, t, 1, i, 0]; "
   5208 		    " S_0[t] -> [0, t, 0] }";
   5209 
   5210 	if (test_one_schedule(ctx, D, W, R, S, 2, 1) < 0)
   5211 		return -1;
   5212 	ctx->opt->schedule_parametric = 0;
   5213 	if (test_one_schedule(ctx, D, W, R, S, 0, 0) < 0)
   5214 		return -1;
   5215 	ctx->opt->schedule_parametric = 1;
   5216 
   5217 	D = "[N] -> { S1[i,j] : 0 <= i,j < N; S2[i,j] : 0 <= i,j < N }";
   5218 	S = "{ S1[i,j] -> [0,i,j]; S2[i,j] -> [1,i,j] }";
   5219 	if (test_one_schedule(ctx, D, "{}", "{}", S, 2, 2) < 0)
   5220 		return -1;
   5221 
   5222 	D = "[M, N] -> { S_1[i] : i >= 0 and i <= -1 + M; "
   5223 	    "S_0[i, j] : i >= 0 and i <= -1 + M and j >= 0 and j <= -1 + N }";
   5224 	W = "[M, N] -> { S_0[i, j] -> a[j] : i >= 0 and i <= -1 + M and "
   5225 					    "j >= 0 and j <= -1 + N; "
   5226 			"S_1[i] -> b[0] : i >= 0 and i <= -1 + M }";
   5227 	R = "[M, N] -> { S_0[i, j] -> a[0] : i >= 0 and i <= -1 + M and "
   5228 					    "j >= 0 and j <= -1 + N; "
   5229 			"S_1[i] -> b[0] : i >= 0 and i <= -1 + M }";
   5230 	S = "[M, N] -> { S_1[i] -> [1, i, 0]; S_0[i, j] -> [0, i, 0, j, 0] }";
   5231 	if (test_one_schedule(ctx, D, W, R, S, 0, 0) < 0)
   5232 		return -1;
   5233 
   5234 	D = "{ S_0[i] : i >= 0 }";
   5235 	W = "{ S_0[i] -> a[i] : i >= 0 }";
   5236 	R = "{ S_0[i] -> a[0] : i >= 0 }";
   5237 	S = "{ S_0[i] -> [0, i, 0] }";
   5238 	if (test_one_schedule(ctx, D, W, R, S, 0, 0) < 0)
   5239 		return -1;
   5240 
   5241 	D = "{ S_0[i] : i >= 0; S_1[i] : i >= 0 }";
   5242 	W = "{ S_0[i] -> a[i] : i >= 0; S_1[i] -> b[i] : i >= 0 }";
   5243 	R = "{ S_0[i] -> b[0] : i >= 0; S_1[i] -> a[i] : i >= 0 }";
   5244 	S = "{ S_1[i] -> [0, i, 1]; S_0[i] -> [0, i, 0] }";
   5245 	if (test_one_schedule(ctx, D, W, R, S, 0, 0) < 0)
   5246 		return -1;
   5247 
   5248 	D = "[n] -> { S_0[j, k] : j <= -1 + n and j >= 0 and "
   5249 				"k <= -1 + n and k >= 0 }";
   5250 	W = "[n] -> { S_0[j, k] -> B[j] : j <= -1 + n and j >= 0 and "							"k <= -1 + n and k >= 0 }";
   5251 	R = "[n] -> { S_0[j, k] -> B[j] : j <= -1 + n and j >= 0 and "
   5252 					"k <= -1 + n and k >= 0; "
   5253 		    "S_0[j, k] -> B[k] : j <= -1 + n and j >= 0 and "
   5254 					"k <= -1 + n and k >= 0; "
   5255 		    "S_0[j, k] -> A[k] : j <= -1 + n and j >= 0 and "
   5256 					"k <= -1 + n and k >= 0 }";
   5257 	S = "[n] -> { S_0[j, k] -> [2, j, k] }";
   5258 	ctx->opt->schedule_outer_coincidence = 1;
   5259 	if (test_one_schedule(ctx, D, W, R, S, 0, 0) < 0)
   5260 		return -1;
   5261 	ctx->opt->schedule_outer_coincidence = 0;
   5262 
   5263 	D = "{Stmt_for_body24[i0, i1, i2, i3]:"
   5264 		"i0 >= 0 and i0 <= 1 and i1 >= 0 and i1 <= 6 and i2 >= 2 and "
   5265 		"i2 <= 6 - i1 and i3 >= 0 and i3 <= -1 + i2;"
   5266 	     "Stmt_for_body24[i0, i1, 1, 0]:"
   5267 		"i0 >= 0 and i0 <= 1 and i1 >= 0 and i1 <= 5;"
   5268 	     "Stmt_for_body7[i0, i1, i2]:"
   5269 		"i0 >= 0 and i0 <= 1 and i1 >= 0 and i1 <= 7 and i2 >= 0 and "
   5270 		"i2 <= 7 }";
   5271 
   5272 	V = "{Stmt_for_body24[0, i1, i2, i3] -> "
   5273 		"Stmt_for_body24[1, i1, i2, i3]:"
   5274 		"i3 >= 0 and i3 <= -1 + i2 and i1 >= 0 and i2 <= 6 - i1 and "
   5275 		"i2 >= 1;"
   5276 	     "Stmt_for_body24[0, i1, i2, i3] -> "
   5277 		"Stmt_for_body7[1, 1 + i1 + i3, 1 + i1 + i2]:"
   5278 		"i3 <= -1 + i2 and i2 <= 6 - i1 and i2 >= 1 and i1 >= 0 and "
   5279 		"i3 >= 0;"
   5280 	      "Stmt_for_body24[0, i1, i2, i3] ->"
   5281 		"Stmt_for_body7[1, i1, 1 + i1 + i3]:"
   5282 		"i3 >= 0 and i2 <= 6 - i1 and i1 >= 0 and i3 <= -1 + i2;"
   5283 	      "Stmt_for_body7[0, i1, i2] -> Stmt_for_body7[1, i1, i2]:"
   5284 		"(i2 >= 1 + i1 and i2 <= 6 and i1 >= 0 and i1 <= 4) or "
   5285 		"(i2 >= 3 and i2 <= 7 and i1 >= 1 and i2 >= 1 + i1) or "
   5286 		"(i2 >= 0 and i2 <= i1 and i2 >= -7 + i1 and i1 <= 7);"
   5287 	      "Stmt_for_body7[0, i1, 1 + i1] -> Stmt_for_body7[1, i1, 1 + i1]:"
   5288 		"i1 <= 6 and i1 >= 0;"
   5289 	      "Stmt_for_body7[0, 0, 7] -> Stmt_for_body7[1, 0, 7];"
   5290 	      "Stmt_for_body7[i0, i1, i2] -> "
   5291 		"Stmt_for_body24[i0, o1, -1 + i2 - o1, -1 + i1 - o1]:"
   5292 		"i0 >= 0 and i0 <= 1 and o1 >= 0 and i2 >= 1 + i1 and "
   5293 		"o1 <= -2 + i2 and i2 <= 7 and o1 <= -1 + i1;"
   5294 	      "Stmt_for_body7[i0, i1, i2] -> "
   5295 		"Stmt_for_body24[i0, i1, o2, -1 - i1 + i2]:"
   5296 		"i0 >= 0 and i0 <= 1 and i1 >= 0 and o2 >= -i1 + i2 and "
   5297 		"o2 >= 1 and o2 <= 6 - i1 and i2 >= 1 + i1 }";
   5298 	P = V;
   5299 
   5300 	treat_coalescing = isl_options_get_schedule_treat_coalescing(ctx);
   5301 	isl_options_set_schedule_treat_coalescing(ctx, 0);
   5302 	if (test_has_schedule(ctx, D, V, P) < 0)
   5303 		return -1;
   5304 	isl_options_set_schedule_treat_coalescing(ctx, treat_coalescing);
   5305 
   5306 	D = "{ S_0[i, j] : i >= 1 and i <= 10 and j >= 1 and j <= 8 }";
   5307 	V = "{ S_0[i, j] -> S_0[i, 1 + j] : i >= 1 and i <= 10 and "
   5308 					   "j >= 1 and j <= 7;"
   5309 		"S_0[i, j] -> S_0[1 + i, j] : i >= 1 and i <= 9 and "
   5310 					     "j >= 1 and j <= 8 }";
   5311 	P = "{ }";
   5312 	S = "{ S_0[i, j] -> [i + j, i] }";
   5313 	ctx->opt->schedule_algorithm = ISL_SCHEDULE_ALGORITHM_FEAUTRIER;
   5314 	if (test_special_schedule(ctx, D, V, P, S) < 0)
   5315 		return -1;
   5316 	ctx->opt->schedule_algorithm = ISL_SCHEDULE_ALGORITHM_ISL;
   5317 
   5318 	/* Fig. 1 from Feautrier's "Some Efficient Solutions..." pt. 2, 1992 */
   5319 	D = "[N] -> { S_0[i, j] : i >= 0 and i <= -1 + N and "
   5320 				 "j >= 0 and j <= -1 + i }";
   5321 	V = "[N] -> { S_0[i, j] -> S_0[i, 1 + j] : j <= -2 + i and "
   5322 					"i <= -1 + N and j >= 0;"
   5323 		     "S_0[i, -1 + i] -> S_0[1 + i, 0] : i >= 1 and "
   5324 					"i <= -2 + N }";
   5325 	P = "{ }";
   5326 	S = "{ S_0[i, j] -> [i, j] }";
   5327 	ctx->opt->schedule_algorithm = ISL_SCHEDULE_ALGORITHM_FEAUTRIER;
   5328 	if (test_special_schedule(ctx, D, V, P, S) < 0)
   5329 		return -1;
   5330 	ctx->opt->schedule_algorithm = ISL_SCHEDULE_ALGORITHM_ISL;
   5331 
   5332 	/* Test both algorithms on a case with only proximity dependences. */
   5333 	D = "{ S[i,j] : 0 <= i <= 10 }";
   5334 	V = "{ }";
   5335 	P = "{ S[i,j] -> S[i+1,j] : 0 <= i,j <= 10 }";
   5336 	S = "{ S[i, j] -> [j, i] }";
   5337 	ctx->opt->schedule_algorithm = ISL_SCHEDULE_ALGORITHM_FEAUTRIER;
   5338 	if (test_special_schedule(ctx, D, V, P, S) < 0)
   5339 		return -1;
   5340 	ctx->opt->schedule_algorithm = ISL_SCHEDULE_ALGORITHM_ISL;
   5341 	if (test_special_schedule(ctx, D, V, P, S) < 0)
   5342 		return -1;
   5343 
   5344 	D = "{ A[a]; B[] }";
   5345 	V = "{}";
   5346 	P = "{ A[a] -> B[] }";
   5347 	if (test_has_schedule(ctx, D, V, P) < 0)
   5348 		return -1;
   5349 
   5350 	if (test_padded_schedule(ctx) < 0)
   5351 		return -1;
   5352 
   5353 	/* Check that check for progress is not confused by rational
   5354 	 * solution.
   5355 	 */
   5356 	D = "[N] -> { S0[i, j] : i >= 0 and i <= N and j >= 0 and j <= N }";
   5357 	V = "[N] -> { S0[i0, -1 + N] -> S0[2 + i0, 0] : i0 >= 0 and "
   5358 							"i0 <= -2 + N; "
   5359 			"S0[i0, i1] -> S0[i0, 1 + i1] : i0 >= 0 and "
   5360 				"i0 <= N and i1 >= 0 and i1 <= -1 + N }";
   5361 	P = "{}";
   5362 	ctx->opt->schedule_algorithm = ISL_SCHEDULE_ALGORITHM_FEAUTRIER;
   5363 	if (test_has_schedule(ctx, D, V, P) < 0)
   5364 		return -1;
   5365 	ctx->opt->schedule_algorithm = ISL_SCHEDULE_ALGORITHM_ISL;
   5366 
   5367 	/* Check that we allow schedule rows that are only non-trivial
   5368 	 * on some full-dimensional domains.
   5369 	 */
   5370 	D = "{ S1[j] : 0 <= j <= 1; S0[]; S2[k] : 0 <= k <= 1 }";
   5371 	V = "{ S0[] -> S1[j] : 0 <= j <= 1; S2[0] -> S0[];"
   5372 		"S1[j] -> S2[1] : 0 <= j <= 1 }";
   5373 	P = "{}";
   5374 	ctx->opt->schedule_algorithm = ISL_SCHEDULE_ALGORITHM_FEAUTRIER;
   5375 	if (test_has_schedule(ctx, D, V, P) < 0)
   5376 		return -1;
   5377 	ctx->opt->schedule_algorithm = ISL_SCHEDULE_ALGORITHM_ISL;
   5378 
   5379 	if (test_conditional_schedule_constraints(ctx) < 0)
   5380 		return -1;
   5381 
   5382 	if (test_strongly_satisfying_schedule(ctx) < 0)
   5383 		return -1;
   5384 
   5385 	if (test_conflicting_context_schedule(ctx) < 0)
   5386 		return -1;
   5387 
   5388 	if (test_coalescing_schedule(ctx) < 0)
   5389 		return -1;
   5390 	if (test_skewing_schedule(ctx) < 0)
   5391 		return -1;
   5392 
   5393 	return 0;
   5394 }
   5395 
   5396 /* Perform scheduling tests using the whole component scheduler.
   5397  */
   5398 static int test_schedule_whole(isl_ctx *ctx)
   5399 {
   5400 	int whole;
   5401 	int r;
   5402 
   5403 	whole = isl_options_get_schedule_whole_component(ctx);
   5404 	isl_options_set_schedule_whole_component(ctx, 1);
   5405 	r = test_schedule(ctx);
   5406 	isl_options_set_schedule_whole_component(ctx, whole);
   5407 
   5408 	return r;
   5409 }
   5410 
   5411 /* Perform scheduling tests using the incremental scheduler.
   5412  */
   5413 static int test_schedule_incremental(isl_ctx *ctx)
   5414 {
   5415 	int whole;
   5416 	int r;
   5417 
   5418 	whole = isl_options_get_schedule_whole_component(ctx);
   5419 	isl_options_set_schedule_whole_component(ctx, 0);
   5420 	r = test_schedule(ctx);
   5421 	isl_options_set_schedule_whole_component(ctx, whole);
   5422 
   5423 	return r;
   5424 }
   5425 
   5426 int test_plain_injective(isl_ctx *ctx, const char *str, int injective)
   5427 {
   5428 	isl_union_map *umap;
   5429 	int test;
   5430 
   5431 	umap = isl_union_map_read_from_str(ctx, str);
   5432 	test = isl_union_map_plain_is_injective(umap);
   5433 	isl_union_map_free(umap);
   5434 	if (test < 0)
   5435 		return -1;
   5436 	if (test == injective)
   5437 		return 0;
   5438 	if (injective)
   5439 		isl_die(ctx, isl_error_unknown,
   5440 			"map not detected as injective", return -1);
   5441 	else
   5442 		isl_die(ctx, isl_error_unknown,
   5443 			"map detected as injective", return -1);
   5444 }
   5445 
   5446 int test_injective(isl_ctx *ctx)
   5447 {
   5448 	const char *str;
   5449 
   5450 	if (test_plain_injective(ctx, "{S[i,j] -> A[0]; T[i,j] -> B[1]}", 0))
   5451 		return -1;
   5452 	if (test_plain_injective(ctx, "{S[] -> A[0]; T[] -> B[0]}", 1))
   5453 		return -1;
   5454 	if (test_plain_injective(ctx, "{S[] -> A[0]; T[] -> A[1]}", 1))
   5455 		return -1;
   5456 	if (test_plain_injective(ctx, "{S[] -> A[0]; T[] -> A[0]}", 0))
   5457 		return -1;
   5458 	if (test_plain_injective(ctx, "{S[i] -> A[i,0]; T[i] -> A[i,1]}", 1))
   5459 		return -1;
   5460 	if (test_plain_injective(ctx, "{S[i] -> A[i]; T[i] -> A[i]}", 0))
   5461 		return -1;
   5462 	if (test_plain_injective(ctx, "{S[] -> A[0,0]; T[] -> A[0,1]}", 1))
   5463 		return -1;
   5464 	if (test_plain_injective(ctx, "{S[] -> A[0,0]; T[] -> A[1,0]}", 1))
   5465 		return -1;
   5466 
   5467 	str = "{S[] -> A[0,0]; T[] -> A[0,1]; U[] -> A[1,0]}";
   5468 	if (test_plain_injective(ctx, str, 1))
   5469 		return -1;
   5470 	str = "{S[] -> A[0,0]; T[] -> A[0,1]; U[] -> A[0,0]}";
   5471 	if (test_plain_injective(ctx, str, 0))
   5472 		return -1;
   5473 
   5474 	return 0;
   5475 }
   5476 
   5477 #undef BASE
   5478 #define BASE	aff
   5479 #include "isl_test_plain_equal_templ.c"
   5480 
   5481 #undef BASE
   5482 #define BASE	pw_multi_aff
   5483 #include "isl_test_plain_equal_templ.c"
   5484 
   5485 #undef BASE
   5486 #define BASE	union_pw_aff
   5487 #include "isl_test_plain_equal_templ.c"
   5488 
   5489 /* Basic tests on isl_union_pw_aff.
   5490  *
   5491  * In particular, check that isl_union_pw_aff_aff_on_domain
   5492  * aligns the parameters of the input objects and
   5493  * that isl_union_pw_aff_param_on_domain_id properly
   5494  * introduces the parameter.
   5495  */
   5496 static int test_upa(isl_ctx *ctx)
   5497 {
   5498 	const char *str;
   5499 	isl_id *id;
   5500 	isl_aff *aff;
   5501 	isl_union_set *domain;
   5502 	isl_union_pw_aff *upa;
   5503 	isl_stat ok;
   5504 
   5505 	aff = isl_aff_read_from_str(ctx, "[N] -> { [N] }");
   5506 	str = "[M] -> { A[i] : 0 <= i < M; B[] }";
   5507 	domain = isl_union_set_read_from_str(ctx, str);
   5508 	upa = isl_union_pw_aff_aff_on_domain(domain, aff);
   5509 	str = "[N, M] -> { A[i] -> [N] : 0 <= i < M; B[] -> [N] }";
   5510 	ok = union_pw_aff_check_plain_equal(upa, str);
   5511 	isl_union_pw_aff_free(upa);
   5512 	if (ok < 0)
   5513 		return -1;
   5514 
   5515 	id = isl_id_alloc(ctx, "N", NULL);
   5516 	str = "[M] -> { A[i] : 0 <= i < M; B[] }";
   5517 	domain = isl_union_set_read_from_str(ctx, str);
   5518 	upa = isl_union_pw_aff_param_on_domain_id(domain, id);
   5519 	str = "[N, M] -> { A[i] -> [N] : 0 <= i < M; B[] -> [N] }";
   5520 	ok = union_pw_aff_check_plain_equal(upa, str);
   5521 	isl_union_pw_aff_free(upa);
   5522 	if (ok < 0)
   5523 		return -1;
   5524 
   5525 	return 0;
   5526 }
   5527 
   5528 struct {
   5529 	__isl_give isl_aff *(*fn)(__isl_take isl_aff *aff1,
   5530 				__isl_take isl_aff *aff2);
   5531 } aff_bin_op[] = {
   5532 	['+'] = { &isl_aff_add },
   5533 	['-'] = { &isl_aff_sub },
   5534 	['*'] = { &isl_aff_mul },
   5535 	['/'] = { &isl_aff_div },
   5536 };
   5537 
   5538 struct {
   5539 	const char *arg1;
   5540 	unsigned char op;
   5541 	const char *arg2;
   5542 	const char *res;
   5543 } aff_bin_tests[] = {
   5544 	{ "{ [i] -> [i] }", '+', "{ [i] -> [i] }",
   5545 	  "{ [i] -> [2i] }" },
   5546 	{ "{ [i] -> [i] }", '-', "{ [i] -> [i] }",
   5547 	  "{ [i] -> [0] }" },
   5548 	{ "{ [i] -> [i] }", '*', "{ [i] -> [2] }",
   5549 	  "{ [i] -> [2i] }" },
   5550 	{ "{ [i] -> [2] }", '*', "{ [i] -> [i] }",
   5551 	  "{ [i] -> [2i] }" },
   5552 	{ "{ [i] -> [i] }", '/', "{ [i] -> [2] }",
   5553 	  "{ [i] -> [i/2] }" },
   5554 	{ "{ [i] -> [2i] }", '/', "{ [i] -> [2] }",
   5555 	  "{ [i] -> [i] }" },
   5556 	{ "{ [i] -> [i] }", '+', "{ [i] -> [NaN] }",
   5557 	  "{ [i] -> [NaN] }" },
   5558 	{ "{ [i] -> [i] }", '-', "{ [i] -> [NaN] }",
   5559 	  "{ [i] -> [NaN] }" },
   5560 	{ "{ [i] -> [i] }", '*', "{ [i] -> [NaN] }",
   5561 	  "{ [i] -> [NaN] }" },
   5562 	{ "{ [i] -> [2] }", '*', "{ [i] -> [NaN] }",
   5563 	  "{ [i] -> [NaN] }" },
   5564 	{ "{ [i] -> [i] }", '/', "{ [i] -> [NaN] }",
   5565 	  "{ [i] -> [NaN] }" },
   5566 	{ "{ [i] -> [2] }", '/', "{ [i] -> [NaN] }",
   5567 	  "{ [i] -> [NaN] }" },
   5568 	{ "{ [i] -> [NaN] }", '+', "{ [i] -> [i] }",
   5569 	  "{ [i] -> [NaN] }" },
   5570 	{ "{ [i] -> [NaN] }", '-', "{ [i] -> [i] }",
   5571 	  "{ [i] -> [NaN] }" },
   5572 	{ "{ [i] -> [NaN] }", '*', "{ [i] -> [2] }",
   5573 	  "{ [i] -> [NaN] }" },
   5574 	{ "{ [i] -> [NaN] }", '*', "{ [i] -> [i] }",
   5575 	  "{ [i] -> [NaN] }" },
   5576 	{ "{ [i] -> [NaN] }", '/', "{ [i] -> [2] }",
   5577 	  "{ [i] -> [NaN] }" },
   5578 	{ "{ [i] -> [NaN] }", '/', "{ [i] -> [i] }",
   5579 	  "{ [i] -> [NaN] }" },
   5580 	{ "{ [i] -> [i] }", '/', "{ [i] -> [0] }",
   5581 	  "{ [i] -> [NaN] }" },
   5582 };
   5583 
   5584 /* Perform some basic tests of binary operations on isl_aff objects.
   5585  */
   5586 static int test_bin_aff(isl_ctx *ctx)
   5587 {
   5588 	int i;
   5589 	isl_aff *aff1, *aff2, *res;
   5590 	__isl_give isl_aff *(*fn)(__isl_take isl_aff *aff1,
   5591 				__isl_take isl_aff *aff2);
   5592 	int ok;
   5593 
   5594 	for (i = 0; i < ARRAY_SIZE(aff_bin_tests); ++i) {
   5595 		aff1 = isl_aff_read_from_str(ctx, aff_bin_tests[i].arg1);
   5596 		aff2 = isl_aff_read_from_str(ctx, aff_bin_tests[i].arg2);
   5597 		res = isl_aff_read_from_str(ctx, aff_bin_tests[i].res);
   5598 		fn = aff_bin_op[aff_bin_tests[i].op].fn;
   5599 		aff1 = fn(aff1, aff2);
   5600 		if (isl_aff_is_nan(res))
   5601 			ok = isl_aff_is_nan(aff1);
   5602 		else
   5603 			ok = isl_aff_plain_is_equal(aff1, res);
   5604 		isl_aff_free(aff1);
   5605 		isl_aff_free(res);
   5606 		if (ok < 0)
   5607 			return -1;
   5608 		if (!ok)
   5609 			isl_die(ctx, isl_error_unknown,
   5610 				"unexpected result", return -1);
   5611 	}
   5612 
   5613 	return 0;
   5614 }
   5615 
   5616 struct {
   5617 	__isl_give isl_pw_aff *(*fn)(__isl_take isl_pw_aff *pa1,
   5618 				     __isl_take isl_pw_aff *pa2);
   5619 } pw_aff_bin_op[] = {
   5620 	['m'] = { &isl_pw_aff_min },
   5621 	['M'] = { &isl_pw_aff_max },
   5622 };
   5623 
   5624 /* Inputs for binary isl_pw_aff operation tests.
   5625  * "arg1" and "arg2" are the two arguments, "op" identifies the operation
   5626  * defined by pw_aff_bin_op, and "res" is the expected result.
   5627  */
   5628 struct {
   5629 	const char *arg1;
   5630 	unsigned char op;
   5631 	const char *arg2;
   5632 	const char *res;
   5633 } pw_aff_bin_tests[] = {
   5634 	{ "{ [i] -> [i] }", 'm', "{ [i] -> [i] }",
   5635 	  "{ [i] -> [i] }" },
   5636 	{ "{ [i] -> [i] }", 'M', "{ [i] -> [i] }",
   5637 	  "{ [i] -> [i] }" },
   5638 	{ "{ [i] -> [i] }", 'm', "{ [i] -> [0] }",
   5639 	  "{ [i] -> [i] : i <= 0; [i] -> [0] : i > 0 }" },
   5640 	{ "{ [i] -> [i] }", 'M', "{ [i] -> [0] }",
   5641 	  "{ [i] -> [i] : i >= 0; [i] -> [0] : i < 0 }" },
   5642 	{ "{ [i] -> [i] }", 'm', "{ [i] -> [NaN] }",
   5643 	  "{ [i] -> [NaN] }" },
   5644 	{ "{ [i] -> [NaN] }", 'm', "{ [i] -> [i] }",
   5645 	  "{ [i] -> [NaN] }" },
   5646 };
   5647 
   5648 /* Perform some basic tests of binary operations on isl_pw_aff objects.
   5649  */
   5650 static int test_bin_pw_aff(isl_ctx *ctx)
   5651 {
   5652 	int i;
   5653 	isl_bool ok;
   5654 	isl_pw_aff *pa1, *pa2, *res;
   5655 
   5656 	for (i = 0; i < ARRAY_SIZE(pw_aff_bin_tests); ++i) {
   5657 		pa1 = isl_pw_aff_read_from_str(ctx, pw_aff_bin_tests[i].arg1);
   5658 		pa2 = isl_pw_aff_read_from_str(ctx, pw_aff_bin_tests[i].arg2);
   5659 		res = isl_pw_aff_read_from_str(ctx, pw_aff_bin_tests[i].res);
   5660 		pa1 = pw_aff_bin_op[pw_aff_bin_tests[i].op].fn(pa1, pa2);
   5661 		if (isl_pw_aff_involves_nan(res))
   5662 			ok = isl_pw_aff_involves_nan(pa1);
   5663 		else
   5664 			ok = isl_pw_aff_plain_is_equal(pa1, res);
   5665 		isl_pw_aff_free(pa1);
   5666 		isl_pw_aff_free(res);
   5667 		if (ok < 0)
   5668 			return -1;
   5669 		if (!ok)
   5670 			isl_die(ctx, isl_error_unknown,
   5671 				"unexpected result", return -1);
   5672 	}
   5673 
   5674 	return 0;
   5675 }
   5676 
   5677 /* Inputs for basic tests of test operations on
   5678  * isl_union_pw_multi_aff objects.
   5679  * "fn" is the function that is being tested.
   5680  * "arg" is a string description of the input.
   5681  * "res" is the expected result.
   5682  */
   5683 static struct {
   5684 	isl_bool (*fn)(__isl_keep isl_union_pw_multi_aff *upma1);
   5685 	const char *arg;
   5686 	isl_bool res;
   5687 } upma_test_tests[] = {
   5688 	{ &isl_union_pw_multi_aff_involves_nan, "{ A[] -> [0]; B[0] -> [1] }",
   5689 	  isl_bool_false },
   5690 	{ &isl_union_pw_multi_aff_involves_nan, "{ A[] -> [NaN]; B[0] -> [1] }",
   5691 	  isl_bool_true },
   5692 	{ &isl_union_pw_multi_aff_involves_nan, "{ A[] -> [0]; B[0] -> [NaN] }",
   5693 	  isl_bool_true },
   5694 	{ &isl_union_pw_multi_aff_involves_nan,
   5695 	  "{ A[] -> [0]; B[0] -> [1, NaN, 5] }",
   5696 	  isl_bool_true },
   5697 	{ &isl_union_pw_multi_aff_involves_locals,
   5698 	  "{ A[] -> [0]; B[0] -> [1] }",
   5699 	  isl_bool_false },
   5700 	{ &isl_union_pw_multi_aff_involves_locals,
   5701 	  "{ A[] -> [0]; B[x] -> [1] : x mod 2 = 0 }",
   5702 	  isl_bool_true },
   5703 	{ &isl_union_pw_multi_aff_involves_locals,
   5704 	  "{ A[] -> [0]; B[x] -> [x // 2] }",
   5705 	  isl_bool_true },
   5706 	{ &isl_union_pw_multi_aff_involves_locals,
   5707 	  "{ A[i] -> [i // 2]; B[0] -> [1] }",
   5708 	  isl_bool_true },
   5709 };
   5710 
   5711 /* Perform some basic tests of test operations on
   5712  * isl_union_pw_multi_aff objects.
   5713  */
   5714 static isl_stat test_upma_test(isl_ctx *ctx)
   5715 {
   5716 	int i;
   5717 	isl_union_pw_multi_aff *upma;
   5718 	isl_bool res;
   5719 
   5720 	for (i = 0; i < ARRAY_SIZE(upma_test_tests); ++i) {
   5721 		const char *str;
   5722 
   5723 		str = upma_test_tests[i].arg;
   5724 		upma = isl_union_pw_multi_aff_read_from_str(ctx, str);
   5725 		res = upma_test_tests[i].fn(upma);
   5726 		isl_union_pw_multi_aff_free(upma);
   5727 		if (res < 0)
   5728 			return isl_stat_error;
   5729 		if (res != upma_test_tests[i].res)
   5730 			isl_die(ctx, isl_error_unknown,
   5731 				"unexpected result", return isl_stat_error);
   5732 	}
   5733 
   5734 	return isl_stat_ok;
   5735 }
   5736 
   5737 struct {
   5738 	__isl_give isl_union_pw_multi_aff *(*fn)(
   5739 		__isl_take isl_union_pw_multi_aff *upma1,
   5740 		__isl_take isl_union_pw_multi_aff *upma2);
   5741 	const char *arg1;
   5742 	const char *arg2;
   5743 	const char *res;
   5744 } upma_bin_tests[] = {
   5745 	{ &isl_union_pw_multi_aff_add, "{ A[] -> [0]; B[0] -> [1] }",
   5746 	  "{ B[x] -> [2] : x >= 0 }", "{ B[0] -> [3] }" },
   5747 	{ &isl_union_pw_multi_aff_union_add, "{ A[] -> [0]; B[0] -> [1] }",
   5748 	  "{ B[x] -> [2] : x >= 0 }",
   5749 	  "{ A[] -> [0]; B[0] -> [3]; B[x] -> [2] : x >= 1 }" },
   5750 	{ &isl_union_pw_multi_aff_pullback_union_pw_multi_aff,
   5751 	  "{ A[] -> B[0]; C[x] -> B[1] : x < 10; C[y] -> B[2] : y >= 10 }",
   5752 	  "{ D[i] -> A[] : i < 0; D[i] -> C[i + 5] : i >= 0 }",
   5753 	  "{ D[i] -> B[0] : i < 0; D[i] -> B[1] : 0 <= i < 5; "
   5754 	    "D[i] -> B[2] : i >= 5 }" },
   5755 	{ &isl_union_pw_multi_aff_union_add, "{ B[x] -> A[1] : x <= 0 }",
   5756 	  "{ B[x] -> C[2] : x > 0 }",
   5757 	  "{ B[x] -> A[1] : x <= 0; B[x] -> C[2] : x > 0 }" },
   5758 	{ &isl_union_pw_multi_aff_union_add, "{ B[x] -> A[1] : x <= 0 }",
   5759 	  "{ B[x] -> A[2] : x >= 0 }",
   5760 	  "{ B[x] -> A[1] : x < 0; B[x] -> A[2] : x > 0; B[0] -> A[3] }" },
   5761 	{
   5762   &isl_union_pw_multi_aff_preimage_domain_wrapped_domain_union_pw_multi_aff,
   5763 	  "{ B[x] -> C[x + 2] }",
   5764 	  "{ D[y] -> B[2y] }",
   5765 	  "{ }" },
   5766 	{
   5767   &isl_union_pw_multi_aff_preimage_domain_wrapped_domain_union_pw_multi_aff,
   5768 	  "{ [A[x] -> B[x + 1]] -> C[x + 2] }",
   5769 	  "{ D[y] -> B[2y] }",
   5770 	  "{ }" },
   5771 	{
   5772   &isl_union_pw_multi_aff_preimage_domain_wrapped_domain_union_pw_multi_aff,
   5773 	  "{ [A[x] -> B[x + 1]] -> C[x + 2]; B[x] -> C[x + 2] }",
   5774 	  "{ D[y] -> A[2y] }",
   5775 	  "{ [D[y] -> B[2y + 1]] -> C[2y + 2] }" },
   5776 	{
   5777   &isl_union_pw_multi_aff_preimage_domain_wrapped_domain_union_pw_multi_aff,
   5778 	  "{ T[A[x] -> B[x + 1]] -> C[x + 2]; B[x] -> C[x + 2] }",
   5779 	  "{ D[y] -> A[2y] }",
   5780 	  "{ T[D[y] -> B[2y + 1]] -> C[2y + 2] }" },
   5781 };
   5782 
   5783 /* Perform some basic tests of binary operations on
   5784  * isl_union_pw_multi_aff objects.
   5785  */
   5786 static int test_bin_upma(isl_ctx *ctx)
   5787 {
   5788 	int i;
   5789 	isl_union_pw_multi_aff *upma1, *upma2, *res;
   5790 	int ok;
   5791 
   5792 	for (i = 0; i < ARRAY_SIZE(upma_bin_tests); ++i) {
   5793 		upma1 = isl_union_pw_multi_aff_read_from_str(ctx,
   5794 							upma_bin_tests[i].arg1);
   5795 		upma2 = isl_union_pw_multi_aff_read_from_str(ctx,
   5796 							upma_bin_tests[i].arg2);
   5797 		res = isl_union_pw_multi_aff_read_from_str(ctx,
   5798 							upma_bin_tests[i].res);
   5799 		upma1 = upma_bin_tests[i].fn(upma1, upma2);
   5800 		ok = isl_union_pw_multi_aff_plain_is_equal(upma1, res);
   5801 		isl_union_pw_multi_aff_free(upma1);
   5802 		isl_union_pw_multi_aff_free(res);
   5803 		if (ok < 0)
   5804 			return -1;
   5805 		if (!ok)
   5806 			isl_die(ctx, isl_error_unknown,
   5807 				"unexpected result", return -1);
   5808 	}
   5809 
   5810 	return 0;
   5811 }
   5812 
   5813 struct {
   5814 	__isl_give isl_union_pw_multi_aff *(*fn)(
   5815 		__isl_take isl_union_pw_multi_aff *upma1,
   5816 		__isl_take isl_union_pw_multi_aff *upma2);
   5817 	const char *arg1;
   5818 	const char *arg2;
   5819 } upma_bin_fail_tests[] = {
   5820 	{ &isl_union_pw_multi_aff_union_add, "{ B[x] -> A[1] : x <= 0 }",
   5821 	  "{ B[x] -> C[2] : x >= 0 }" },
   5822 };
   5823 
   5824 /* Perform some basic tests of binary operations on
   5825  * isl_union_pw_multi_aff objects that are expected to fail.
   5826  */
   5827 static int test_bin_upma_fail(isl_ctx *ctx)
   5828 {
   5829 	int i, n;
   5830 	isl_union_pw_multi_aff *upma1, *upma2;
   5831 	int on_error;
   5832 
   5833 	on_error = isl_options_get_on_error(ctx);
   5834 	isl_options_set_on_error(ctx, ISL_ON_ERROR_CONTINUE);
   5835 	n = ARRAY_SIZE(upma_bin_fail_tests);
   5836 	for (i = 0; i < n; ++i) {
   5837 		upma1 = isl_union_pw_multi_aff_read_from_str(ctx,
   5838 						upma_bin_fail_tests[i].arg1);
   5839 		upma2 = isl_union_pw_multi_aff_read_from_str(ctx,
   5840 						upma_bin_fail_tests[i].arg2);
   5841 		upma1 = upma_bin_fail_tests[i].fn(upma1, upma2);
   5842 		isl_union_pw_multi_aff_free(upma1);
   5843 		if (upma1)
   5844 			break;
   5845 	}
   5846 	isl_options_set_on_error(ctx, on_error);
   5847 	if (i < n)
   5848 		isl_die(ctx, isl_error_unknown,
   5849 			"operation not expected to succeed", return -1);
   5850 
   5851 	return 0;
   5852 }
   5853 
   5854 /* Inputs for basic tests of binary operations on
   5855  * pairs of isl_union_pw_multi_aff and isl_union_set objects.
   5856  * "fn" is the function that is being tested.
   5857  * "arg1" and "arg2" are string descriptions of the inputs.
   5858  * "res" is a string description of the expected result.
   5859  */
   5860 struct {
   5861 	__isl_give isl_union_pw_multi_aff *(*fn)(
   5862 		__isl_take isl_union_pw_multi_aff *upma,
   5863 		__isl_take isl_union_set *uset);
   5864 	const char *arg1;
   5865 	const char *arg2;
   5866 	const char *res;
   5867 } upma_uset_tests[] = {
   5868 	{ &isl_union_pw_multi_aff_intersect_domain_wrapped_range,
   5869 	  "{ A[i] -> B[i] }", "{ B[0] }",
   5870 	  "{ }" },
   5871 	{ &isl_union_pw_multi_aff_intersect_domain_wrapped_domain,
   5872 	  "{ [A[i] -> B[i]] -> C[i + 1] }", "{ A[1]; B[0] }",
   5873 	  "{ [A[1] -> B[1]] -> C[2] }" },
   5874 	{ &isl_union_pw_multi_aff_intersect_domain_wrapped_range,
   5875 	  "{ [A[i] -> B[i]] -> C[i + 1] }", "{ A[1]; B[0] }",
   5876 	  "{ [A[0] -> B[0]] -> C[1] }" },
   5877 	{ &isl_union_pw_multi_aff_intersect_domain_wrapped_range,
   5878 	  "{ [A[i] -> B[i]] -> C[i + 1] }", "[N] -> { B[N] }",
   5879 	  "[N] -> { [A[N] -> B[N]] -> C[N + 1] }" },
   5880 	{ &isl_union_pw_multi_aff_intersect_domain_wrapped_range,
   5881 	  "[M] -> { [A[M] -> B[M]] -> C[M + 1] }", "[N] -> { B[N] }",
   5882 	  "[N, M] -> { [A[N] -> B[N]] -> C[N + 1] : N = M }" },
   5883 	{ &isl_union_pw_multi_aff_intersect_domain_wrapped_range,
   5884 	  "{ [A[] -> B[]] -> C[]; N[A[] -> B[]] -> D[]; [B[] -> A[]] -> E[] }",
   5885 	  "{ B[] }",
   5886 	  "{ [A[] -> B[]] -> C[]; N[A[] -> B[]] -> D[] }" },
   5887 };
   5888 
   5889 /* Perform some basic tests of binary operations on
   5890  * pairs of isl_union_pw_multi_aff and isl_union_set objects.
   5891  */
   5892 static isl_stat test_upma_uset(isl_ctx *ctx)
   5893 {
   5894 	int i;
   5895 	isl_bool ok;
   5896 	isl_union_pw_multi_aff *upma, *res;
   5897 	isl_union_set *uset;
   5898 
   5899 	for (i = 0; i < ARRAY_SIZE(upma_uset_tests); ++i) {
   5900 		upma = isl_union_pw_multi_aff_read_from_str(ctx,
   5901 						    upma_uset_tests[i].arg1);
   5902 		uset = isl_union_set_read_from_str(ctx,
   5903 						    upma_uset_tests[i].arg2);
   5904 		res = isl_union_pw_multi_aff_read_from_str(ctx,
   5905 						    upma_uset_tests[i].res);
   5906 		upma = upma_uset_tests[i].fn(upma, uset);
   5907 		ok = isl_union_pw_multi_aff_plain_is_equal(upma, res);
   5908 		isl_union_pw_multi_aff_free(upma);
   5909 		isl_union_pw_multi_aff_free(res);
   5910 		if (ok < 0)
   5911 			return isl_stat_error;
   5912 		if (!ok)
   5913 			isl_die(ctx, isl_error_unknown,
   5914 				"unexpected result", return isl_stat_error);
   5915 	}
   5916 
   5917 	return isl_stat_ok;
   5918 }
   5919 
   5920 /* Inputs for basic tests of unary operations on isl_multi_pw_aff objects.
   5921  * "fn" is the function that is tested.
   5922  * "arg" is a string description of the input.
   5923  * "res" is a string description of the expected result.
   5924  */
   5925 struct {
   5926 	__isl_give isl_multi_pw_aff *(*fn)(__isl_take isl_multi_pw_aff *mpa);
   5927 	const char *arg;
   5928 	const char *res;
   5929 } mpa_un_tests[] = {
   5930 	{ &isl_multi_pw_aff_range_factor_domain,
   5931 	  "{ A[x] -> [B[(1 : x >= 5)] -> C[(2 : x <= 10)]] }",
   5932 	  "{ A[x] -> B[(1 : x >= 5)] }" },
   5933 	{ &isl_multi_pw_aff_range_factor_range,
   5934 	  "{ A[x] -> [B[(1 : x >= 5)] -> C[(2 : x <= 10)]] }",
   5935 	  "{ A[y] -> C[(2 : y <= 10)] }" },
   5936 	{ &isl_multi_pw_aff_range_factor_domain,
   5937 	  "{ A[x] -> [B[(1 : x >= 5)] -> C[]] }",
   5938 	  "{ A[x] -> B[(1 : x >= 5)] }" },
   5939 	{ &isl_multi_pw_aff_range_factor_range,
   5940 	  "{ A[x] -> [B[(1 : x >= 5)] -> C[]] }",
   5941 	  "{ A[y] -> C[] }" },
   5942 	{ &isl_multi_pw_aff_range_factor_domain,
   5943 	  "{ A[x] -> [B[] -> C[(2 : x <= 10)]] }",
   5944 	  "{ A[x] -> B[] }" },
   5945 	{ &isl_multi_pw_aff_range_factor_range,
   5946 	  "{ A[x] -> [B[] -> C[(2 : x <= 10)]] }",
   5947 	  "{ A[y] -> C[(2 : y <= 10)] }" },
   5948 	{ &isl_multi_pw_aff_range_factor_domain,
   5949 	  "{ A[x] -> [B[] -> C[]] }",
   5950 	  "{ A[x] -> B[] }" },
   5951 	{ &isl_multi_pw_aff_range_factor_range,
   5952 	  "{ A[x] -> [B[] -> C[]] }",
   5953 	  "{ A[y] -> C[] }" },
   5954 	{ &isl_multi_pw_aff_factor_range,
   5955 	  "{ [B[] -> C[]] }",
   5956 	  "{ C[] }" },
   5957 	{ &isl_multi_pw_aff_range_factor_domain,
   5958 	  "{ A[x] -> [B[] -> C[]] : x >= 0 }",
   5959 	  "{ A[x] -> B[] : x >= 0 }" },
   5960 	{ &isl_multi_pw_aff_range_factor_range,
   5961 	  "{ A[x] -> [B[] -> C[]] : x >= 0 }",
   5962 	  "{ A[y] -> C[] : y >= 0 }" },
   5963 	{ &isl_multi_pw_aff_factor_range,
   5964 	  "[N] -> { [B[] -> C[]] : N >= 0 }",
   5965 	  "[N] -> { C[] : N >= 0 }" },
   5966 };
   5967 
   5968 /* Perform some basic tests of unary operations on isl_multi_pw_aff objects.
   5969  */
   5970 static int test_un_mpa(isl_ctx *ctx)
   5971 {
   5972 	int i;
   5973 	isl_bool ok;
   5974 	isl_multi_pw_aff *mpa, *res;
   5975 
   5976 	for (i = 0; i < ARRAY_SIZE(mpa_un_tests); ++i) {
   5977 		mpa = isl_multi_pw_aff_read_from_str(ctx, mpa_un_tests[i].arg);
   5978 		res = isl_multi_pw_aff_read_from_str(ctx, mpa_un_tests[i].res);
   5979 		mpa = mpa_un_tests[i].fn(mpa);
   5980 		ok = isl_multi_pw_aff_plain_is_equal(mpa, res);
   5981 		isl_multi_pw_aff_free(mpa);
   5982 		isl_multi_pw_aff_free(res);
   5983 		if (ok < 0)
   5984 			return -1;
   5985 		if (!ok)
   5986 			isl_die(ctx, isl_error_unknown,
   5987 				"unexpected result", return -1);
   5988 	}
   5989 
   5990 	return 0;
   5991 }
   5992 
   5993 /* Inputs for basic tests of binary operations on isl_multi_pw_aff objects.
   5994  * "fn" is the function that is tested.
   5995  * "arg1" and "arg2" are string descriptions of the inputs.
   5996  * "res" is a string description of the expected result.
   5997  */
   5998 struct {
   5999 	__isl_give isl_multi_pw_aff *(*fn)(
   6000 		__isl_take isl_multi_pw_aff *mpa1,
   6001 		__isl_take isl_multi_pw_aff *mpa2);
   6002 	const char *arg1;
   6003 	const char *arg2;
   6004 	const char *res;
   6005 } mpa_bin_tests[] = {
   6006 	{ &isl_multi_pw_aff_add, "{ A[] -> [1] }", "{ A[] -> [2] }",
   6007 	  "{ A[] -> [3] }" },
   6008 	{ &isl_multi_pw_aff_add, "{ A[x] -> [(1 : x >= 5)] }",
   6009 	  "{ A[x] -> [(x : x <= 10)] }",
   6010 	  "{ A[x] -> [(1 + x : 5 <= x <= 10)] }" },
   6011 	{ &isl_multi_pw_aff_add, "{ A[x] -> [] : x >= 5 }",
   6012 	  "{ A[x] -> [] : x <= 10 }",
   6013 	  "{ A[x] -> [] : 5 <= x <= 10 }" },
   6014 	{ &isl_multi_pw_aff_add, "{ A[x] -> [] : x >= 5 }",
   6015 	  "[N] -> { A[x] -> [] : x <= N }",
   6016 	  "[N] -> { A[x] -> [] : 5 <= x <= N }" },
   6017 	{ &isl_multi_pw_aff_add,
   6018 	  "[N] -> { A[x] -> [] : x <= N }",
   6019 	  "{ A[x] -> [] : x >= 5 }",
   6020 	  "[N] -> { A[x] -> [] : 5 <= x <= N }" },
   6021 	{ &isl_multi_pw_aff_range_product, "{ A[x] -> B[(1 : x >= 5)] }",
   6022 	  "{ A[y] -> C[(2 : y <= 10)] }",
   6023 	  "{ A[x] -> [B[(1 : x >= 5)] -> C[(2 : x <= 10)]] }" },
   6024 	{ &isl_multi_pw_aff_range_product, "{ A[x] -> B[1] : x >= 5 }",
   6025 	  "{ A[y] -> C[2] : y <= 10 }",
   6026 	  "{ A[x] -> [B[(1 : x >= 5)] -> C[(2 : x <= 10)]] }" },
   6027 	{ &isl_multi_pw_aff_range_product, "{ A[x] -> B[1] : x >= 5 }",
   6028 	  "[N] -> { A[y] -> C[2] : y <= N }",
   6029 	  "[N] -> { A[x] -> [B[(1 : x >= 5)] -> C[(2 : x <= N)]] }" },
   6030 	{ &isl_multi_pw_aff_range_product, "[N] -> { A[x] -> B[1] : x >= N }",
   6031 	  "{ A[y] -> C[2] : y <= 10 }",
   6032 	  "[N] -> { A[x] -> [B[(1 : x >= N)] -> C[(2 : x <= 10)]] }" },
   6033 	{ &isl_multi_pw_aff_range_product, "{ A[] -> B[1] }", "{ A[] -> C[2] }",
   6034 	  "{ A[] -> [B[1] -> C[2]] }" },
   6035 	{ &isl_multi_pw_aff_range_product, "{ A[] -> B[] }", "{ A[] -> C[] }",
   6036 	  "{ A[] -> [B[] -> C[]] }" },
   6037 	{ &isl_multi_pw_aff_range_product, "{ A[x] -> B[(1 : x >= 5)] }",
   6038 	  "{ A[y] -> C[] : y <= 10 }",
   6039 	  "{ A[x] -> [B[(1 : x >= 5)] -> C[]] : x <= 10 }" },
   6040 	{ &isl_multi_pw_aff_range_product, "{ A[y] -> C[] : y <= 10 }",
   6041 	  "{ A[x] -> B[(1 : x >= 5)] }",
   6042 	  "{ A[x] -> [C[] -> B[(1 : x >= 5)]] : x <= 10 }" },
   6043 	{ &isl_multi_pw_aff_product, "{ A[x] -> B[(1 : x >= 5)] }",
   6044 	  "{ A[y] -> C[(2 : y <= 10)] }",
   6045 	  "{ [A[x] -> A[y]] -> [B[(1 : x >= 5)] -> C[(2 : y <= 10)]] }" },
   6046 	{ &isl_multi_pw_aff_product, "{ A[x] -> B[(1 : x >= 5)] }",
   6047 	  "{ A[y] -> C[] : y <= 10 }",
   6048 	  "{ [A[x] -> A[y]] -> [B[(1 : x >= 5)] -> C[]] : y <= 10 }" },
   6049 	{ &isl_multi_pw_aff_product, "{ A[y] -> C[] : y <= 10 }",
   6050 	  "{ A[x] -> B[(1 : x >= 5)] }",
   6051 	  "{ [A[y] -> A[x]] -> [C[] -> B[(1 : x >= 5)]] : y <= 10 }" },
   6052 	{ &isl_multi_pw_aff_product, "{ A[x] -> B[(1 : x >= 5)] }",
   6053 	  "[N] -> { A[y] -> C[] : y <= N }",
   6054 	  "[N] -> { [A[x] -> A[y]] -> [B[(1 : x >= 5)] -> C[]] : y <= N }" },
   6055 	{ &isl_multi_pw_aff_product, "[N] -> { A[y] -> C[] : y <= N }",
   6056 	  "{ A[x] -> B[(1 : x >= 5)] }",
   6057 	  "[N] -> { [A[y] -> A[x]] -> [C[] -> B[(1 : x >= 5)]] : y <= N }" },
   6058 	{ &isl_multi_pw_aff_product, "{ A[x] -> B[] : x >= 5 }",
   6059 	  "{ A[y] -> C[] : y <= 10 }",
   6060 	  "{ [A[x] -> A[y]] -> [B[] -> C[]] : x >= 5 and y <= 10 }" },
   6061 	{ &isl_multi_pw_aff_product, "{ A[] -> B[1] }", "{ A[] -> C[2] }",
   6062 	  "{ [A[] -> A[]] -> [B[1] -> C[2]] }" },
   6063 	{ &isl_multi_pw_aff_product, "{ A[] -> B[] }", "{ A[] -> C[] }",
   6064 	  "{ [A[] -> A[]] -> [B[] -> C[]] }" },
   6065 	{ &isl_multi_pw_aff_pullback_multi_pw_aff,
   6066 	  "{ B[i,j] -> C[i + 2j] }", "{ A[a,b] -> B[b,a] }",
   6067 	  "{ A[a,b] -> C[b + 2a] }" },
   6068 	{ &isl_multi_pw_aff_pullback_multi_pw_aff,
   6069 	  "{ B[i,j] -> C[i + 2j] }",
   6070 	  "{ A[a,b] -> B[(b : b > a),(a : b > a)] }",
   6071 	  "{ A[a,b] -> C[(b + 2a : b > a)] }" },
   6072 	{ &isl_multi_pw_aff_pullback_multi_pw_aff,
   6073 	  "{ B[i,j] -> C[(i + 2j : j > 4)] }",
   6074 	  "{ A[a,b] -> B[(b : b > a),(a : b > a)] }",
   6075 	  "{ A[a,b] -> C[(b + 2a : b > a > 4)] }" },
   6076 	{ &isl_multi_pw_aff_pullback_multi_pw_aff,
   6077 	  "{ B[i,j] -> C[] }",
   6078 	  "{ A[a,b] -> B[(b : b > a),(a : b > a)] }",
   6079 	  "{ A[a,b] -> C[] }" },
   6080 	{ &isl_multi_pw_aff_pullback_multi_pw_aff,
   6081 	  "{ B[i,j] -> C[] : i > j }",
   6082 	  "{ A[a,b] -> B[b,a] }",
   6083 	  "{ A[a,b] -> C[] : b > a }" },
   6084 	{ &isl_multi_pw_aff_pullback_multi_pw_aff,
   6085 	  "{ B[i,j] -> C[] : j > 5 }",
   6086 	  "{ A[a,b] -> B[(b : b > a),(a : b > a)] }",
   6087 	  "{ A[a,b] -> C[] : b > a > 5 }" },
   6088 	{ &isl_multi_pw_aff_pullback_multi_pw_aff,
   6089 	  "[N] -> { B[i,j] -> C[] : j > N }",
   6090 	  "{ A[a,b] -> B[(b : b > a),(a : b > a)] }",
   6091 	  "[N] -> { A[a,b] -> C[] : b > a > N }" },
   6092 	{ &isl_multi_pw_aff_pullback_multi_pw_aff,
   6093 	  "[M,N] -> { B[] -> C[] : N > 5 }",
   6094 	  "[M,N] -> { A[] -> B[] : M > N }",
   6095 	  "[M,N] -> { A[] -> C[] : M > N > 5 }" },
   6096 };
   6097 
   6098 /* Perform some basic tests of binary operations on isl_multi_pw_aff objects.
   6099  */
   6100 static int test_bin_mpa(isl_ctx *ctx)
   6101 {
   6102 	int i;
   6103 	isl_bool ok;
   6104 	isl_multi_pw_aff *mpa1, *mpa2, *res;
   6105 
   6106 	for (i = 0; i < ARRAY_SIZE(mpa_bin_tests); ++i) {
   6107 		mpa1 = isl_multi_pw_aff_read_from_str(ctx,
   6108 							mpa_bin_tests[i].arg1);
   6109 		mpa2 = isl_multi_pw_aff_read_from_str(ctx,
   6110 							mpa_bin_tests[i].arg2);
   6111 		res = isl_multi_pw_aff_read_from_str(ctx,
   6112 							mpa_bin_tests[i].res);
   6113 		mpa1 = mpa_bin_tests[i].fn(mpa1, mpa2);
   6114 		ok = isl_multi_pw_aff_plain_is_equal(mpa1, res);
   6115 		isl_multi_pw_aff_free(mpa1);
   6116 		isl_multi_pw_aff_free(res);
   6117 		if (ok < 0)
   6118 			return -1;
   6119 		if (!ok)
   6120 			isl_die(ctx, isl_error_unknown,
   6121 				"unexpected result", return -1);
   6122 	}
   6123 
   6124 	return 0;
   6125 }
   6126 
   6127 /* Inputs for basic tests of unary operations on
   6128  * isl_multi_union_pw_aff objects.
   6129  * "fn" is the function that is tested.
   6130  * "arg" is a string description of the input.
   6131  * "res" is a string description of the expected result.
   6132  */
   6133 struct {
   6134 	__isl_give isl_multi_union_pw_aff *(*fn)(
   6135 		__isl_take isl_multi_union_pw_aff *mupa);
   6136 	const char *arg;
   6137 	const char *res;
   6138 } mupa_un_tests[] = {
   6139 	{ &isl_multi_union_pw_aff_factor_range,
   6140 	  "[B[{ A[] -> [1] }] -> C[{ A[] -> [2] }]]",
   6141 	  "C[{ A[] -> [2] }]" },
   6142 	{ &isl_multi_union_pw_aff_factor_range,
   6143 	  "[B[] -> C[{ A[] -> [2] }]]",
   6144 	  "C[{ A[] -> [2] }]" },
   6145 	{ &isl_multi_union_pw_aff_factor_range,
   6146 	  "[B[{ A[] -> [1] }] -> C[]]",
   6147 	  "C[]" },
   6148 	{ &isl_multi_union_pw_aff_factor_range,
   6149 	  "[B[] -> C[]]",
   6150 	  "C[]" },
   6151 	{ &isl_multi_union_pw_aff_factor_range,
   6152 	  "([B[] -> C[]] : { A[x] : x >= 0 })",
   6153 	  "(C[] : { A[x] : x >= 0 })" },
   6154 	{ &isl_multi_union_pw_aff_factor_range,
   6155 	  "[N] -> ([B[] -> C[]] : { A[x] : x <= N })",
   6156 	  "[N] -> (C[] : { A[x] : x <= N })" },
   6157 	{ &isl_multi_union_pw_aff_factor_range,
   6158 	  "[N] -> ([B[] -> C[]] : { : N >= 0 })",
   6159 	  "[N] -> (C[] : { : N >= 0 })" },
   6160 };
   6161 
   6162 /* Perform some basic tests of unary operations on
   6163  * isl_multi_union_pw_aff objects.
   6164  */
   6165 static int test_un_mupa(isl_ctx *ctx)
   6166 {
   6167 	int i;
   6168 	isl_bool ok;
   6169 	isl_multi_union_pw_aff *mupa, *res;
   6170 
   6171 	for (i = 0; i < ARRAY_SIZE(mupa_un_tests); ++i) {
   6172 		mupa = isl_multi_union_pw_aff_read_from_str(ctx,
   6173 							mupa_un_tests[i].arg);
   6174 		res = isl_multi_union_pw_aff_read_from_str(ctx,
   6175 							mupa_un_tests[i].res);
   6176 		mupa = mupa_un_tests[i].fn(mupa);
   6177 		ok = isl_multi_union_pw_aff_plain_is_equal(mupa, res);
   6178 		isl_multi_union_pw_aff_free(mupa);
   6179 		isl_multi_union_pw_aff_free(res);
   6180 		if (ok < 0)
   6181 			return -1;
   6182 		if (!ok)
   6183 			isl_die(ctx, isl_error_unknown,
   6184 				"unexpected result", return -1);
   6185 	}
   6186 
   6187 	return 0;
   6188 }
   6189 
   6190 /* Inputs for basic tests of binary operations on
   6191  * isl_multi_union_pw_aff objects.
   6192  * "fn" is the function that is tested.
   6193  * "arg1" and "arg2" are string descriptions of the inputs.
   6194  * "res" is a string description of the expected result.
   6195  */
   6196 struct {
   6197 	__isl_give isl_multi_union_pw_aff *(*fn)(
   6198 		__isl_take isl_multi_union_pw_aff *mupa1,
   6199 		__isl_take isl_multi_union_pw_aff *mupa2);
   6200 	const char *arg1;
   6201 	const char *arg2;
   6202 	const char *res;
   6203 } mupa_bin_tests[] = {
   6204 	{ &isl_multi_union_pw_aff_add, "[{ A[] -> [1] }]", "[{ A[] -> [2] }]",
   6205 	  "[{ A[] -> [3] }]" },
   6206 	{ &isl_multi_union_pw_aff_sub, "[{ A[] -> [1] }]", "[{ A[] -> [2] }]",
   6207 	  "[{ A[] -> [-1] }]" },
   6208 	{ &isl_multi_union_pw_aff_add,
   6209 	  "[{ A[] -> [1]; B[] -> [4] }]",
   6210 	  "[{ A[] -> [2]; C[] -> [5] }]",
   6211 	  "[{ A[] -> [3] }]" },
   6212 	{ &isl_multi_union_pw_aff_union_add,
   6213 	  "[{ A[] -> [1]; B[] -> [4] }]",
   6214 	  "[{ A[] -> [2]; C[] -> [5] }]",
   6215 	  "[{ A[] -> [3]; B[] -> [4]; C[] -> [5] }]" },
   6216 	{ &isl_multi_union_pw_aff_add, "[{ A[x] -> [(1)] : x >= 5 }]",
   6217 	  "[{ A[x] -> [(x)] : x <= 10 }]",
   6218 	  "[{ A[x] -> [(1 + x)] : 5 <= x <= 10 }]" },
   6219 	{ &isl_multi_union_pw_aff_add, "([] : { A[x] : x >= 5 })",
   6220 	  "([] : { A[x] : x <= 10 })",
   6221 	  "([] : { A[x] : 5 <= x <= 10 })" },
   6222 	{ &isl_multi_union_pw_aff_add, "([] : { A[x] : x >= 5 })",
   6223 	  "[N] -> ([] : { A[x] : x <= N })",
   6224 	  "[N] -> ([] : { A[x] : 5 <= x <= N })" },
   6225 	{ &isl_multi_union_pw_aff_add, "[N] -> ([] : { A[x] : x >= N })",
   6226 	  "([] : { A[x] : x <= 10 })",
   6227 	  "[N] -> ([] : { A[x] : N <= x <= 10 })" },
   6228 	{ &isl_multi_union_pw_aff_union_add, "[{ A[x] -> [(1)] : x >= 5 }]",
   6229 	  "[{ A[x] -> [(x)] : x <= 10 }]",
   6230 	  "[{ A[x] -> [(1 + x)] : 5 <= x <= 10; "
   6231 	     "A[x] -> [(1)] : x > 10; A[x] -> [(x)] : x < 5 }]" },
   6232 	{ &isl_multi_union_pw_aff_union_add, "([] : { A[x] : x >= 5 })",
   6233 	  "([] : { A[x] : x <= 10 })",
   6234 	  "([] : { A[x] })" },
   6235 	{ &isl_multi_union_pw_aff_union_add, "([] : { A[x] : x >= 0 })",
   6236 	  "[N] -> ([] : { A[x] : x >= N })",
   6237 	  "[N] -> ([] : { A[x] : x >= 0 or x >= N })" },
   6238 	{ &isl_multi_union_pw_aff_union_add,
   6239 	  "[N] -> ([] : { A[] : N >= 0})",
   6240 	  "[N] -> ([] : { A[] : N <= 0})",
   6241 	  "[N] -> ([] : { A[] })" },
   6242 	{ &isl_multi_union_pw_aff_union_add,
   6243 	  "[N] -> ([] : { A[] })",
   6244 	  "[N] -> ([] : { : })",
   6245 	  "[N] -> ([] : { : })" },
   6246 	{ &isl_multi_union_pw_aff_union_add,
   6247 	  "[N] -> ([] : { : })",
   6248 	  "[N] -> ([] : { A[] })",
   6249 	  "[N] -> ([] : { : })" },
   6250 	{ &isl_multi_union_pw_aff_union_add,
   6251 	  "[N] -> ([] : { : N >= 0})",
   6252 	  "[N] -> ([] : { : N <= 0})",
   6253 	  "[N] -> ([] : { : })" },
   6254 	{ &isl_multi_union_pw_aff_range_product,
   6255 	  "B[{ A[] -> [1] }]",
   6256 	  "C[{ A[] -> [2] }]",
   6257 	  "[B[{ A[] -> [1] }] -> C[{ A[] -> [2] }]]" },
   6258 	{ &isl_multi_union_pw_aff_range_product,
   6259 	  "(B[] : { A[x] : x >= 5 })",
   6260 	  "(C[] : { A[x] : x <= 10 })",
   6261 	  "([B[] -> C[]] : { A[x] : 5 <= x <= 10 })" },
   6262 	{ &isl_multi_union_pw_aff_range_product,
   6263 	  "B[{ A[x] -> [x + 1] : x >= 5 }]",
   6264 	  "(C[] : { A[x] : x <= 10 })",
   6265 	  "[B[{ A[x] -> [x + 1] : 5 <= x <= 10 }] -> C[]]" },
   6266 	{ &isl_multi_union_pw_aff_range_product,
   6267 	  "(C[] : { A[x] : x <= 10 })",
   6268 	  "B[{ A[x] -> [x + 1] : x >= 5 }]",
   6269 	  "[C[] -> B[{ A[x] -> [x + 1] : 5 <= x <= 10 }]]" },
   6270 	{ &isl_multi_union_pw_aff_range_product,
   6271 	  "B[{ A[x] -> [x + 1] : x >= 5 }]",
   6272 	  "[N] -> (C[] : { A[x] : x <= N })",
   6273 	  "[N] -> [B[{ A[x] -> [x + 1] : 5 <= x <= N }] -> C[]]" },
   6274 	{ &isl_multi_union_pw_aff_range_product,
   6275 	  "[N] -> (C[] : { A[x] : x <= N })",
   6276 	  "B[{ A[x] -> [x + 1] : x >= 5 }]",
   6277 	  "[N] -> [C[] -> B[{ A[x] -> [x + 1] : 5 <= x <= N }]]" },
   6278 	{ &isl_multi_union_pw_aff_range_product,
   6279 	  "B[{ A[] -> [1]; D[] -> [3] }]",
   6280 	  "C[{ A[] -> [2] }]",
   6281 	  "[B[{ A[] -> [1]; D[] -> [3] }] -> C[{ A[] -> [2] }]]" },
   6282 	{ &isl_multi_union_pw_aff_range_product,
   6283 	  "B[] }]",
   6284 	  "(C[] : { A[x] })",
   6285 	  "([B[] -> C[]] : { A[x] })" },
   6286 	{ &isl_multi_union_pw_aff_range_product,
   6287 	  "(B[] : { A[x] })",
   6288 	  "C[] }]",
   6289 	  "([B[] -> C[]] : { A[x] })" },
   6290 };
   6291 
   6292 /* Perform some basic tests of binary operations on
   6293  * isl_multi_union_pw_aff objects.
   6294  */
   6295 static int test_bin_mupa(isl_ctx *ctx)
   6296 {
   6297 	int i;
   6298 	isl_bool ok;
   6299 	isl_multi_union_pw_aff *mupa1, *mupa2, *res;
   6300 
   6301 	for (i = 0; i < ARRAY_SIZE(mupa_bin_tests); ++i) {
   6302 		mupa1 = isl_multi_union_pw_aff_read_from_str(ctx,
   6303 							mupa_bin_tests[i].arg1);
   6304 		mupa2 = isl_multi_union_pw_aff_read_from_str(ctx,
   6305 							mupa_bin_tests[i].arg2);
   6306 		res = isl_multi_union_pw_aff_read_from_str(ctx,
   6307 							mupa_bin_tests[i].res);
   6308 		mupa1 = mupa_bin_tests[i].fn(mupa1, mupa2);
   6309 		ok = isl_multi_union_pw_aff_plain_is_equal(mupa1, res);
   6310 		isl_multi_union_pw_aff_free(mupa1);
   6311 		isl_multi_union_pw_aff_free(res);
   6312 		if (ok < 0)
   6313 			return -1;
   6314 		if (!ok)
   6315 			isl_die(ctx, isl_error_unknown,
   6316 				"unexpected result", return -1);
   6317 	}
   6318 
   6319 	return 0;
   6320 }
   6321 
   6322 /* Inputs for basic tests of binary operations on
   6323  * pairs of isl_multi_union_pw_aff and isl_set objects.
   6324  * "fn" is the function that is tested.
   6325  * "arg1" and "arg2" are string descriptions of the inputs.
   6326  * "res" is a string description of the expected result.
   6327  */
   6328 struct {
   6329 	__isl_give isl_multi_union_pw_aff *(*fn)(
   6330 		__isl_take isl_multi_union_pw_aff *mupa,
   6331 		__isl_take isl_set *set);
   6332 	const char *arg1;
   6333 	const char *arg2;
   6334 	const char *res;
   6335 } mupa_set_tests[] = {
   6336 	{ &isl_multi_union_pw_aff_intersect_range,
   6337 	  "C[{ B[i,j] -> [i + 2j] }]", "{ C[1] }",
   6338 	  "C[{ B[i,j] -> [i + 2j] : i + 2j = 1 }]" },
   6339 	{ &isl_multi_union_pw_aff_intersect_range,
   6340 	  "C[{ B[i,j] -> [i + 2j] }]", "[N] -> { C[N] }",
   6341 	  "[N] -> C[{ B[i,j] -> [i + 2j] : i + 2j = N }]" },
   6342 	{ &isl_multi_union_pw_aff_intersect_range,
   6343 	  "[N] -> C[{ B[i,j] -> [i + 2j + N] }]", "{ C[1] }",
   6344 	  "[N] -> C[{ B[i,j] -> [i + 2j + N] : i + 2j + N = 1 }]" },
   6345 	{ &isl_multi_union_pw_aff_intersect_range,
   6346 	  "C[{ B[i,j] -> [i + 2j] }]", "[N] -> { C[x] : N >= 0 }",
   6347 	  "[N] -> C[{ B[i,j] -> [i + 2j] : N >= 0 }]" },
   6348 	{ &isl_multi_union_pw_aff_intersect_range,
   6349 	  "C[]", "{ C[] }", "C[]" },
   6350 	{ &isl_multi_union_pw_aff_intersect_range,
   6351 	  "[N] -> (C[] : { : N >= 0 })",
   6352 	  "{ C[] }",
   6353 	  "[N] -> (C[] : { : N >= 0 })" },
   6354 	{ &isl_multi_union_pw_aff_intersect_range,
   6355 	  "(C[] : { A[a,b] })",
   6356 	  "{ C[] }",
   6357 	  "(C[] : { A[a,b] })" },
   6358 	{ &isl_multi_union_pw_aff_intersect_range,
   6359 	  "[N] -> (C[] : { A[a,b] : a,b <= N })",
   6360 	  "{ C[] }",
   6361 	  "[N] -> (C[] : { A[a,b] : a,b <= N })" },
   6362 	{ &isl_multi_union_pw_aff_intersect_range,
   6363 	  "C[]",
   6364 	  "[N] -> { C[] : N >= 0 }",
   6365 	  "[N] -> (C[] : { : N >= 0 })" },
   6366 	{ &isl_multi_union_pw_aff_intersect_range,
   6367 	  "(C[] : { A[a,b] })",
   6368 	  "[N] -> { C[] : N >= 0 }",
   6369 	  "[N] -> (C[] : { A[a,b] : N >= 0 })" },
   6370 	{ &isl_multi_union_pw_aff_intersect_range,
   6371 	  "[N] -> (C[] : { : N >= 0 })",
   6372 	  "[N] -> { C[] : N < 1024 }",
   6373 	  "[N] -> (C[] : { : 0 <= N < 1024 })" },
   6374 	{ &isl_multi_union_pw_aff_intersect_params,
   6375 	  "C[{ B[i,j] -> [i + 2j] }]", "[N] -> { : N >= 0 }",
   6376 	  "[N] -> C[{ B[i,j] -> [i + 2j] : N >= 0}]" },
   6377 	{ &isl_multi_union_pw_aff_intersect_params,
   6378 	  "[N] -> C[{ B[i,j] -> [i + 2j] : N <= 256 }]", "[N] -> { : N >= 0 }",
   6379 	  "[N] -> C[{ B[i,j] -> [i + 2j] : 0 <= N <= 256 }]" },
   6380 	{ &isl_multi_union_pw_aff_intersect_params,
   6381 	  "[N] -> C[{ B[i,j] -> [i + 2j] : N <= 256 }]", "{ : }",
   6382 	  "[N] -> C[{ B[i,j] -> [i + 2j] : N <= 256 }]" },
   6383 	{ &isl_multi_union_pw_aff_intersect_params,
   6384 	  "C[]", "[N] -> { : N >= 0 }",
   6385 	  "[N] -> (C[] : { : N >= 0 })" },
   6386 	{ &isl_multi_union_pw_aff_intersect_params,
   6387 	  "(C[] : { A[a,b] })", "[N] -> { : N >= 0 }",
   6388 	  "[N] -> (C[] : { A[a,b] : N >= 0 })" },
   6389 	{ &isl_multi_union_pw_aff_intersect_params,
   6390 	  "[N] -> (C[] : { A[a,N] })", "{ : }",
   6391 	  "[N] -> (C[] : { A[a,N] })" },
   6392 	{ &isl_multi_union_pw_aff_intersect_params,
   6393 	  "[N] -> (C[] : { A[a,b] : N <= 256 })", "[N] -> { : N >= 0 }",
   6394 	  "[N] -> (C[] : { A[a,b] : 0 <= N <= 256 })" },
   6395 };
   6396 
   6397 /* Perform some basic tests of binary operations on
   6398  * pairs of isl_multi_union_pw_aff and isl_set objects.
   6399  */
   6400 static int test_mupa_set(isl_ctx *ctx)
   6401 {
   6402 	int i;
   6403 	isl_bool ok;
   6404 	isl_multi_union_pw_aff *mupa, *res;
   6405 	isl_set *set;
   6406 
   6407 	for (i = 0; i < ARRAY_SIZE(mupa_set_tests); ++i) {
   6408 		mupa = isl_multi_union_pw_aff_read_from_str(ctx,
   6409 						    mupa_set_tests[i].arg1);
   6410 		set = isl_set_read_from_str(ctx, mupa_set_tests[i].arg2);
   6411 		res = isl_multi_union_pw_aff_read_from_str(ctx,
   6412 						    mupa_set_tests[i].res);
   6413 		mupa = mupa_set_tests[i].fn(mupa, set);
   6414 		ok = isl_multi_union_pw_aff_plain_is_equal(mupa, res);
   6415 		isl_multi_union_pw_aff_free(mupa);
   6416 		isl_multi_union_pw_aff_free(res);
   6417 		if (ok < 0)
   6418 			return -1;
   6419 		if (!ok)
   6420 			isl_die(ctx, isl_error_unknown,
   6421 				"unexpected result", return -1);
   6422 	}
   6423 
   6424 	return 0;
   6425 }
   6426 
   6427 /* Inputs for basic tests of binary operations on
   6428  * pairs of isl_multi_union_pw_aff and isl_union_set objects.
   6429  * "fn" is the function that is tested.
   6430  * "arg1" and "arg2" are string descriptions of the inputs.
   6431  * "res" is a string description of the expected result.
   6432  */
   6433 struct {
   6434 	__isl_give isl_multi_union_pw_aff *(*fn)(
   6435 		__isl_take isl_multi_union_pw_aff *mupa,
   6436 		__isl_take isl_union_set *uset);
   6437 	const char *arg1;
   6438 	const char *arg2;
   6439 	const char *res;
   6440 } mupa_uset_tests[] = {
   6441 	{ &isl_multi_union_pw_aff_intersect_domain,
   6442 	  "C[{ B[i,j] -> [i + 2j] }]", "{ B[i,i] }",
   6443 	  "C[{ B[i,i] -> [3i] }]" },
   6444 	{ &isl_multi_union_pw_aff_intersect_domain,
   6445 	  "(C[] : { B[i,j] })", "{ B[i,i] }",
   6446 	  "(C[] : { B[i,i] })" },
   6447 	{ &isl_multi_union_pw_aff_intersect_domain,
   6448 	  "(C[] : { B[i,j] })", "[N] -> { B[N,N] }",
   6449 	  "[N] -> (C[] : { B[N,N] })" },
   6450 	{ &isl_multi_union_pw_aff_intersect_domain,
   6451 	  "C[]", "{ B[i,i] }",
   6452 	  "(C[] : { B[i,i] })" },
   6453 	{ &isl_multi_union_pw_aff_intersect_domain,
   6454 	  "[N] -> (C[] : { : N >= 0 })", "{ B[i,i] }",
   6455 	  "[N] -> (C[] : { B[i,i] : N >= 0 })" },
   6456 };
   6457 
   6458 /* Perform some basic tests of binary operations on
   6459  * pairs of isl_multi_union_pw_aff and isl_union_set objects.
   6460  */
   6461 static int test_mupa_uset(isl_ctx *ctx)
   6462 {
   6463 	int i;
   6464 	isl_bool ok;
   6465 	isl_multi_union_pw_aff *mupa, *res;
   6466 	isl_union_set *uset;
   6467 
   6468 	for (i = 0; i < ARRAY_SIZE(mupa_uset_tests); ++i) {
   6469 		mupa = isl_multi_union_pw_aff_read_from_str(ctx,
   6470 						    mupa_uset_tests[i].arg1);
   6471 		uset = isl_union_set_read_from_str(ctx,
   6472 						    mupa_uset_tests[i].arg2);
   6473 		res = isl_multi_union_pw_aff_read_from_str(ctx,
   6474 						    mupa_uset_tests[i].res);
   6475 		mupa = mupa_uset_tests[i].fn(mupa, uset);
   6476 		ok = isl_multi_union_pw_aff_plain_is_equal(mupa, res);
   6477 		isl_multi_union_pw_aff_free(mupa);
   6478 		isl_multi_union_pw_aff_free(res);
   6479 		if (ok < 0)
   6480 			return -1;
   6481 		if (!ok)
   6482 			isl_die(ctx, isl_error_unknown,
   6483 				"unexpected result", return -1);
   6484 	}
   6485 
   6486 	return 0;
   6487 }
   6488 
   6489 /* Inputs for basic tests of binary operations on
   6490  * pairs of isl_multi_union_pw_aff and isl_multi_aff objects.
   6491  * "fn" is the function that is tested.
   6492  * "arg1" and "arg2" are string descriptions of the inputs.
   6493  * "res" is a string description of the expected result.
   6494  */
   6495 struct {
   6496 	__isl_give isl_multi_union_pw_aff *(*fn)(
   6497 		__isl_take isl_multi_union_pw_aff *mupa,
   6498 		__isl_take isl_multi_aff *ma);
   6499 	const char *arg1;
   6500 	const char *arg2;
   6501 	const char *res;
   6502 } mupa_ma_tests[] = {
   6503 	{ &isl_multi_union_pw_aff_apply_multi_aff,
   6504 	  "C[{ A[i,j] -> [i]; B[i,j] -> [j] }, "
   6505 	    "{ A[i,j] -> [j]; B[i,j] -> [i] }]",
   6506 	  "{ C[a,b] -> D[b,a] }",
   6507 	  "D[{ A[i,j] -> [j]; B[i,j] -> [i] }, "
   6508 	    "{ A[i,j] -> [i]; B[i,j] -> [j] }]" },
   6509 	{ &isl_multi_union_pw_aff_apply_multi_aff,
   6510 	  "C[{ A[i,j] -> [i] : i >= 0; B[i,j] -> [j] }, "
   6511 	    "{ A[i,j] -> [j]; B[i,j] -> [i] }]",
   6512 	  "{ C[a,b] -> D[b,a] }",
   6513 	  "D[{ A[i,j] -> [j] : i >= 0; B[i,j] -> [i] }, "
   6514 	    "{ A[i,j] -> [i] : i >= 0; B[i,j] -> [j] }]" },
   6515 	{ &isl_multi_union_pw_aff_apply_multi_aff,
   6516 	  "C[{ A[i,j] -> [i]; B[i,j] -> [j] }]",
   6517 	  "[N] -> { C[a] -> D[a + N] }",
   6518 	  "[N] -> D[{ A[i,j] -> [i + N]; B[i,j] -> [j + N] }] " },
   6519 	{ &isl_multi_union_pw_aff_apply_multi_aff,
   6520 	  "C[]",
   6521 	  "{ C[] -> D[] }",
   6522 	  "D[]" },
   6523 	{ &isl_multi_union_pw_aff_apply_multi_aff,
   6524 	  "[N] -> (C[] : { : N >= 0 })",
   6525 	  "{ C[] -> D[] }",
   6526 	  "[N] -> (D[] : { : N >= 0 })" },
   6527 	{ &isl_multi_union_pw_aff_apply_multi_aff,
   6528 	  "C[]",
   6529 	  "[N] -> { C[] -> D[N] }",
   6530 	  "[N] -> D[{ [N] }]" },
   6531 	{ &isl_multi_union_pw_aff_apply_multi_aff,
   6532 	  "(C[] : { A[i,j] : i >= j })",
   6533 	  "{ C[] -> D[] }",
   6534 	  "(D[] : { A[i,j] : i >= j })" },
   6535 	{ &isl_multi_union_pw_aff_apply_multi_aff,
   6536 	  "[N] -> (C[] : { A[i,j] : N >= 0 })",
   6537 	  "{ C[] -> D[] }",
   6538 	  "[N] -> (D[] : { A[i,j] : N >= 0 })" },
   6539 	{ &isl_multi_union_pw_aff_apply_multi_aff,
   6540 	  "(C[] : { A[i,j] : i >= j })",
   6541 	  "[N] -> { C[] -> D[N] }",
   6542 	  "[N] -> (D[{ A[i,j] -> [N] : i >= j }])" },
   6543 };
   6544 
   6545 /* Perform some basic tests of binary operations on
   6546  * pairs of isl_multi_union_pw_aff and isl_multi_aff objects.
   6547  */
   6548 static int test_mupa_ma(isl_ctx *ctx)
   6549 {
   6550 	int i;
   6551 	isl_bool ok;
   6552 	isl_multi_union_pw_aff *mupa, *res;
   6553 	isl_multi_aff *ma;
   6554 
   6555 	for (i = 0; i < ARRAY_SIZE(mupa_ma_tests); ++i) {
   6556 		mupa = isl_multi_union_pw_aff_read_from_str(ctx,
   6557 						    mupa_ma_tests[i].arg1);
   6558 		ma = isl_multi_aff_read_from_str(ctx, mupa_ma_tests[i].arg2);
   6559 		res = isl_multi_union_pw_aff_read_from_str(ctx,
   6560 						    mupa_ma_tests[i].res);
   6561 		mupa = mupa_ma_tests[i].fn(mupa, ma);
   6562 		ok = isl_multi_union_pw_aff_plain_is_equal(mupa, res);
   6563 		isl_multi_union_pw_aff_free(mupa);
   6564 		isl_multi_union_pw_aff_free(res);
   6565 		if (ok < 0)
   6566 			return -1;
   6567 		if (!ok)
   6568 			isl_die(ctx, isl_error_unknown,
   6569 				"unexpected result", return -1);
   6570 	}
   6571 
   6572 	return 0;
   6573 }
   6574 
   6575 /* Inputs for basic tests of binary operations on
   6576  * pairs of isl_multi_union_pw_aff and isl_pw_aff objects.
   6577  * "fn" is the function that is tested.
   6578  * "arg1" and "arg2" are string descriptions of the inputs.
   6579  * "res" is a string description of the expected result.
   6580  */
   6581 struct {
   6582 	__isl_give isl_union_pw_aff *(*fn)(
   6583 		__isl_take isl_multi_union_pw_aff *mupa,
   6584 		__isl_take isl_pw_aff *pa);
   6585 	const char *arg1;
   6586 	const char *arg2;
   6587 	const char *res;
   6588 } mupa_pa_tests[] = {
   6589 	{ &isl_multi_union_pw_aff_apply_pw_aff,
   6590 	  "C[{ A[i,j] -> [i]; B[i,j] -> [j] }]",
   6591 	  "[N] -> { C[a] -> [a + N] }",
   6592 	  "[N] -> { A[i,j] -> [i + N]; B[i,j] -> [j + N] }" },
   6593 	{ &isl_multi_union_pw_aff_apply_pw_aff,
   6594 	  "C[{ A[i,j] -> [i]; B[i,j] -> [j] }]",
   6595 	  "{ C[a] -> [a] : a >= 0; C[a] -> [-a] : a < 0 }",
   6596 	  "{ A[i,j] -> [i] : i >= 0; A[i,j] -> [-i] : i < 0; "
   6597 	    "B[i,j] -> [j] : j >= 0; B[i,j] -> [-j] : j < 0 }" },
   6598 	{ &isl_multi_union_pw_aff_apply_pw_aff,
   6599 	  "C[]",
   6600 	  "[N] -> { C[] -> [N] }",
   6601 	  "[N] -> { [N] }" },
   6602 	{ &isl_multi_union_pw_aff_apply_pw_aff,
   6603 	  "C[]",
   6604 	  "[N] -> { C[] -> [N] : N >= 0; C[] -> [-N] : N < 0 }",
   6605 	  "[N] -> { [N] : N >= 0; [-N] : N < 0 }" },
   6606 	{ &isl_multi_union_pw_aff_apply_pw_aff,
   6607 	  "[N] -> (C[] : { : N >= 0 })",
   6608 	  "[N] -> { C[] -> [N] }",
   6609 	  "[N] -> { [N] : N >= 0 }" },
   6610 	{ &isl_multi_union_pw_aff_apply_pw_aff,
   6611 	  "[N] -> (C[] : { : N >= 0 })",
   6612 	  "[N] -> { C[] -> [N] : N >= 0; C[] -> [-N] : N < 0 }",
   6613 	  "[N] -> { [N] : N >= 0 }" },
   6614 	{ &isl_multi_union_pw_aff_apply_pw_aff,
   6615 	  "[N] -> (C[] : { : N >= 0 })",
   6616 	  "{ C[] -> [0] }",
   6617 	  "[N] -> { [0] : N >= 0 }" },
   6618 	{ &isl_multi_union_pw_aff_apply_pw_aff,
   6619 	  "(C[] : { A[i,j] : i >= j })",
   6620 	  "[N] -> { C[] -> [N] }",
   6621 	  "[N] -> { A[i,j] -> [N] : i >= j }" },
   6622 	{ &isl_multi_union_pw_aff_apply_pw_aff,
   6623 	  "(C[] : { A[i,j] : i >= j })",
   6624 	  "[N] -> { C[] -> [N] : N >= 0 }",
   6625 	  "[N] -> { A[i,j] -> [N] : i >= j and N >= 0 }" },
   6626 };
   6627 
   6628 /* Perform some basic tests of binary operations on
   6629  * pairs of isl_multi_union_pw_aff and isl_pw_aff objects.
   6630  */
   6631 static int test_mupa_pa(isl_ctx *ctx)
   6632 {
   6633 	int i;
   6634 	isl_bool ok;
   6635 	isl_multi_union_pw_aff *mupa;
   6636 	isl_union_pw_aff *upa, *res;
   6637 	isl_pw_aff *pa;
   6638 
   6639 	for (i = 0; i < ARRAY_SIZE(mupa_pa_tests); ++i) {
   6640 		mupa = isl_multi_union_pw_aff_read_from_str(ctx,
   6641 						    mupa_pa_tests[i].arg1);
   6642 		pa = isl_pw_aff_read_from_str(ctx, mupa_pa_tests[i].arg2);
   6643 		res = isl_union_pw_aff_read_from_str(ctx,
   6644 						    mupa_pa_tests[i].res);
   6645 		upa = mupa_pa_tests[i].fn(mupa, pa);
   6646 		ok = isl_union_pw_aff_plain_is_equal(upa, res);
   6647 		isl_union_pw_aff_free(upa);
   6648 		isl_union_pw_aff_free(res);
   6649 		if (ok < 0)
   6650 			return -1;
   6651 		if (!ok)
   6652 			isl_die(ctx, isl_error_unknown,
   6653 				"unexpected result", return -1);
   6654 	}
   6655 
   6656 	return 0;
   6657 }
   6658 
   6659 /* Inputs for basic tests of binary operations on
   6660  * pairs of isl_multi_union_pw_aff and isl_pw_multi_aff objects.
   6661  * "fn" is the function that is tested.
   6662  * "arg1" and "arg2" are string descriptions of the inputs.
   6663  * "res" is a string description of the expected result.
   6664  */
   6665 struct {
   6666 	__isl_give isl_multi_union_pw_aff *(*fn)(
   6667 		__isl_take isl_multi_union_pw_aff *mupa,
   6668 		__isl_take isl_pw_multi_aff *pma);
   6669 	const char *arg1;
   6670 	const char *arg2;
   6671 	const char *res;
   6672 } mupa_pma_tests[] = {
   6673 	{ &isl_multi_union_pw_aff_apply_pw_multi_aff,
   6674 	  "C[{ A[i,j] -> [i]; B[i,j] -> [j] }, "
   6675 	    "{ A[i,j] -> [j]; B[i,j] -> [i] }]",
   6676 	  "{ C[a,b] -> D[b,a] }",
   6677 	  "D[{ A[i,j] -> [j]; B[i,j] -> [i] }, "
   6678 	    "{ A[i,j] -> [i]; B[i,j] -> [j] }]" },
   6679 	{ &isl_multi_union_pw_aff_apply_pw_multi_aff,
   6680 	  "C[{ A[i,j] -> [i] : i >= 0; B[i,j] -> [j] }, "
   6681 	    "{ A[i,j] -> [j]; B[i,j] -> [i] }]",
   6682 	  "{ C[a,b] -> D[b,a] }",
   6683 	  "D[{ A[i,j] -> [j] : i >= 0; B[i,j] -> [i] }, "
   6684 	    "{ A[i,j] -> [i] : i >= 0; B[i,j] -> [j] }]" },
   6685 	{ &isl_multi_union_pw_aff_apply_pw_multi_aff,
   6686 	  "C[{ A[i,j] -> [i]; B[i,j] -> [j] }]",
   6687 	  "[N] -> { C[a] -> D[a + N] }",
   6688 	  "[N] -> D[{ A[i,j] -> [i + N]; B[i,j] -> [j + N] }]" },
   6689 	{ &isl_multi_union_pw_aff_apply_pw_multi_aff,
   6690 	  "C[{ A[i,j] -> [i]; B[i,j] -> [j] }]",
   6691 	  "{ C[a] -> D[a] : a >= 0; C[a] -> D[-a] : a < 0 }",
   6692 	  "D[{ A[i,j] -> [i] : i >= 0; A[i,j] -> [-i] : i < 0; "
   6693 	      "B[i,j] -> [j] : j >= 0; B[i,j] -> [-j] : j < 0 }]" },
   6694 	{ &isl_multi_union_pw_aff_apply_pw_multi_aff,
   6695 	  "C[{ A[i,j] -> [i]; B[i,j] -> [j] }, "
   6696 	    "{ A[i,j] -> [j]; B[i,j] -> [i] }]",
   6697 	  "{ C[a,b] -> D[a,b] : a >= b; C[a,b] -> D[b,a] : a < b }",
   6698 	  "D[{ A[i,j] -> [i] : i >= j; A[i,j] -> [j] : i < j; "
   6699 	      "B[i,j] -> [j] : i <= j; B[i,j] -> [i] : i > j }, "
   6700 	    "{ A[i,j] -> [j] : i >= j; A[i,j] -> [i] : i < j; "
   6701 	      "B[i,j] -> [i] : i <= j; B[i,j] -> [j] : i > j }]" },
   6702 	{ &isl_multi_union_pw_aff_apply_pw_multi_aff,
   6703 	  "C[]",
   6704 	  "{ C[] -> D[] }",
   6705 	  "D[]" },
   6706 	{ &isl_multi_union_pw_aff_apply_pw_multi_aff,
   6707 	  "[N] -> (C[] : { : N >= 0 })",
   6708 	  "{ C[] -> D[] }",
   6709 	  "[N] -> (D[] : { : N >= 0 })" },
   6710 	{ &isl_multi_union_pw_aff_apply_pw_multi_aff,
   6711 	  "C[]",
   6712 	  "[N] -> { C[] -> D[N] }",
   6713 	  "[N] -> D[{ [N] }]" },
   6714 	{ &isl_multi_union_pw_aff_apply_pw_multi_aff,
   6715 	  "(C[] : { A[i,j] : i >= j })",
   6716 	  "{ C[] -> D[] }",
   6717 	  "(D[] : { A[i,j] : i >= j })" },
   6718 	{ &isl_multi_union_pw_aff_apply_pw_multi_aff,
   6719 	  "[N] -> (C[] : { A[i,j] : N >= 0 })",
   6720 	  "{ C[] -> D[] }",
   6721 	  "[N] -> (D[] : { A[i,j] : N >= 0 })" },
   6722 	{ &isl_multi_union_pw_aff_apply_pw_multi_aff,
   6723 	  "(C[] : { A[i,j] : i >= j })",
   6724 	  "[N] -> { C[] -> D[N] }",
   6725 	  "[N] -> (D[{ A[i,j] -> [N] : i >= j }])" },
   6726 	{ &isl_multi_union_pw_aff_apply_pw_multi_aff,
   6727 	  "C[]",
   6728 	  "[N] -> { C[] -> D[N] : N >= 0; C[] -> D[-N] : N < 0 }",
   6729 	  "[N] -> D[{ [N] : N >= 0; [-N] : N < 0 }]" },
   6730 	{ &isl_multi_union_pw_aff_apply_pw_multi_aff,
   6731 	  "[N] -> (C[] : { : N >= 0 })",
   6732 	  "[N] -> { C[] -> D[N] }",
   6733 	  "[N] -> D[{ [N] : N >= 0 }]" },
   6734 	{ &isl_multi_union_pw_aff_apply_pw_multi_aff,
   6735 	  "[N] -> (C[] : { : N >= 0 })",
   6736 	  "[N] -> { C[] -> D[N] : N >= 0; C[] -> D[-N] : N < 0 }",
   6737 	  "[N] -> D[{ [N] : N >= 0 }]" },
   6738 	{ &isl_multi_union_pw_aff_apply_pw_multi_aff,
   6739 	  "[N] -> (C[] : { : N >= 0 })",
   6740 	  "{ C[] -> D[0] }",
   6741 	  "[N] -> D[{ [0] : N >= 0 }]" },
   6742 	{ &isl_multi_union_pw_aff_apply_pw_multi_aff,
   6743 	  "(C[] : { A[i,j] : i >= j })",
   6744 	  "[N] -> { C[] -> D[N] : N >= 0 }",
   6745 	  "[N] -> D[{ A[i,j] -> [N] : i >= j and N >= 0 }]" },
   6746 };
   6747 
   6748 /* Perform some basic tests of binary operations on
   6749  * pairs of isl_multi_union_pw_aff and isl_pw_multi_aff objects.
   6750  */
   6751 static int test_mupa_pma(isl_ctx *ctx)
   6752 {
   6753 	int i;
   6754 	isl_bool ok;
   6755 	isl_multi_union_pw_aff *mupa, *res;
   6756 	isl_pw_multi_aff *pma;
   6757 
   6758 	for (i = 0; i < ARRAY_SIZE(mupa_pma_tests); ++i) {
   6759 		mupa = isl_multi_union_pw_aff_read_from_str(ctx,
   6760 						    mupa_pma_tests[i].arg1);
   6761 		pma = isl_pw_multi_aff_read_from_str(ctx,
   6762 						    mupa_pma_tests[i].arg2);
   6763 		res = isl_multi_union_pw_aff_read_from_str(ctx,
   6764 						    mupa_pma_tests[i].res);
   6765 		mupa = mupa_pma_tests[i].fn(mupa, pma);
   6766 		ok = isl_multi_union_pw_aff_plain_is_equal(mupa, res);
   6767 		isl_multi_union_pw_aff_free(mupa);
   6768 		isl_multi_union_pw_aff_free(res);
   6769 		if (ok < 0)
   6770 			return -1;
   6771 		if (!ok)
   6772 			isl_die(ctx, isl_error_unknown,
   6773 				"unexpected result", return -1);
   6774 	}
   6775 
   6776 	return 0;
   6777 }
   6778 
   6779 /* Inputs for basic tests of binary operations on
   6780  * pairs of isl_multi_union_pw_aff and isl_union_pw_multi_aff objects.
   6781  * "fn" is the function that is tested.
   6782  * "arg1" and "arg2" are string descriptions of the inputs.
   6783  * "res" is a string description of the expected result.
   6784  */
   6785 struct {
   6786 	__isl_give isl_multi_union_pw_aff *(*fn)(
   6787 		__isl_take isl_multi_union_pw_aff *mupa,
   6788 		__isl_take isl_union_pw_multi_aff *upma);
   6789 	const char *arg1;
   6790 	const char *arg2;
   6791 	const char *res;
   6792 } mupa_upma_tests[] = {
   6793 	{ &isl_multi_union_pw_aff_pullback_union_pw_multi_aff,
   6794 	  "C[{ B[i,j] -> [i + 2j] }]", "{ A[a,b] -> B[b,a] }",
   6795 	  "C[{ A[a,b] -> [b + 2a] }]" },
   6796 	{ &isl_multi_union_pw_aff_pullback_union_pw_multi_aff,
   6797 	  "C[{ B[i,j] -> [i + 2j] }]",
   6798 	  "{ A[a,b] -> B[b,a] : b > a }",
   6799 	  "C[{ A[a,b] -> [b + 2a] : b > a }]" },
   6800 	{ &isl_multi_union_pw_aff_pullback_union_pw_multi_aff,
   6801 	  "C[{ B[i,j] -> [i + 2j] : j > 4 }]",
   6802 	  "{ A[a,b] -> B[b,a] : b > a }",
   6803 	  "C[{ A[a,b] -> [b + 2a] : b > a > 4 }]" },
   6804 	{ &isl_multi_union_pw_aff_pullback_union_pw_multi_aff,
   6805 	  "C[{ B[i,j] -> [i + 2j] }]",
   6806 	  "{ A[a,b] -> B[b,a] : a > b; A[a,b] -> B[a,b] : a <= b }",
   6807 	  "C[{ A[a,b] -> [b + 2a] : a > b; A[a,b] -> [a + 2b] : a <= b }]" },
   6808 	{ &isl_multi_union_pw_aff_pullback_union_pw_multi_aff,
   6809 	  "(C[] : { B[a,b] })",
   6810 	  "{ A[a,b] -> B[b,a] }",
   6811 	  "(C[] : { A[a,b] })" },
   6812 	{ &isl_multi_union_pw_aff_pullback_union_pw_multi_aff,
   6813 	  "(C[] : { B[a,b] })",
   6814 	  "{ B[a,b] -> A[b,a] }",
   6815 	  "(C[] : { })" },
   6816 	{ &isl_multi_union_pw_aff_pullback_union_pw_multi_aff,
   6817 	  "(C[] : { B[a,b] })",
   6818 	  "{ A[a,b] -> B[b,a] : a > b }",
   6819 	  "(C[] : { A[a,b] : a > b })" },
   6820 	{ &isl_multi_union_pw_aff_pullback_union_pw_multi_aff,
   6821 	  "(C[] : { B[a,b] : a > b })",
   6822 	  "{ A[a,b] -> B[b,a] }",
   6823 	  "(C[] : { A[a,b] : b > a })" },
   6824 	{ &isl_multi_union_pw_aff_pullback_union_pw_multi_aff,
   6825 	  "[N] -> (C[] : { B[a,b] : a > N })",
   6826 	  "{ A[a,b] -> B[b,a] : a > b }",
   6827 	  "[N] -> (C[] : { A[a,b] : a > b > N })" },
   6828 	{ &isl_multi_union_pw_aff_pullback_union_pw_multi_aff,
   6829 	  "(C[] : { B[a,b] : a > b })",
   6830 	  "[N] -> { A[a,b] -> B[b,a] : a > N }",
   6831 	  "[N] -> (C[] : { A[a,b] : b > a > N })" },
   6832 	{ &isl_multi_union_pw_aff_pullback_union_pw_multi_aff,
   6833 	  "C[]",
   6834 	  "{ A[a,b] -> B[b,a] }",
   6835 	  "C[]" },
   6836 	{ &isl_multi_union_pw_aff_pullback_union_pw_multi_aff,
   6837 	  "[N] -> (C[] : { : N >= 0 })",
   6838 	  "{ A[a,b] -> B[b,a] }",
   6839 	  "[N] -> (C[] : { : N >= 0 })" },
   6840 	{ &isl_multi_union_pw_aff_pullback_union_pw_multi_aff,
   6841 	  "C[]",
   6842 	  "[N] -> { A[a,b] -> B[b,a] : N >= 0 }",
   6843 	  "[N] -> (C[] : { : N >= 0 })" },
   6844 };
   6845 
   6846 /* Perform some basic tests of binary operations on
   6847  * pairs of isl_multi_union_pw_aff and isl_union_pw_multi_aff objects.
   6848  */
   6849 static int test_mupa_upma(isl_ctx *ctx)
   6850 {
   6851 	int i;
   6852 	isl_bool ok;
   6853 	isl_multi_union_pw_aff *mupa, *res;
   6854 	isl_union_pw_multi_aff *upma;
   6855 
   6856 	for (i = 0; i < ARRAY_SIZE(mupa_upma_tests); ++i) {
   6857 		mupa = isl_multi_union_pw_aff_read_from_str(ctx,
   6858 						    mupa_upma_tests[i].arg1);
   6859 		upma = isl_union_pw_multi_aff_read_from_str(ctx,
   6860 						    mupa_upma_tests[i].arg2);
   6861 		res = isl_multi_union_pw_aff_read_from_str(ctx,
   6862 						    mupa_upma_tests[i].res);
   6863 		mupa = mupa_upma_tests[i].fn(mupa, upma);
   6864 		ok = isl_multi_union_pw_aff_plain_is_equal(mupa, res);
   6865 		isl_multi_union_pw_aff_free(mupa);
   6866 		isl_multi_union_pw_aff_free(res);
   6867 		if (ok < 0)
   6868 			return -1;
   6869 		if (!ok)
   6870 			isl_die(ctx, isl_error_unknown,
   6871 				"unexpected result", return -1);
   6872 	}
   6873 
   6874 	return 0;
   6875 }
   6876 
   6877 /* Check that the input tuple of an isl_aff can be set properly.
   6878  */
   6879 static isl_stat test_aff_set_tuple_id(isl_ctx *ctx)
   6880 {
   6881 	isl_id *id;
   6882 	isl_aff *aff;
   6883 	isl_stat equal;
   6884 
   6885 	aff = isl_aff_read_from_str(ctx, "{ [x] -> [x + 1] }");
   6886 	id = isl_id_alloc(ctx, "A", NULL);
   6887 	aff = isl_aff_set_tuple_id(aff, isl_dim_in, id);
   6888 	equal = aff_check_plain_equal(aff, "{ A[x] -> [x + 1] }");
   6889 	isl_aff_free(aff);
   6890 	if (equal < 0)
   6891 		return isl_stat_error;
   6892 
   6893 	return isl_stat_ok;
   6894 }
   6895 
   6896 /* Check that affine expressions get normalized on addition/subtraction.
   6897  * In particular, check that (final) unused integer divisions get removed
   6898  * such that an expression derived from expressions with integer divisions
   6899  * is found to be obviously equal to one that is created directly.
   6900  */
   6901 static isl_stat test_aff_normalize(isl_ctx *ctx)
   6902 {
   6903 	isl_aff *aff, *aff2;
   6904 	isl_stat ok;
   6905 
   6906 	aff = isl_aff_read_from_str(ctx, "{ [x] -> [x//2] }");
   6907 	aff2 = isl_aff_read_from_str(ctx, "{ [x] -> [1 + x//2] }");
   6908 	aff = isl_aff_sub(aff2, aff);
   6909 	ok = aff_check_plain_equal(aff, "{ [x] -> [1] }");
   6910 	isl_aff_free(aff);
   6911 
   6912 	return ok;
   6913 }
   6914 
   6915 int test_aff(isl_ctx *ctx)
   6916 {
   6917 	const char *str;
   6918 	isl_set *set;
   6919 	isl_space *space;
   6920 	isl_local_space *ls;
   6921 	isl_aff *aff;
   6922 	int zero;
   6923 	isl_stat equal;
   6924 
   6925 	if (test_upa(ctx) < 0)
   6926 		return -1;
   6927 	if (test_bin_aff(ctx) < 0)
   6928 		return -1;
   6929 	if (test_bin_pw_aff(ctx) < 0)
   6930 		return -1;
   6931 	if (test_upma_test(ctx) < 0)
   6932 		return -1;
   6933 	if (test_bin_upma(ctx) < 0)
   6934 		return -1;
   6935 	if (test_bin_upma_fail(ctx) < 0)
   6936 		return -1;
   6937 	if (test_upma_uset(ctx) < 0)
   6938 		return -1;
   6939 	if (test_un_mpa(ctx) < 0)
   6940 		return -1;
   6941 	if (test_bin_mpa(ctx) < 0)
   6942 		return -1;
   6943 	if (test_un_mupa(ctx) < 0)
   6944 		return -1;
   6945 	if (test_bin_mupa(ctx) < 0)
   6946 		return -1;
   6947 	if (test_mupa_set(ctx) < 0)
   6948 		return -1;
   6949 	if (test_mupa_uset(ctx) < 0)
   6950 		return -1;
   6951 	if (test_mupa_ma(ctx) < 0)
   6952 		return -1;
   6953 	if (test_mupa_pa(ctx) < 0)
   6954 		return -1;
   6955 	if (test_mupa_pma(ctx) < 0)
   6956 		return -1;
   6957 	if (test_mupa_upma(ctx) < 0)
   6958 		return -1;
   6959 
   6960 	space = isl_space_set_alloc(ctx, 0, 1);
   6961 	ls = isl_local_space_from_space(space);
   6962 	aff = isl_aff_zero_on_domain(ls);
   6963 
   6964 	aff = isl_aff_add_coefficient_si(aff, isl_dim_in, 0, 1);
   6965 	aff = isl_aff_scale_down_ui(aff, 3);
   6966 	aff = isl_aff_floor(aff);
   6967 	aff = isl_aff_add_coefficient_si(aff, isl_dim_in, 0, 1);
   6968 	aff = isl_aff_scale_down_ui(aff, 2);
   6969 	aff = isl_aff_floor(aff);
   6970 	aff = isl_aff_add_coefficient_si(aff, isl_dim_in, 0, 1);
   6971 
   6972 	str = "{ [10] }";
   6973 	set = isl_set_read_from_str(ctx, str);
   6974 	aff = isl_aff_gist(aff, set);
   6975 
   6976 	aff = isl_aff_add_constant_si(aff, -16);
   6977 	zero = isl_aff_plain_is_zero(aff);
   6978 	isl_aff_free(aff);
   6979 
   6980 	if (zero < 0)
   6981 		return -1;
   6982 	if (!zero)
   6983 		isl_die(ctx, isl_error_unknown, "unexpected result", return -1);
   6984 
   6985 	aff = isl_aff_read_from_str(ctx, "{ [-1] }");
   6986 	aff = isl_aff_scale_down_ui(aff, 64);
   6987 	aff = isl_aff_floor(aff);
   6988 	equal = aff_check_plain_equal(aff, "{ [-1] }");
   6989 	isl_aff_free(aff);
   6990 	if (equal < 0)
   6991 		return -1;
   6992 
   6993 	if (test_aff_set_tuple_id(ctx) < 0)
   6994 		return -1;
   6995 	if (test_aff_normalize(ctx) < 0)
   6996 		return -1;
   6997 
   6998 	return 0;
   6999 }
   7000 
   7001 /* Inputs for isl_set_bind tests.
   7002  * "set" is the input set.
   7003  * "tuple" is the binding tuple.
   7004  * "res" is the expected result.
   7005  */
   7006 static
   7007 struct {
   7008 	const char *set;
   7009 	const char *tuple;
   7010 	const char *res;
   7011 } bind_set_tests[] = {
   7012 	{ "{ A[M, N] : M mod 2 = 0 and N mod 8 = 3 }",
   7013 	  "{ A[M, N] }",
   7014 	  "[M, N] -> { : M mod 2 = 0 and N mod 8 = 3 }" },
   7015 	{ "{ B[N, M] : M mod 2 = 0 and N mod 8 = 3 }",
   7016 	  "{ B[N, M] }",
   7017 	  "[M, N] -> { : M mod 2 = 0 and N mod 8 = 3 }" },
   7018 	{ "[M] -> { C[N] : M mod 2 = 0 and N mod 8 = 3 }",
   7019 	  "{ C[N] }",
   7020 	  "[M, N] -> { : M mod 2 = 0 and N mod 8 = 3 }" },
   7021 	{ "[M] -> { D[x, N] : x mod 2 = 0 and N mod 8 = 3 and M >= 0 }",
   7022 	  "{ D[M, N] }",
   7023 	  "[M, N] -> { : M mod 2 = 0 and N mod 8 = 3 and M >= 0 }" },
   7024 };
   7025 
   7026 /* Perform basic isl_set_bind tests.
   7027  */
   7028 static isl_stat test_bind_set(isl_ctx *ctx)
   7029 {
   7030 	int i;
   7031 
   7032 	for (i = 0; i < ARRAY_SIZE(bind_set_tests); ++i) {
   7033 		const char *str;
   7034 		isl_set *set;
   7035 		isl_multi_id *tuple;
   7036 		isl_stat r;
   7037 
   7038 		set = isl_set_read_from_str(ctx, bind_set_tests[i].set);
   7039 		str = bind_set_tests[i].tuple;
   7040 		tuple = isl_multi_id_read_from_str(ctx, str);
   7041 		set = isl_set_bind(set, tuple);
   7042 		r = set_check_equal(set, bind_set_tests[i].res);
   7043 		isl_set_free(set);
   7044 		if (r < 0)
   7045 			return isl_stat_error;
   7046 	}
   7047 
   7048 	return isl_stat_ok;
   7049 }
   7050 
   7051 /* Inputs for isl_map_bind_domain tests.
   7052  * "map" is the input map.
   7053  * "tuple" is the binding tuple.
   7054  * "res" is the expected result.
   7055  */
   7056 struct {
   7057 	const char *map;
   7058 	const char *tuple;
   7059 	const char *res;
   7060 } bind_map_domain_tests[] = {
   7061 	{ "{ A[M, N] -> [M + floor(N/2)] }",
   7062 	  "{ A[M, N] }",
   7063 	  "[M, N] -> { [M + floor(N/2)] }" },
   7064 	{ "{ B[N, M] -> [M + floor(N/2)] }",
   7065 	  "{ B[N, M] }",
   7066 	  "[N, M] -> { [M + floor(N/2)] }" },
   7067 	{ "[M] -> { C[N] -> [M + floor(N/2)] }",
   7068 	  "{ C[N] }",
   7069 	  "[M, N] -> { [M + floor(N/2)] }" },
   7070 	{ "[M] -> { C[x, N] -> [x + floor(N/2)] }",
   7071 	  "{ C[M, N] }",
   7072 	  "[M, N] -> { [M + floor(N/2)] }" },
   7073 	{ "[M] -> { C[x, N] -> [M + floor(N/2)] }",
   7074 	  "{ C[M, N] }",
   7075 	  "[M, N] -> { [M + floor(N/2)] }" },
   7076 	{ "[A, M] -> { C[N, x] -> [x + floor(N/2)] }",
   7077 	  "{ C[N, M] }",
   7078 	  "[A, N, M] -> { [M + floor(N/2)] }" },
   7079 };
   7080 
   7081 /* Perform basic isl_map_bind_domain tests.
   7082  */
   7083 static isl_stat test_bind_map_domain(isl_ctx *ctx)
   7084 {
   7085 	int i;
   7086 
   7087 	for (i = 0; i < ARRAY_SIZE(bind_map_domain_tests); ++i) {
   7088 		const char *str;
   7089 		isl_map *map;
   7090 		isl_set *set;
   7091 		isl_multi_id *tuple;
   7092 		isl_stat r;
   7093 
   7094 		str = bind_map_domain_tests[i].map;
   7095 		map = isl_map_read_from_str(ctx, str);
   7096 		str = bind_map_domain_tests[i].tuple;
   7097 		tuple = isl_multi_id_read_from_str(ctx, str);
   7098 		set = isl_map_bind_domain(map, tuple);
   7099 		str = bind_map_domain_tests[i].res;
   7100 		r = set_check_equal(set, str);
   7101 		isl_set_free(set);
   7102 		if (r < 0)
   7103 			return isl_stat_error;
   7104 	}
   7105 
   7106 	return isl_stat_ok;
   7107 }
   7108 
   7109 /* Inputs for isl_union_map_bind_range tests.
   7110  * "map" is the input union map.
   7111  * "tuple" is the binding tuple.
   7112  * "res" is the expected result.
   7113  */
   7114 struct {
   7115 	const char *map;
   7116 	const char *tuple;
   7117 	const char *res;
   7118 } bind_umap_range_tests[] = {
   7119 	{ "{ B[N, M] -> A[M, N] : M mod 2 = 0 and N mod 8 = 3 }",
   7120 	  "{ A[M, N] }",
   7121 	  "[M, N] -> { B[N, M] : M mod 2 = 0 and N mod 8 = 3 }" },
   7122 	{ "{ B[N, M] -> A[M, N] : M mod 2 = 0 and N mod 8 = 3 }",
   7123 	  "{ B[M, N] }",
   7124 	  "{ }" },
   7125 	{ "{ A[] -> B[]; C[] -> D[]; E[] -> B[] }",
   7126 	  "{ B[] }",
   7127 	  "{ A[]; E[] }" },
   7128 };
   7129 
   7130 /* Perform basic isl_union_map_bind_range tests.
   7131  */
   7132 static isl_stat test_bind_umap_range(isl_ctx *ctx)
   7133 {
   7134 	int i;
   7135 
   7136 	for (i = 0; i < ARRAY_SIZE(bind_umap_range_tests); ++i) {
   7137 		const char *str;
   7138 		isl_union_map *umap;
   7139 		isl_union_set *uset;
   7140 		isl_multi_id *tuple;
   7141 		isl_stat r;
   7142 
   7143 		str = bind_umap_range_tests[i].map;
   7144 		umap = isl_union_map_read_from_str(ctx, str);
   7145 		str = bind_umap_range_tests[i].tuple;
   7146 		tuple = isl_multi_id_read_from_str(ctx, str);
   7147 		uset = isl_union_map_bind_range(umap, tuple);
   7148 		str = bind_umap_range_tests[i].res;
   7149 		r = uset_check_equal(uset, str);
   7150 		isl_union_set_free(uset);
   7151 		if (r < 0)
   7152 			return isl_stat_error;
   7153 	}
   7154 
   7155 	return isl_stat_ok;
   7156 }
   7157 
   7158 /* Inputs for isl_pw_multi_aff_bind_domain tests.
   7159  * "pma" is the input expression.
   7160  * "tuple" is the binding tuple.
   7161  * "res" is the expected result.
   7162  */
   7163 struct {
   7164 	const char *pma;
   7165 	const char *tuple;
   7166 	const char *res;
   7167 } bind_pma_domain_tests[] = {
   7168 	{ "{ A[M, N] -> [M + floor(N/2)] }",
   7169 	  "{ A[M, N] }",
   7170 	  "[M, N] -> { [M + floor(N/2)] }" },
   7171 	{ "{ B[N, M] -> [M + floor(N/2)] }",
   7172 	  "{ B[N, M] }",
   7173 	  "[N, M] -> { [M + floor(N/2)] }" },
   7174 	{ "[M] -> { C[N] -> [M + floor(N/2)] }",
   7175 	  "{ C[N] }",
   7176 	  "[M, N] -> { [M + floor(N/2)] }" },
   7177 	{ "[M] -> { C[x, N] -> [x + floor(N/2)] }",
   7178 	  "{ C[M, N] }",
   7179 	  "[M, N] -> { [M + floor(N/2)] }" },
   7180 	{ "[M] -> { C[x, N] -> [M + floor(N/2)] }",
   7181 	  "{ C[M, N] }",
   7182 	  "[M, N] -> { [M + floor(N/2)] }" },
   7183 	{ "[A, M] -> { C[N, x] -> [x + floor(N/2)] }",
   7184 	  "{ C[N, M] }",
   7185 	  "[A, N, M] -> { [M + floor(N/2)] }" },
   7186 };
   7187 
   7188 /* Perform basic isl_pw_multi_aff_bind_domain tests.
   7189  */
   7190 static isl_stat test_bind_pma_domain(isl_ctx *ctx)
   7191 {
   7192 	int i;
   7193 
   7194 	for (i = 0; i < ARRAY_SIZE(bind_pma_domain_tests); ++i) {
   7195 		const char *str;
   7196 		isl_pw_multi_aff *pma;
   7197 		isl_multi_id *tuple;
   7198 		isl_stat r;
   7199 
   7200 		str = bind_pma_domain_tests[i].pma;
   7201 		pma = isl_pw_multi_aff_read_from_str(ctx, str);
   7202 		str = bind_pma_domain_tests[i].tuple;
   7203 		tuple = isl_multi_id_read_from_str(ctx, str);
   7204 		pma = isl_pw_multi_aff_bind_domain(pma, tuple);
   7205 		str = bind_pma_domain_tests[i].res;
   7206 		r = pw_multi_aff_check_plain_equal(pma, str);
   7207 		isl_pw_multi_aff_free(pma);
   7208 		if (r < 0)
   7209 			return isl_stat_error;
   7210 	}
   7211 
   7212 	return isl_stat_ok;
   7213 }
   7214 
   7215 /* Inputs for isl_pw_multi_aff_bind_domain_wrapped_domain tests.
   7216  * "pma" is the input expression.
   7217  * "tuple" is the binding tuple.
   7218  * "res" is the expected result.
   7219  */
   7220 struct {
   7221 	const char *pma;
   7222 	const char *tuple;
   7223 	const char *res;
   7224 } bind_pma_domain_wrapped_tests[] = {
   7225 	{ "{ [A[M, N] -> B[]] -> [M + floor(N/2)] }",
   7226 	  "{ A[M, N] }",
   7227 	  "[M, N] -> { B[] -> [M + floor(N/2)] }" },
   7228 	{ "{ [B[N, M] -> D[]] -> [M + floor(N/2)] }",
   7229 	  "{ B[N, M] }",
   7230 	  "[N, M] -> { D[] -> [M + floor(N/2)] }" },
   7231 	{ "[M] -> { [C[N] -> B[x]] -> [x + M + floor(N/2)] }",
   7232 	  "{ C[N] }",
   7233 	  "[M, N] -> { B[x] -> [x + M + floor(N/2)] }" },
   7234 	{ "[M] -> { [C[x, N] -> B[]] -> [x + floor(N/2)] }",
   7235 	  "{ C[M, N] }",
   7236 	  "[M, N] -> { B[] -> [M + floor(N/2)] }" },
   7237 	{ "[M] -> { [C[x, N] -> B[]] -> [M + floor(N/2)] }",
   7238 	  "{ C[M, N] }",
   7239 	  "[M, N] -> { B[] -> [M + floor(N/2)] }" },
   7240 	{ "[A, M] -> { [C[N, x] -> B[]] -> [x + floor(N/2)] }",
   7241 	  "{ C[N, M] }",
   7242 	  "[A, N, M] -> { B[] -> [M + floor(N/2)] }" },
   7243 };
   7244 
   7245 /* Perform basic isl_pw_multi_aff_bind_domain_wrapped_domain tests.
   7246  */
   7247 static isl_stat test_bind_pma_domain_wrapped(isl_ctx *ctx)
   7248 {
   7249 	int i;
   7250 
   7251 	for (i = 0; i < ARRAY_SIZE(bind_pma_domain_wrapped_tests); ++i) {
   7252 		const char *str;
   7253 		isl_pw_multi_aff *pma;
   7254 		isl_multi_id *tuple;
   7255 		isl_stat r;
   7256 
   7257 		str = bind_pma_domain_wrapped_tests[i].pma;
   7258 		pma = isl_pw_multi_aff_read_from_str(ctx, str);
   7259 		str = bind_pma_domain_wrapped_tests[i].tuple;
   7260 		tuple = isl_multi_id_read_from_str(ctx, str);
   7261 		pma = isl_pw_multi_aff_bind_domain_wrapped_domain(pma, tuple);
   7262 		str = bind_pma_domain_wrapped_tests[i].res;
   7263 		r = pw_multi_aff_check_plain_equal(pma, str);
   7264 		isl_pw_multi_aff_free(pma);
   7265 		if (r < 0)
   7266 			return isl_stat_error;
   7267 	}
   7268 
   7269 	return isl_stat_ok;
   7270 }
   7271 
   7272 /* Inputs for isl_aff_bind_id tests.
   7273  * "aff" is the input expression.
   7274  * "id" is the binding id.
   7275  * "res" is the expected result.
   7276  */
   7277 static
   7278 struct {
   7279 	const char *aff;
   7280 	const char *id;
   7281 	const char *res;
   7282 } bind_aff_tests[] = {
   7283 	{ "{ [4] }", "M", "[M = 4] -> { : }" },
   7284 	{ "{ B[x] -> [floor(x/2)] }", "M", "[M] -> { B[x] : M = floor(x/2) }" },
   7285 	{ "[M] -> { [4] }", "M", "[M = 4] -> { : }" },
   7286 	{ "[M] -> { [floor(M/2)] }", "M", "[M] -> { : floor(M/2) = M }" },
   7287 	{ "{ [NaN] }", "M", "{ : false }" },
   7288 	{ "{ A[x] -> [NaN] }", "M", "{ A[x] : false }" },
   7289 };
   7290 
   7291 /* Perform basic isl_aff_bind_id tests.
   7292  */
   7293 static isl_stat test_bind_aff(isl_ctx *ctx)
   7294 {
   7295 	int i;
   7296 
   7297 	for (i = 0; i < ARRAY_SIZE(bind_aff_tests); ++i) {
   7298 		isl_aff *aff;
   7299 		isl_set *res;
   7300 		isl_id *id;
   7301 		isl_stat r;
   7302 
   7303 		aff = isl_aff_read_from_str(ctx, bind_aff_tests[i].aff);
   7304 		id = isl_id_read_from_str(ctx, bind_aff_tests[i].id);
   7305 		res = isl_set_from_basic_set(isl_aff_bind_id(aff, id));
   7306 		r = set_check_equal(res, bind_aff_tests[i].res);
   7307 		isl_set_free(res);
   7308 		if (r < 0)
   7309 			return isl_stat_error;
   7310 	}
   7311 
   7312 	return isl_stat_ok;
   7313 }
   7314 
   7315 /* Inputs for isl_pw_aff_bind_id tests.
   7316  * "pa" is the input expression.
   7317  * "id" is the binding id.
   7318  * "res" is the expected result.
   7319  */
   7320 static
   7321 struct {
   7322 	const char *pa;
   7323 	const char *id;
   7324 	const char *res;
   7325 } bind_pa_tests[] = {
   7326 	{ "{ [4] }", "M", "[M = 4] -> { : }" },
   7327 	{ "{ B[x] -> [floor(x/2)] }", "M", "[M] -> { B[x] : M = floor(x/2) }" },
   7328 	{ "[M] -> { [4] }", "M", "[M = 4] -> { : }" },
   7329 	{ "[M] -> { [floor(M/2)] }", "M", "[M] -> { : floor(M/2) = M }" },
   7330 	{ "[M] -> { [M] : M >= 0; [-M] : M < 0 }", "M", "[M] -> { : M >= 0 }" },
   7331 	{ "{ [NaN] }", "M", "{ : false }" },
   7332 	{ "{ A[x] -> [NaN] }", "M", "{ A[x] : false }" },
   7333 };
   7334 
   7335 /* Perform basic isl_pw_aff_bind_id tests.
   7336  */
   7337 static isl_stat test_bind_pa(isl_ctx *ctx)
   7338 {
   7339 	int i;
   7340 
   7341 	for (i = 0; i < ARRAY_SIZE(bind_pa_tests); ++i) {
   7342 		isl_pw_aff *pa;
   7343 		isl_set *res;
   7344 		isl_id *id;
   7345 		isl_stat r;
   7346 
   7347 		pa = isl_pw_aff_read_from_str(ctx, bind_pa_tests[i].pa);
   7348 		id = isl_id_read_from_str(ctx, bind_pa_tests[i].id);
   7349 		res = isl_pw_aff_bind_id(pa, id);
   7350 		r = set_check_equal(res, bind_pa_tests[i].res);
   7351 		isl_set_free(res);
   7352 		if (r < 0)
   7353 			return isl_stat_error;
   7354 	}
   7355 
   7356 	return isl_stat_ok;
   7357 }
   7358 
   7359 /* Inputs for isl_multi_union_pw_aff_bind tests.
   7360  * "mupa" is the input expression.
   7361  * "tuple" is the binding tuple.
   7362  * "res" is the expected result.
   7363  */
   7364 static
   7365 struct {
   7366 	const char *mupa;
   7367 	const char *tuple;
   7368 	const char *res;
   7369 } bind_mupa_tests[] = {
   7370 	{ "A[{ [4] }, { [5] }]",
   7371 	  "{ A[M, N] }",
   7372 	  "[M = 4, N = 5] -> { : }" },
   7373 	{ "A[{ B[x] -> [floor(x/2)] }, { B[y] -> [y + 5] }]",
   7374 	  "{ A[M, N] }",
   7375 	  "[M, N] -> { B[x] : M = floor(x/2) and N = x + 5 }" },
   7376 	{ "[M] -> A[{ [4] }, { [M + 1] }]",
   7377 	  "{ A[M, N] }",
   7378 	  "[M = 4, N = 5] -> { : }" },
   7379 };
   7380 
   7381 /* Perform basic isl_multi_union_pw_aff_bind tests.
   7382  */
   7383 static isl_stat test_bind_mupa(isl_ctx *ctx)
   7384 {
   7385 	int i;
   7386 
   7387 	for (i = 0; i < ARRAY_SIZE(bind_mupa_tests); ++i) {
   7388 		const char *str;
   7389 		isl_multi_union_pw_aff *mupa;
   7390 		isl_union_set *res;
   7391 		isl_multi_id *tuple;
   7392 		isl_stat r;
   7393 
   7394 		str = bind_mupa_tests[i].mupa;
   7395 		mupa = isl_multi_union_pw_aff_read_from_str(ctx, str);
   7396 		str = bind_mupa_tests[i].tuple;
   7397 		tuple = isl_multi_id_read_from_str(ctx, str);
   7398 		res = isl_multi_union_pw_aff_bind(mupa, tuple);
   7399 		r = uset_check_equal(res, bind_mupa_tests[i].res);
   7400 		isl_union_set_free(res);
   7401 		if (r < 0)
   7402 			return isl_stat_error;
   7403 	}
   7404 
   7405 	return isl_stat_ok;
   7406 }
   7407 
   7408 /* Perform tests that reinterpret dimensions as parameters.
   7409  */
   7410 static int test_bind(isl_ctx *ctx)
   7411 {
   7412 	if (test_bind_set(ctx) < 0)
   7413 		return -1;
   7414 	if (test_bind_map_domain(ctx) < 0)
   7415 		return -1;
   7416 	if (test_bind_umap_range(ctx) < 0)
   7417 		return -1;
   7418 	if (test_bind_pma_domain(ctx) < 0)
   7419 		return -1;
   7420 	if (test_bind_pma_domain_wrapped(ctx) < 0)
   7421 		return -1;
   7422 	if (test_bind_aff(ctx) < 0)
   7423 		return -1;
   7424 	if (test_bind_pa(ctx) < 0)
   7425 		return -1;
   7426 	if (test_bind_mupa(ctx) < 0)
   7427 		return -1;
   7428 
   7429 	return 0;
   7430 }
   7431 
   7432 /* Inputs for isl_set_unbind_params tests.
   7433  * "set" is the input parameter domain.
   7434  * "tuple" is the tuple of the constructed set.
   7435  * "res" is the expected result.
   7436  */
   7437 struct {
   7438 	const char *set;
   7439 	const char *tuple;
   7440 	const char *res;
   7441 } unbind_set_tests[] = {
   7442 	{ "[M, N] -> { : M mod 2 = 0 and N mod 8 = 3 }",
   7443 	  "{ A[M, N] }",
   7444 	  "{ A[M, N] : M mod 2 = 0 and N mod 8 = 3 }" },
   7445 	{ "[M, N] -> { : M mod 2 = 0 and N mod 8 = 3 }",
   7446 	  "{ B[N, M] }",
   7447 	  "{ B[N, M] : M mod 2 = 0 and N mod 8 = 3 }" },
   7448 	{ "[M, N] -> { : M mod 2 = 0 and N mod 8 = 3 }",
   7449 	  "{ C[N] }",
   7450 	  "[M] -> { C[N] : M mod 2 = 0 and N mod 8 = 3 }" },
   7451 	{ "[M, N] -> { : M mod 2 = 0 and N mod 8 = 3 }",
   7452 	  "{ D[T, N] }",
   7453 	  "[M] -> { D[x, N] : M mod 2 = 0 and N mod 8 = 3 }" },
   7454 };
   7455 
   7456 /* Perform basic isl_set_unbind_params tests.
   7457  */
   7458 static isl_stat test_unbind_set(isl_ctx *ctx)
   7459 {
   7460 	int i;
   7461 
   7462 	for (i = 0; i < ARRAY_SIZE(unbind_set_tests); ++i) {
   7463 		const char *str;
   7464 		isl_set *set;
   7465 		isl_multi_id *tuple;
   7466 		isl_stat r;
   7467 
   7468 		set = isl_set_read_from_str(ctx, unbind_set_tests[i].set);
   7469 		str = unbind_set_tests[i].tuple;
   7470 		tuple = isl_multi_id_read_from_str(ctx, str);
   7471 		set = isl_set_unbind_params(set, tuple);
   7472 		r = set_check_equal(set, unbind_set_tests[i].res);
   7473 		isl_set_free(set);
   7474 		if (r < 0)
   7475 			return isl_stat_error;
   7476 	}
   7477 
   7478 	return isl_stat_ok;
   7479 }
   7480 
   7481 /* Inputs for isl_aff_unbind_params_insert_domain tests.
   7482  * "aff" is the input affine expression defined over a parameter domain.
   7483  * "tuple" is the tuple of the domain that gets introduced.
   7484  * "res" is the expected result.
   7485  */
   7486 struct {
   7487 	const char *aff;
   7488 	const char *tuple;
   7489 	const char *res;
   7490 } unbind_aff_tests[] = {
   7491 	{ "[M, N] -> { [M + floor(N/2)] }",
   7492 	  "{ A[M, N] }",
   7493 	  "{ A[M, N] -> [M + floor(N/2)] }" },
   7494 	{ "[M, N] -> { [M + floor(N/2)] }",
   7495 	  "{ B[N, M] }",
   7496 	  "{ B[N, M] -> [M + floor(N/2)] }" },
   7497 	{ "[M, N] -> { [M + floor(N/2)] }",
   7498 	  "{ C[N] }",
   7499 	  "[M] -> { C[N] -> [M + floor(N/2)] }" },
   7500 	{ "[M, N] -> { [M + floor(N/2)] }",
   7501 	  "{ D[A, B, C, N, Z] }",
   7502 	  "[M] -> { D[A, B, C, N, Z] -> [M + floor(N/2)] }" },
   7503 };
   7504 
   7505 /* Perform basic isl_aff_unbind_params_insert_domain tests.
   7506  */
   7507 static isl_stat test_unbind_aff(isl_ctx *ctx)
   7508 {
   7509 	int i;
   7510 
   7511 	for (i = 0; i < ARRAY_SIZE(unbind_aff_tests); ++i) {
   7512 		const char *str;
   7513 		isl_aff *aff;
   7514 		isl_multi_id *tuple;
   7515 		isl_stat r;
   7516 
   7517 		aff = isl_aff_read_from_str(ctx, unbind_aff_tests[i].aff);
   7518 		str = unbind_aff_tests[i].tuple;
   7519 		tuple = isl_multi_id_read_from_str(ctx, str);
   7520 		aff = isl_aff_unbind_params_insert_domain(aff, tuple);
   7521 		r = aff_check_plain_equal(aff, unbind_aff_tests[i].res);
   7522 		isl_aff_free(aff);
   7523 		if (r < 0)
   7524 			return isl_stat_error;
   7525 	}
   7526 
   7527 	return isl_stat_ok;
   7528 }
   7529 
   7530 /* Inputs for isl_multi_aff_unbind_params_insert_domain tests.
   7531  * "ma" is the input multi affine expression defined over a parameter domain.
   7532  * "tuple" is the tuple of the domain that gets introduced.
   7533  * "res" is the expected result.
   7534  */
   7535 static struct {
   7536 	const char *ma;
   7537 	const char *tuple;
   7538 	const char *res;
   7539 } unbind_multi_aff_tests[] = {
   7540 	{ "[M, N] -> { T[M + floor(N/2)] }",
   7541 	  "{ A[M, N] }",
   7542 	  "{ A[M, N] -> T[M + floor(N/2)] }" },
   7543 	{ "[M, N] -> { [M + floor(N/2)] }",
   7544 	  "{ B[N, M] }",
   7545 	  "{ B[N, M] -> [M + floor(N/2)] }" },
   7546 	{ "[M, N] -> { [M + floor(N/2)] }",
   7547 	  "{ C[N] }",
   7548 	  "[M] -> { C[N] -> [M + floor(N/2)] }" },
   7549 	{ "[M, N] -> { [M + floor(N/2)] }",
   7550 	  "{ D[A, B, C, N, Z] }",
   7551 	  "[M] -> { D[A, B, C, N, Z] -> [M + floor(N/2)] }" },
   7552 	{ "[M, N] -> { T[M + floor(N/2), N + floor(M/3)] }",
   7553 	  "{ A[M, N] }",
   7554 	  "{ A[M, N] -> T[M + floor(N/2), N + floor(M/3)] }" },
   7555 };
   7556 
   7557 /* Perform basic isl_multi_aff_unbind_params_insert_domain tests.
   7558  */
   7559 static isl_stat test_unbind_multi_aff(isl_ctx *ctx)
   7560 {
   7561 	int i;
   7562 
   7563 	for (i = 0; i < ARRAY_SIZE(unbind_multi_aff_tests); ++i) {
   7564 		const char *str;
   7565 		isl_multi_aff *ma;
   7566 		isl_multi_id *tuple;
   7567 		isl_stat r;
   7568 
   7569 		str = unbind_multi_aff_tests[i].ma;
   7570 		ma = isl_multi_aff_read_from_str(ctx, str);
   7571 		str = unbind_multi_aff_tests[i].tuple;
   7572 		tuple = isl_multi_id_read_from_str(ctx, str);
   7573 		ma = isl_multi_aff_unbind_params_insert_domain(ma, tuple);
   7574 		str = unbind_multi_aff_tests[i].res;
   7575 		r = multi_aff_check_plain_equal(ma, str);
   7576 		isl_multi_aff_free(ma);
   7577 		if (r < 0)
   7578 			return isl_stat_error;
   7579 	}
   7580 
   7581 	return isl_stat_ok;
   7582 }
   7583 
   7584 /* Perform tests that reinterpret parameters.
   7585  */
   7586 static int test_unbind(isl_ctx *ctx)
   7587 {
   7588 	if (test_unbind_set(ctx) < 0)
   7589 		return -1;
   7590 	if (test_unbind_aff(ctx) < 0)
   7591 		return -1;
   7592 	if (test_unbind_multi_aff(ctx) < 0)
   7593 		return -1;
   7594 
   7595 	return 0;
   7596 }
   7597 
   7598 /* Check that "pa" consists of a single expression.
   7599  */
   7600 static int check_single_piece(isl_ctx *ctx, __isl_take isl_pw_aff *pa)
   7601 {
   7602 	isl_size n;
   7603 
   7604 	n = isl_pw_aff_n_piece(pa);
   7605 	isl_pw_aff_free(pa);
   7606 
   7607 	if (n < 0)
   7608 		return -1;
   7609 	if (n != 1)
   7610 		isl_die(ctx, isl_error_unknown, "expecting single expression",
   7611 			return -1);
   7612 
   7613 	return 0;
   7614 }
   7615 
   7616 /* Check that the computation below results in a single expression.
   7617  * One or two expressions may result depending on which constraint
   7618  * ends up being considered as redundant with respect to the other
   7619  * constraints after the projection that is performed internally
   7620  * by isl_set_dim_min.
   7621  */
   7622 static int test_dim_max_1(isl_ctx *ctx)
   7623 {
   7624 	const char *str;
   7625 	isl_set *set;
   7626 	isl_pw_aff *pa;
   7627 
   7628 	str = "[n] -> { [a, b] : n >= 0 and 4a >= -4 + n and b >= 0 and "
   7629 				"-4a <= b <= 3 and b < n - 4a }";
   7630 	set = isl_set_read_from_str(ctx, str);
   7631 	pa = isl_set_dim_min(set, 0);
   7632 	return check_single_piece(ctx, pa);
   7633 }
   7634 
   7635 /* Check that the computation below results in a single expression.
   7636  * The PIP problem corresponding to these constraints has a row
   7637  * that causes a split of the solution domain.  The solver should
   7638  * first pick rows that split off empty parts such that the actual
   7639  * solution domain does not get split.
   7640  * Note that the description contains some redundant constraints.
   7641  * If these constraints get removed first, then the row mentioned
   7642  * above does not appear in the PIP problem.
   7643  */
   7644 static int test_dim_max_2(isl_ctx *ctx)
   7645 {
   7646 	const char *str;
   7647 	isl_set *set;
   7648 	isl_pw_aff *pa;
   7649 
   7650 	str = "[P, N] -> { [a] : a < N and a >= 0 and N > P and a <= P and "
   7651 				"N > 0 and P >= 0 }";
   7652 	set = isl_set_read_from_str(ctx, str);
   7653 	pa = isl_set_dim_max(set, 0);
   7654 	return check_single_piece(ctx, pa);
   7655 }
   7656 
   7657 int test_dim_max(isl_ctx *ctx)
   7658 {
   7659 	int equal;
   7660 	const char *str;
   7661 	isl_set *set1, *set2;
   7662 	isl_set *set;
   7663 	isl_map *map;
   7664 	isl_pw_aff *pwaff;
   7665 
   7666 	if (test_dim_max_1(ctx) < 0)
   7667 		return -1;
   7668 	if (test_dim_max_2(ctx) < 0)
   7669 		return -1;
   7670 
   7671 	str = "[N] -> { [i] : 0 <= i <= min(N,10) }";
   7672 	set = isl_set_read_from_str(ctx, str);
   7673 	pwaff = isl_set_dim_max(set, 0);
   7674 	set1 = isl_set_from_pw_aff(pwaff);
   7675 	str = "[N] -> { [10] : N >= 10; [N] : N <= 9 and N >= 0 }";
   7676 	set2 = isl_set_read_from_str(ctx, str);
   7677 	equal = isl_set_is_equal(set1, set2);
   7678 	isl_set_free(set1);
   7679 	isl_set_free(set2);
   7680 	if (equal < 0)
   7681 		return -1;
   7682 	if (!equal)
   7683 		isl_die(ctx, isl_error_unknown, "unexpected result", return -1);
   7684 
   7685 	str = "[N] -> { [i] : 0 <= i <= max(2N,N+6) }";
   7686 	set = isl_set_read_from_str(ctx, str);
   7687 	pwaff = isl_set_dim_max(set, 0);
   7688 	set1 = isl_set_from_pw_aff(pwaff);
   7689 	str = "[N] -> { [6 + N] : -6 <= N <= 5; [2N] : N >= 6 }";
   7690 	set2 = isl_set_read_from_str(ctx, str);
   7691 	equal = isl_set_is_equal(set1, set2);
   7692 	isl_set_free(set1);
   7693 	isl_set_free(set2);
   7694 	if (equal < 0)
   7695 		return -1;
   7696 	if (!equal)
   7697 		isl_die(ctx, isl_error_unknown, "unexpected result", return -1);
   7698 
   7699 	str = "[N] -> { [i] : 0 <= i <= 2N or 0 <= i <= N+6 }";
   7700 	set = isl_set_read_from_str(ctx, str);
   7701 	pwaff = isl_set_dim_max(set, 0);
   7702 	set1 = isl_set_from_pw_aff(pwaff);
   7703 	str = "[N] -> { [6 + N] : -6 <= N <= 5; [2N] : N >= 6 }";
   7704 	set2 = isl_set_read_from_str(ctx, str);
   7705 	equal = isl_set_is_equal(set1, set2);
   7706 	isl_set_free(set1);
   7707 	isl_set_free(set2);
   7708 	if (equal < 0)
   7709 		return -1;
   7710 	if (!equal)
   7711 		isl_die(ctx, isl_error_unknown, "unexpected result", return -1);
   7712 
   7713 	str = "[N,M] -> { [i,j] -> [([i/16]), i%16, ([j/16]), j%16] : "
   7714 			"0 <= i < N and 0 <= j < M }";
   7715 	map = isl_map_read_from_str(ctx, str);
   7716 	set = isl_map_range(map);
   7717 
   7718 	pwaff = isl_set_dim_max(isl_set_copy(set), 0);
   7719 	set1 = isl_set_from_pw_aff(pwaff);
   7720 	str = "[N,M] -> { [([(N-1)/16])] : M,N > 0 }";
   7721 	set2 = isl_set_read_from_str(ctx, str);
   7722 	equal = isl_set_is_equal(set1, set2);
   7723 	isl_set_free(set1);
   7724 	isl_set_free(set2);
   7725 
   7726 	pwaff = isl_set_dim_max(isl_set_copy(set), 3);
   7727 	set1 = isl_set_from_pw_aff(pwaff);
   7728 	str = "[N,M] -> { [t] : t = min(M-1,15) and M,N > 0 }";
   7729 	set2 = isl_set_read_from_str(ctx, str);
   7730 	if (equal >= 0 && equal)
   7731 		equal = isl_set_is_equal(set1, set2);
   7732 	isl_set_free(set1);
   7733 	isl_set_free(set2);
   7734 
   7735 	isl_set_free(set);
   7736 
   7737 	if (equal < 0)
   7738 		return -1;
   7739 	if (!equal)
   7740 		isl_die(ctx, isl_error_unknown, "unexpected result", return -1);
   7741 
   7742 	/* Check that solutions are properly merged. */
   7743 	str = "[n] -> { [a, b, c] : c >= -4a - 2b and "
   7744 				"c <= -1 + n - 4a - 2b and c >= -2b and "
   7745 				"4a >= -4 + n and c >= 0 }";
   7746 	set = isl_set_read_from_str(ctx, str);
   7747 	pwaff = isl_set_dim_min(set, 2);
   7748 	set1 = isl_set_from_pw_aff(pwaff);
   7749 	str = "[n] -> { [(0)] : n >= 1 }";
   7750 	set2 = isl_set_read_from_str(ctx, str);
   7751 	equal = isl_set_is_equal(set1, set2);
   7752 	isl_set_free(set1);
   7753 	isl_set_free(set2);
   7754 
   7755 	if (equal < 0)
   7756 		return -1;
   7757 	if (!equal)
   7758 		isl_die(ctx, isl_error_unknown, "unexpected result", return -1);
   7759 
   7760 	/* Check that empty solution lie in the right space. */
   7761 	str = "[n] -> { [t,a] : 1 = 0 }";
   7762 	set = isl_set_read_from_str(ctx, str);
   7763 	pwaff = isl_set_dim_max(set, 0);
   7764 	set1 = isl_set_from_pw_aff(pwaff);
   7765 	str = "[n] -> { [t] : 1 = 0 }";
   7766 	set2 = isl_set_read_from_str(ctx, str);
   7767 	equal = isl_set_is_equal(set1, set2);
   7768 	isl_set_free(set1);
   7769 	isl_set_free(set2);
   7770 
   7771 	if (equal < 0)
   7772 		return -1;
   7773 	if (!equal)
   7774 		isl_die(ctx, isl_error_unknown, "unexpected result", return -1);
   7775 
   7776 	return 0;
   7777 }
   7778 
   7779 /* Basic test for isl_pw_multi_aff_product.
   7780  *
   7781  * Check that multiple pieces are properly handled.
   7782  */
   7783 static int test_product_pma(isl_ctx *ctx)
   7784 {
   7785 	isl_stat equal;
   7786 	const char *str;
   7787 	isl_pw_multi_aff *pma1, *pma2;
   7788 
   7789 	str = "{ A[i] -> B[1] : i < 0; A[i] -> B[2] : i >= 0 }";
   7790 	pma1 = isl_pw_multi_aff_read_from_str(ctx, str);
   7791 	str = "{ C[] -> D[] }";
   7792 	pma2 = isl_pw_multi_aff_read_from_str(ctx, str);
   7793 	pma1 = isl_pw_multi_aff_product(pma1, pma2);
   7794 	str = "{ [A[i] -> C[]] -> [B[(1)] -> D[]] : i < 0;"
   7795 		"[A[i] -> C[]] -> [B[(2)] -> D[]] : i >= 0 }";
   7796 	equal = pw_multi_aff_check_plain_equal(pma1, str);
   7797 	isl_pw_multi_aff_free(pma1);
   7798 	if (equal < 0)
   7799 		return -1;
   7800 
   7801 	return 0;
   7802 }
   7803 
   7804 int test_product(isl_ctx *ctx)
   7805 {
   7806 	const char *str;
   7807 	isl_set *set;
   7808 	isl_union_set *uset1, *uset2;
   7809 	int ok;
   7810 
   7811 	str = "{ A[i] }";
   7812 	set = isl_set_read_from_str(ctx, str);
   7813 	set = isl_set_product(set, isl_set_copy(set));
   7814 	ok = isl_set_is_wrapping(set);
   7815 	isl_set_free(set);
   7816 	if (ok < 0)
   7817 		return -1;
   7818 	if (!ok)
   7819 		isl_die(ctx, isl_error_unknown, "unexpected result", return -1);
   7820 
   7821 	str = "{ [] }";
   7822 	uset1 = isl_union_set_read_from_str(ctx, str);
   7823 	uset1 = isl_union_set_product(uset1, isl_union_set_copy(uset1));
   7824 	str = "{ [[] -> []] }";
   7825 	uset2 = isl_union_set_read_from_str(ctx, str);
   7826 	ok = isl_union_set_is_equal(uset1, uset2);
   7827 	isl_union_set_free(uset1);
   7828 	isl_union_set_free(uset2);
   7829 	if (ok < 0)
   7830 		return -1;
   7831 	if (!ok)
   7832 		isl_die(ctx, isl_error_unknown, "unexpected result", return -1);
   7833 
   7834 	if (test_product_pma(ctx) < 0)
   7835 		return -1;
   7836 
   7837 	return 0;
   7838 }
   7839 
   7840 /* Check that two sets are not considered disjoint just because
   7841  * they have a different set of (named) parameters.
   7842  */
   7843 static int test_disjoint(isl_ctx *ctx)
   7844 {
   7845 	const char *str;
   7846 	isl_set *set, *set2;
   7847 	int disjoint;
   7848 
   7849 	str = "[n] -> { [[]->[]] }";
   7850 	set = isl_set_read_from_str(ctx, str);
   7851 	str = "{ [[]->[]] }";
   7852 	set2 = isl_set_read_from_str(ctx, str);
   7853 	disjoint = isl_set_is_disjoint(set, set2);
   7854 	isl_set_free(set);
   7855 	isl_set_free(set2);
   7856 	if (disjoint < 0)
   7857 		return -1;
   7858 	if (disjoint)
   7859 		isl_die(ctx, isl_error_unknown, "unexpected result", return -1);
   7860 
   7861 	return 0;
   7862 }
   7863 
   7864 /* Inputs for isl_pw_multi_aff_is_equal tests.
   7865  * "f1" and "f2" are the two function that need to be compared.
   7866  * "equal" is the expected result.
   7867  */
   7868 struct {
   7869 	int equal;
   7870 	const char *f1;
   7871 	const char *f2;
   7872 } pma_equal_tests[] = {
   7873 	{ 1, "[N] -> { [floor(N/2)] : 0 <= N <= 1 }",
   7874 	     "[N] -> { [0] : 0 <= N <= 1 }" },
   7875 	{ 1, "[N] -> { [floor(N/2)] : 0 <= N <= 2 }",
   7876 	     "[N] -> { [0] : 0 <= N <= 1; [1] : N = 2 }" },
   7877 	{ 0, "[N] -> { [floor(N/2)] : 0 <= N <= 2 }",
   7878 	     "[N] -> { [0] : 0 <= N <= 1 }" },
   7879 	{ 0, "{ [NaN] }", "{ [NaN] }" },
   7880 };
   7881 
   7882 int test_equal(isl_ctx *ctx)
   7883 {
   7884 	int i;
   7885 	const char *str;
   7886 	isl_set *set, *set2;
   7887 	int equal;
   7888 
   7889 	str = "{ S_6[i] }";
   7890 	set = isl_set_read_from_str(ctx, str);
   7891 	str = "{ S_7[i] }";
   7892 	set2 = isl_set_read_from_str(ctx, str);
   7893 	equal = isl_set_is_equal(set, set2);
   7894 	isl_set_free(set);
   7895 	isl_set_free(set2);
   7896 	if (equal < 0)
   7897 		return -1;
   7898 	if (equal)
   7899 		isl_die(ctx, isl_error_unknown, "unexpected result", return -1);
   7900 
   7901 	for (i = 0; i < ARRAY_SIZE(pma_equal_tests); ++i) {
   7902 		int expected = pma_equal_tests[i].equal;
   7903 		isl_pw_multi_aff *f1, *f2;
   7904 
   7905 		f1 = isl_pw_multi_aff_read_from_str(ctx, pma_equal_tests[i].f1);
   7906 		f2 = isl_pw_multi_aff_read_from_str(ctx, pma_equal_tests[i].f2);
   7907 		equal = isl_pw_multi_aff_is_equal(f1, f2);
   7908 		isl_pw_multi_aff_free(f1);
   7909 		isl_pw_multi_aff_free(f2);
   7910 		if (equal < 0)
   7911 			return -1;
   7912 		if (equal != expected)
   7913 			isl_die(ctx, isl_error_unknown,
   7914 				"unexpected equality result", return -1);
   7915 	}
   7916 
   7917 	return 0;
   7918 }
   7919 
   7920 static int test_plain_fixed(isl_ctx *ctx, __isl_take isl_map *map,
   7921 	enum isl_dim_type type, unsigned pos, int fixed)
   7922 {
   7923 	isl_bool test;
   7924 
   7925 	test = isl_map_plain_is_fixed(map, type, pos, NULL);
   7926 	isl_map_free(map);
   7927 	if (test < 0)
   7928 		return -1;
   7929 	if (test == fixed)
   7930 		return 0;
   7931 	if (fixed)
   7932 		isl_die(ctx, isl_error_unknown,
   7933 			"map not detected as fixed", return -1);
   7934 	else
   7935 		isl_die(ctx, isl_error_unknown,
   7936 			"map detected as fixed", return -1);
   7937 }
   7938 
   7939 int test_fixed(isl_ctx *ctx)
   7940 {
   7941 	const char *str;
   7942 	isl_map *map;
   7943 
   7944 	str = "{ [i] -> [i] }";
   7945 	map = isl_map_read_from_str(ctx, str);
   7946 	if (test_plain_fixed(ctx, map, isl_dim_out, 0, 0))
   7947 		return -1;
   7948 	str = "{ [i] -> [1] }";
   7949 	map = isl_map_read_from_str(ctx, str);
   7950 	if (test_plain_fixed(ctx, map, isl_dim_out, 0, 1))
   7951 		return -1;
   7952 	str = "{ S_1[p1] -> [o0] : o0 = -2 and p1 >= 1 and p1 <= 7 }";
   7953 	map = isl_map_read_from_str(ctx, str);
   7954 	if (test_plain_fixed(ctx, map, isl_dim_out, 0, 1))
   7955 		return -1;
   7956 	map = isl_map_read_from_str(ctx, str);
   7957 	map = isl_map_neg(map);
   7958 	if (test_plain_fixed(ctx, map, isl_dim_out, 0, 1))
   7959 		return -1;
   7960 
   7961 	return 0;
   7962 }
   7963 
   7964 struct isl_vertices_test_data {
   7965 	const char *set;
   7966 	int n;
   7967 	const char *vertex[6];
   7968 } vertices_tests[] = {
   7969 	{ "{ A[t, i] : t = 12 and i >= 4 and i <= 12 }",
   7970 	  2, { "{ A[12, 4] }", "{ A[12, 12] }" } },
   7971 	{ "{ A[t, i] : t = 14 and i = 1 }",
   7972 	  1, { "{ A[14, 1] }" } },
   7973 	{ "[n, m] -> { [a, b, c] : b <= a and a <= n and b > 0 and c >= b and "
   7974 				"c <= m and m <= n and m > 0 }",
   7975 	  6, {
   7976 		"[n, m] -> { [n, m, m] : 0 < m <= n }",
   7977 		"[n, m] -> { [n, 1, m] : 0 < m <= n }",
   7978 		"[n, m] -> { [n, 1, 1] : 0 < m <= n }",
   7979 		"[n, m] -> { [m, m, m] : 0 < m <= n }",
   7980 		"[n, m] -> { [1, 1, m] : 0 < m <= n }",
   7981 		"[n, m] -> { [1, 1, 1] : 0 < m <= n }"
   7982 	    } },
   7983 	/* An input with implicit equality constraints among the parameters. */
   7984 	{ "[N, M] -> { [a, b] : M >= 3 and 9 + 3M <= a <= 29 + 2N + 11M and "
   7985 			    "2b >= M + a and 5 - 2N - M + a <= 2b <= 3 + a and "
   7986 			    "3b >= 15 + a }",
   7987 	  2, {
   7988 		"[N, M] -> { [(21), (12)] : M = 3 and N >= 0 }",
   7989 		"[N, M] -> { [(61 + 2N), (32 + N)] : M = 3 and N >= 0 }",
   7990 	     }
   7991 	},
   7992 };
   7993 
   7994 /* Check that "vertex" corresponds to one of the vertices in data->vertex.
   7995  */
   7996 static isl_stat find_vertex(__isl_take isl_vertex *vertex, void *user)
   7997 {
   7998 	struct isl_vertices_test_data *data = user;
   7999 	isl_ctx *ctx;
   8000 	isl_multi_aff *ma;
   8001 	isl_basic_set *bset;
   8002 	isl_pw_multi_aff *pma;
   8003 	int i;
   8004 	isl_bool equal;
   8005 
   8006 	ctx = isl_vertex_get_ctx(vertex);
   8007 	bset = isl_vertex_get_domain(vertex);
   8008 	ma = isl_vertex_get_expr(vertex);
   8009 	pma = isl_pw_multi_aff_alloc(isl_set_from_basic_set(bset), ma);
   8010 
   8011 	for (i = 0; i < data->n; ++i) {
   8012 		isl_pw_multi_aff *pma_i;
   8013 
   8014 		pma_i = isl_pw_multi_aff_read_from_str(ctx, data->vertex[i]);
   8015 		equal = isl_pw_multi_aff_plain_is_equal(pma, pma_i);
   8016 		isl_pw_multi_aff_free(pma_i);
   8017 
   8018 		if (equal < 0 || equal)
   8019 			break;
   8020 	}
   8021 
   8022 	isl_pw_multi_aff_free(pma);
   8023 	isl_vertex_free(vertex);
   8024 
   8025 	if (equal < 0)
   8026 		return isl_stat_error;
   8027 
   8028 	return equal ? isl_stat_ok : isl_stat_error;
   8029 }
   8030 
   8031 int test_vertices(isl_ctx *ctx)
   8032 {
   8033 	int i;
   8034 
   8035 	for (i = 0; i < ARRAY_SIZE(vertices_tests); ++i) {
   8036 		isl_basic_set *bset;
   8037 		isl_vertices *vertices;
   8038 		int ok = 1;
   8039 		isl_size n;
   8040 
   8041 		bset = isl_basic_set_read_from_str(ctx, vertices_tests[i].set);
   8042 		vertices = isl_basic_set_compute_vertices(bset);
   8043 		n = isl_vertices_get_n_vertices(vertices);
   8044 		if (vertices_tests[i].n != n)
   8045 			ok = 0;
   8046 		if (isl_vertices_foreach_vertex(vertices, &find_vertex,
   8047 						&vertices_tests[i]) < 0)
   8048 			ok = 0;
   8049 		isl_vertices_free(vertices);
   8050 		isl_basic_set_free(bset);
   8051 
   8052 		if (n < 0)
   8053 			return -1;
   8054 		if (!ok)
   8055 			isl_die(ctx, isl_error_unknown, "unexpected vertices",
   8056 				return -1);
   8057 	}
   8058 
   8059 	return 0;
   8060 }
   8061 
   8062 /* Inputs for basic tests of binary operations on isl_union_map.
   8063  * "fn" is the function that is being tested.
   8064  * "arg1" and "arg2" are string descriptions of the inputs.
   8065  * "res" is a string description of the expected result.
   8066  */
   8067 static struct {
   8068 	__isl_give isl_union_map *(*fn)(__isl_take isl_union_map *umap1,
   8069 				__isl_take isl_union_map *umap2);
   8070 	const char *arg1;
   8071 	const char *arg2;
   8072 	const char *res;
   8073 } umap_bin_tests[] = {
   8074 	{ &isl_union_map_intersect,
   8075 	  "[n] -> { A[i] -> [] : 0 <= i <= n; B[] -> [] }",
   8076 	  "[m] -> { A[i] -> [] : 0 <= i <= m; C[] -> [] }",
   8077 	  "[m, n] -> { A[i] -> [] : 0 <= i <= n and i <= m }" },
   8078 	{ &isl_union_map_intersect_domain_factor_domain,
   8079 	  "{ [A[i] -> B[i + 1]] -> C[i + 2] }",
   8080 	  "[N] -> { B[i] -> C[N] }",
   8081 	  "{ }" },
   8082 	{ &isl_union_map_intersect_domain_factor_domain,
   8083 	  "{ [A[i] -> B[i + 1]] -> C[i + 2] }",
   8084 	  "[N] -> { A[i] -> C[N] }",
   8085 	  "[N] -> { [A[N - 2] -> B[N - 1]] -> C[N] }" },
   8086 	{ &isl_union_map_intersect_domain_factor_domain,
   8087 	  "{ T[A[i] -> B[i + 1]] -> C[i + 2] }",
   8088 	  "[N] -> { A[i] -> C[N] }",
   8089 	  "[N] -> { T[A[N - 2] -> B[N - 1]] -> C[N] }" },
   8090 	{ &isl_union_map_intersect_domain_factor_range,
   8091 	  "{ [A[i] -> B[i + 1]] -> C[i + 2] }",
   8092 	  "[N] -> { B[i] -> C[N] }",
   8093 	  "[N] -> { [A[N - 2] -> B[N - 1]] -> C[N] }" },
   8094 	{ &isl_union_map_intersect_domain_factor_range,
   8095 	  "{ T[A[i] -> B[i + 1]] -> C[i + 2] }",
   8096 	  "[N] -> { B[i] -> C[N] }",
   8097 	  "[N] -> { T[A[N - 2] -> B[N - 1]] -> C[N] }" },
   8098 	{ &isl_union_map_intersect_domain_factor_range,
   8099 	  "{ [A[i] -> B[i + 1]] -> C[i + 2] }",
   8100 	  "[N] -> { A[i] -> C[N] }",
   8101 	  "{ }" },
   8102 	{ &isl_union_map_intersect_range_factor_domain,
   8103 	  "{ A[i] -> [B[i + 1] -> C[i + 2]] }",
   8104 	  "[N] -> { A[i] -> B[N] }",
   8105 	  "[N] -> { A[N - 1] -> [B[N] -> C[N + 1]] }" },
   8106 	{ &isl_union_map_intersect_range_factor_domain,
   8107 	  "{ A[i] -> T[B[i + 1] -> C[i + 2]] }",
   8108 	  "[N] -> { A[i] -> B[N] }",
   8109 	  "[N] -> { A[N - 1] -> T[B[N] -> C[N + 1]] }" },
   8110 	{ &isl_union_map_intersect_range_factor_domain,
   8111 	  "{ A[i] -> [B[i + 1] -> C[i + 2]] }",
   8112 	  "[N] -> { A[i] -> C[N] }",
   8113 	  "{ }" },
   8114 	{ &isl_union_map_intersect_range_factor_range,
   8115 	  "{ A[i] -> [B[i + 1] -> C[i + 2]] }",
   8116 	  "[N] -> { A[i] -> C[N] }",
   8117 	  "[N] -> { A[N - 2] -> [B[N - 1] -> C[N]] }" },
   8118 	{ &isl_union_map_intersect_range_factor_range,
   8119 	  "{ A[i] -> T[B[i + 1] -> C[i + 2]] }",
   8120 	  "[N] -> { A[i] -> C[N] }",
   8121 	  "[N] -> { A[N - 2] -> T[B[N - 1] -> C[N]] }" },
   8122 	{ &isl_union_map_intersect_range_factor_range,
   8123 	  "{ A[i] -> [B[i + 1] -> C[i + 2]] }",
   8124 	  "[N] -> { A[i] -> B[N] }",
   8125 	  "{ }" },
   8126 };
   8127 
   8128 /* Perform basic tests of binary operations on isl_union_map.
   8129  */
   8130 static isl_stat test_bin_union_map(isl_ctx *ctx)
   8131 {
   8132 	int i;
   8133 
   8134 	for (i = 0; i < ARRAY_SIZE(umap_bin_tests); ++i) {
   8135 		const char *str;
   8136 		isl_union_map *umap1, *umap2, *res;
   8137 		isl_bool equal;
   8138 
   8139 		str = umap_bin_tests[i].arg1;
   8140 		umap1 = isl_union_map_read_from_str(ctx, str);
   8141 		str = umap_bin_tests[i].arg2;
   8142 		umap2 = isl_union_map_read_from_str(ctx, str);
   8143 		str = umap_bin_tests[i].res;
   8144 		res = isl_union_map_read_from_str(ctx, str);
   8145 		umap1 = umap_bin_tests[i].fn(umap1, umap2);
   8146 		equal = isl_union_map_is_equal(umap1, res);
   8147 		isl_union_map_free(umap1);
   8148 		isl_union_map_free(res);
   8149 		if (equal < 0)
   8150 			return isl_stat_error;
   8151 		if (!equal)
   8152 			isl_die(ctx, isl_error_unknown,
   8153 				"unexpected result", return isl_stat_error);
   8154 	}
   8155 
   8156 	return isl_stat_ok;
   8157 }
   8158 
   8159 /* Check that isl_union_set_contains finds space independently
   8160  * of the parameters.
   8161  */
   8162 static isl_stat test_union_set_contains(isl_ctx *ctx)
   8163 {
   8164 	const char *str;
   8165 	isl_bool ok;
   8166 	isl_space *space;
   8167 	isl_id *id;
   8168 	isl_union_set *uset;
   8169 
   8170 	str = "[N] -> { A[0:N]; B[*,*] }";
   8171 	uset = isl_union_set_read_from_str(ctx, str);
   8172 	space = isl_space_unit(ctx);
   8173 	id = isl_id_alloc(ctx, "A", NULL);
   8174 	space = isl_space_add_named_tuple_id_ui(space, id, 1);
   8175 	ok = isl_union_set_contains(uset, space);
   8176 	isl_space_free(space);
   8177 	isl_union_set_free(uset);
   8178 
   8179 	if (ok < 0)
   8180 		return isl_stat_error;
   8181 	if (!ok)
   8182 		isl_die(ctx, isl_error_unknown,
   8183 			"unexpected result", return isl_stat_error);
   8184 
   8185 	return isl_stat_ok;
   8186 }
   8187 
   8188 /* Perform basic tests of operations on isl_union_map or isl_union_set.
   8189  */
   8190 static int test_union_map(isl_ctx *ctx)
   8191 {
   8192 	if (test_bin_union_map(ctx) < 0)
   8193 		return -1;
   8194 	if (test_union_set_contains(ctx) < 0)
   8195 		return -1;
   8196 	return 0;
   8197 }
   8198 
   8199 #undef BASE
   8200 #define BASE	union_pw_qpolynomial
   8201 #include "isl_test_plain_equal_templ.c"
   8202 
   8203 /* Check that the result of applying "fn" to "a" and "b"
   8204  * in (obviously) equal to "res".
   8205  */
   8206 static isl_stat test_union_pw_op(isl_ctx *ctx, const char *a, const char *b,
   8207 	__isl_give isl_union_pw_qpolynomial *(*fn)(
   8208 		__isl_take isl_union_pw_qpolynomial *upwqp1,
   8209 		__isl_take isl_union_pw_qpolynomial *upwqp2),
   8210 	const char *res)
   8211 {
   8212 	isl_stat r;
   8213 	isl_union_pw_qpolynomial *upwqp1, *upwqp2;
   8214 
   8215 	upwqp1 = isl_union_pw_qpolynomial_read_from_str(ctx, a);
   8216 	upwqp2 = isl_union_pw_qpolynomial_read_from_str(ctx, b);
   8217 	upwqp1 = fn(upwqp1, upwqp2);
   8218 	r = union_pw_qpolynomial_check_plain_equal(upwqp1, res);
   8219 	isl_union_pw_qpolynomial_free(upwqp1);
   8220 
   8221 	return r;
   8222 }
   8223 
   8224 int test_union_pw(isl_ctx *ctx)
   8225 {
   8226 	int equal;
   8227 	isl_stat r;
   8228 	const char *str;
   8229 	isl_union_set *uset;
   8230 	isl_union_pw_qpolynomial *upwqp1, *upwqp2;
   8231 	const char *a, *b;
   8232 
   8233 	str = "{ [x] -> x^2 }";
   8234 	upwqp1 = isl_union_pw_qpolynomial_read_from_str(ctx, str);
   8235 	upwqp2 = isl_union_pw_qpolynomial_copy(upwqp1);
   8236 	uset = isl_union_pw_qpolynomial_domain(upwqp1);
   8237 	upwqp1 = isl_union_pw_qpolynomial_copy(upwqp2);
   8238 	upwqp1 = isl_union_pw_qpolynomial_intersect_domain(upwqp1, uset);
   8239 	equal = isl_union_pw_qpolynomial_plain_is_equal(upwqp1, upwqp2);
   8240 	isl_union_pw_qpolynomial_free(upwqp1);
   8241 	isl_union_pw_qpolynomial_free(upwqp2);
   8242 	if (equal < 0)
   8243 		return -1;
   8244 	if (!equal)
   8245 		isl_die(ctx, isl_error_unknown, "unexpected result", return -1);
   8246 
   8247 	a = "{ A[x] -> x^2 : x >= 0; B[x] -> x }";
   8248 	b = "{ A[x] -> x }";
   8249 	str = "{ A[x] -> x^2 + x : x >= 0; A[x] -> x : x < 0; B[x] -> x }";
   8250 	if (test_union_pw_op(ctx, a, b, &isl_union_pw_qpolynomial_add, str) < 0)
   8251 		return -1;
   8252 	str = "{ A[x] -> x^2 - x : x >= 0; A[x] -> -x : x < 0; B[x] -> x }";
   8253 	if (test_union_pw_op(ctx, a, b, &isl_union_pw_qpolynomial_sub, str) < 0)
   8254 		return -1;
   8255 
   8256 	str = "{ A[x] -> 0 }";
   8257 	a = "{ A[x] -> 1 }";
   8258 	b = "{ A[x] -> -1 }";
   8259 	if (test_union_pw_op(ctx, a, b, &isl_union_pw_qpolynomial_add, str) < 0)
   8260 		return -1;
   8261 	a = "{ A[x] -> 1 }";
   8262 	b = "{ A[x] -> 1 }";
   8263 	if (test_union_pw_op(ctx, a, b, &isl_union_pw_qpolynomial_sub, str) < 0)
   8264 		return -1;
   8265 
   8266 	str = "{ [A[x] -> B[y,z]] -> x^2 + y * floor(x/4) * floor(z/2); "
   8267 		"C[z] -> z^3 }";
   8268 	upwqp1 = isl_union_pw_qpolynomial_read_from_str(ctx, str);
   8269 	upwqp1 = isl_union_pw_qpolynomial_domain_reverse(upwqp1);
   8270 	str = "{ [B[y,z] -> A[x]] -> x^2 + y * floor(x/4) * floor(z/2) }";
   8271 	r = union_pw_qpolynomial_check_plain_equal(upwqp1, str);
   8272 	isl_union_pw_qpolynomial_free(upwqp1);
   8273 	if (r < 0)
   8274 		return -1;
   8275 
   8276 	return 0;
   8277 }
   8278 
   8279 /* Inputs for basic tests of functions that select
   8280  * subparts of the domain of an isl_multi_union_pw_aff.
   8281  * "fn" is the function that is tested.
   8282  * "arg" is a string description of the input.
   8283  * "res" is a string description of the expected result.
   8284  */
   8285 struct {
   8286 	__isl_give isl_union_set *(*fn)(
   8287 		__isl_take isl_multi_union_pw_aff *mupa);
   8288 	const char *arg;
   8289 	const char *res;
   8290 } un_locus_tests[] = {
   8291 	{ &isl_multi_union_pw_aff_zero_union_set,
   8292 	  "F[{ A[i,j] -> [i]; B[i,j] -> [i] }]",
   8293 	  "{ A[0,j]; B[0,j] }" },
   8294 	{ &isl_multi_union_pw_aff_zero_union_set,
   8295 	  "F[{ A[i,j] -> [i-j]; B[i,j] -> [i-j] : i >= 0 }]",
   8296 	  "{ A[i,i]; B[i,i] : i >= 0 }" },
   8297 	{ &isl_multi_union_pw_aff_zero_union_set,
   8298 	  "(F[] : { A[i,j]; B[i,i] : i >= 0 })",
   8299 	  "{ A[i,j]; B[i,i] : i >= 0 }" },
   8300 };
   8301 
   8302 /* Perform some basic tests of functions that select
   8303  * subparts of the domain of an isl_multi_union_pw_aff.
   8304  */
   8305 static int test_un_locus(isl_ctx *ctx)
   8306 {
   8307 	int i;
   8308 	isl_bool ok;
   8309 	isl_union_set *uset, *res;
   8310 	isl_multi_union_pw_aff *mupa;
   8311 
   8312 	for (i = 0; i < ARRAY_SIZE(un_locus_tests); ++i) {
   8313 		mupa = isl_multi_union_pw_aff_read_from_str(ctx,
   8314 						    un_locus_tests[i].arg);
   8315 		res = isl_union_set_read_from_str(ctx, un_locus_tests[i].res);
   8316 		uset = un_locus_tests[i].fn(mupa);
   8317 		ok = isl_union_set_is_equal(uset, res);
   8318 		isl_union_set_free(uset);
   8319 		isl_union_set_free(res);
   8320 		if (ok < 0)
   8321 			return -1;
   8322 		if (!ok)
   8323 			isl_die(ctx, isl_error_unknown,
   8324 				"unexpected result", return -1);
   8325 	}
   8326 
   8327 	return 0;
   8328 }
   8329 
   8330 /* Inputs for basic tests of functions that select
   8331  * subparts of an isl_union_map based on a relation
   8332  * specified by an isl_multi_union_pw_aff.
   8333  * "fn" is the function that is tested.
   8334  * "arg1" and "arg2" are string descriptions of the inputs.
   8335  * "res" is a string description of the expected result.
   8336  */
   8337 struct {
   8338 	__isl_give isl_union_map *(*fn)(
   8339 		__isl_take isl_union_map *umap,
   8340 		__isl_take isl_multi_union_pw_aff *mupa);
   8341 	const char *arg1;
   8342 	const char *arg2;
   8343 	const char *res;
   8344 } bin_locus_tests[] = {
   8345 	{ &isl_union_map_eq_at_multi_union_pw_aff,
   8346 	  "{ A[i,j] -> B[i',j'] }",
   8347 	  "F[{ A[i,j] -> [i]; B[i,j] -> [i] }]",
   8348 	  "{ A[i,j] -> B[i,j'] }" },
   8349 	{ &isl_union_map_eq_at_multi_union_pw_aff,
   8350 	  "{ A[i,j] -> B[i',j'] }",
   8351 	  "F[{ A[i,j] -> [i]; B[i,j] -> [i] }, "
   8352 	    "{ A[i,j] -> [j]; B[i,j] -> [j] }]",
   8353 	  "{ A[i,j] -> B[i,j] }" },
   8354 	{ &isl_union_map_eq_at_multi_union_pw_aff,
   8355 	  "{ A[i,j] -> B[i',j']; A[i,j] -> C[i',j'] }",
   8356 	  "F[{ A[i,j] -> [i]; B[i,j] -> [i] }]",
   8357 	  "{ A[i,j] -> B[i,j'] }" },
   8358 	{ &isl_union_map_eq_at_multi_union_pw_aff,
   8359 	  "{ A[i,j] -> B[i',j']; A[i,j] -> C[i',j'] }",
   8360 	  "F[{ A[i,j] -> [i]; B[i,j] -> [i]; C[i,j] -> [0] }]",
   8361 	  "{ A[i,j] -> B[i,j']; A[0,j] -> C[i',j'] }" },
   8362 	{ &isl_union_map_eq_at_multi_union_pw_aff,
   8363 	  "{ A[i,j] -> B[i',j'] }",
   8364 	  "F[{ A[i,j] -> [i] : i > j; B[i,j] -> [i] }]",
   8365 	  "{ A[i,j] -> B[i,j'] : i > j }" },
   8366 	{ &isl_union_map_lex_le_at_multi_union_pw_aff,
   8367 	  "{ A[i,j] -> B[i',j'] }",
   8368 	  "F[{ A[i,j] -> [i]; B[i,j] -> [i] }, "
   8369 	    "{ A[i,j] -> [j]; B[i,j] -> [j] }]",
   8370 	  "{ A[i,j] -> B[i',j'] : i,j <<= i',j' }" },
   8371 	{ &isl_union_map_lex_lt_at_multi_union_pw_aff,
   8372 	  "{ A[i,j] -> B[i',j'] }",
   8373 	  "F[{ A[i,j] -> [i]; B[i,j] -> [i] }, "
   8374 	    "{ A[i,j] -> [j]; B[i,j] -> [j] }]",
   8375 	  "{ A[i,j] -> B[i',j'] : i,j << i',j' }" },
   8376 	{ &isl_union_map_lex_ge_at_multi_union_pw_aff,
   8377 	  "{ A[i,j] -> B[i',j'] }",
   8378 	  "F[{ A[i,j] -> [i]; B[i,j] -> [i] }, "
   8379 	    "{ A[i,j] -> [j]; B[i,j] -> [j] }]",
   8380 	  "{ A[i,j] -> B[i',j'] : i,j >>= i',j' }" },
   8381 	{ &isl_union_map_lex_gt_at_multi_union_pw_aff,
   8382 	  "{ A[i,j] -> B[i',j'] }",
   8383 	  "F[{ A[i,j] -> [i]; B[i,j] -> [i] }, "
   8384 	    "{ A[i,j] -> [j]; B[i,j] -> [j] }]",
   8385 	  "{ A[i,j] -> B[i',j'] : i,j >> i',j' }" },
   8386 	{ &isl_union_map_eq_at_multi_union_pw_aff,
   8387 	  "{ A[i,j] -> B[i',j']; A[i,j] -> C[i',j'] }",
   8388 	  "(F[] : { A[i,j]; B[i,j] })",
   8389 	  "{ A[i,j] -> B[i',j'] }" },
   8390 	{ &isl_union_map_eq_at_multi_union_pw_aff,
   8391 	  "{ A[i,j] -> B[i',j'] }",
   8392 	  "(F[] : { A[i,j] : i > j; B[i,j] : i < j })",
   8393 	  "{ A[i,j] -> B[i',j'] : i > j and i' < j' }" },
   8394 	{ &isl_union_map_eq_at_multi_union_pw_aff,
   8395 	  "[N] -> { A[i,j] -> B[i',j'] : i,i' <= N }",
   8396 	  "(F[] : { A[i,j] : i > j; B[i,j] : i < j })",
   8397 	  "[N] -> { A[i,j] -> B[i',j'] : i > j and i' < j' and i,i' <= N }" },
   8398 	{ &isl_union_map_eq_at_multi_union_pw_aff,
   8399 	  "{ A[i,j] -> B[i',j'] }",
   8400 	  "[N] -> (F[] : { A[i,j] : i < N; B[i,j] : i < N })",
   8401 	  "[N] -> { A[i,j] -> B[i',j'] : i,i' < N }" },
   8402 	{ &isl_union_map_eq_at_multi_union_pw_aff,
   8403 	  "{ A[i,j] -> B[i',j'] }",
   8404 	  "[N] -> (F[] : { : N >= 0 })",
   8405 	  "[N] -> { A[i,j] -> B[i',j'] : N >= 0 }" },
   8406 };
   8407 
   8408 /* Perform some basic tests of functions that select
   8409  * subparts of an isl_union_map based on a relation
   8410  * specified by an isl_multi_union_pw_aff.
   8411  */
   8412 static int test_bin_locus(isl_ctx *ctx)
   8413 {
   8414 	int i;
   8415 	isl_bool ok;
   8416 	isl_union_map *umap, *res;
   8417 	isl_multi_union_pw_aff *mupa;
   8418 
   8419 	for (i = 0; i < ARRAY_SIZE(bin_locus_tests); ++i) {
   8420 		umap = isl_union_map_read_from_str(ctx,
   8421 						    bin_locus_tests[i].arg1);
   8422 		mupa = isl_multi_union_pw_aff_read_from_str(ctx,
   8423 						    bin_locus_tests[i].arg2);
   8424 		res = isl_union_map_read_from_str(ctx, bin_locus_tests[i].res);
   8425 		umap = bin_locus_tests[i].fn(umap, mupa);
   8426 		ok = isl_union_map_is_equal(umap, res);
   8427 		isl_union_map_free(umap);
   8428 		isl_union_map_free(res);
   8429 		if (ok < 0)
   8430 			return -1;
   8431 		if (!ok)
   8432 			isl_die(ctx, isl_error_unknown,
   8433 				"unexpected result", return -1);
   8434 	}
   8435 
   8436 	return 0;
   8437 }
   8438 
   8439 /* Inputs for basic tests of functions that determine
   8440  * the part of the domain where two isl_multi_aff objects
   8441  * related to each other in a specific way.
   8442  * "fn" is the function that is being tested.
   8443  * "arg1" and "arg2" are string descriptions of the inputs.
   8444  * "res" is a string description of the expected result.
   8445  */
   8446 static struct {
   8447 	__isl_give isl_set *(*fn)(__isl_take isl_multi_aff *ma1,
   8448 		__isl_take isl_multi_aff *ma2);
   8449 	const char *arg1;
   8450 	const char *arg2;
   8451 	const char *res;
   8452 } bin_locus_ma_tests[] = {
   8453 	{ &isl_multi_aff_lex_le_set, "{ [] }", "{ [] }", "{ : }" },
   8454 	{ &isl_multi_aff_lex_lt_set, "{ [] }", "{ [] }", "{ : false }" },
   8455 	{ &isl_multi_aff_lex_le_set,
   8456 	  "{ A[i] -> [i] }", "{ A[i] -> [0] }",
   8457 	  "{ A[i] : i <= 0 }" },
   8458 	{ &isl_multi_aff_lex_lt_set,
   8459 	  "{ A[i] -> [i] }", "{ A[i] -> [0] }",
   8460 	  "{ A[i] : i < 0 }" },
   8461 	{ &isl_multi_aff_lex_le_set,
   8462 	  "{ A[i] -> [i, i] }", "{ A[i] -> [0, 0] }",
   8463 	  "{ A[i] : i <= 0 }" },
   8464 	{ &isl_multi_aff_lex_le_set,
   8465 	  "{ A[i] -> [i, 0] }", "{ A[i] -> [0, 0] }",
   8466 	  "{ A[i] : i <= 0 }" },
   8467 	{ &isl_multi_aff_lex_le_set,
   8468 	  "{ A[i] -> [i, 1] }", "{ A[i] -> [0, 0] }",
   8469 	  "{ A[i] : i < 0 }" },
   8470 };
   8471 
   8472 /* Perform some basic tests of functions that determine
   8473  * the part of the domain where two isl_multi_aff objects
   8474  * related to each other in a specific way.
   8475  */
   8476 static isl_stat test_bin_locus_ma(isl_ctx *ctx)
   8477 {
   8478 	int i;
   8479 
   8480 	for (i = 0; i < ARRAY_SIZE(bin_locus_ma_tests); ++i) {
   8481 		const char *str;
   8482 		isl_bool ok;
   8483 		isl_multi_aff *ma1, *ma2;
   8484 		isl_set *set, *res;
   8485 
   8486 		str = bin_locus_ma_tests[i].arg1;
   8487 		ma1 = isl_multi_aff_read_from_str(ctx, str);
   8488 		str = bin_locus_ma_tests[i].arg2;
   8489 		ma2 = isl_multi_aff_read_from_str(ctx, str);
   8490 		res = isl_set_read_from_str(ctx, bin_locus_ma_tests[i].res);
   8491 		set = bin_locus_ma_tests[i].fn(ma1, ma2);
   8492 		ok = isl_set_is_equal(set, res);
   8493 		isl_set_free(set);
   8494 		isl_set_free(res);
   8495 		if (ok < 0)
   8496 			return isl_stat_error;
   8497 		if (!ok)
   8498 			isl_die(ctx, isl_error_unknown,
   8499 				"unexpected result", return isl_stat_error);
   8500 	}
   8501 
   8502 	return isl_stat_ok;
   8503 }
   8504 
   8505 /* Perform basic locus tests.
   8506  */
   8507 static int test_locus(isl_ctx *ctx)
   8508 {
   8509 	if (test_un_locus(ctx) < 0)
   8510 		return -1;
   8511 	if (test_bin_locus(ctx) < 0)
   8512 		return -1;
   8513 	if (test_bin_locus_ma(ctx) < 0)
   8514 		return -1;
   8515 	return 0;
   8516 }
   8517 
   8518 /* Test that isl_union_pw_qpolynomial_eval picks up the function
   8519  * defined over the correct domain space.
   8520  */
   8521 static int test_eval_1(isl_ctx *ctx)
   8522 {
   8523 	const char *str;
   8524 	isl_point *pnt;
   8525 	isl_set *set;
   8526 	isl_union_pw_qpolynomial *upwqp;
   8527 	isl_val *v;
   8528 	int cmp;
   8529 
   8530 	str = "{ A[x] -> x^2; B[x] -> -x^2 }";
   8531 	upwqp = isl_union_pw_qpolynomial_read_from_str(ctx, str);
   8532 	str = "{ A[6] }";
   8533 	set = isl_set_read_from_str(ctx, str);
   8534 	pnt = isl_set_sample_point(set);
   8535 	v = isl_union_pw_qpolynomial_eval(upwqp, pnt);
   8536 	cmp = isl_val_cmp_si(v, 36);
   8537 	isl_val_free(v);
   8538 
   8539 	if (!v)
   8540 		return -1;
   8541 	if (cmp != 0)
   8542 		isl_die(ctx, isl_error_unknown, "unexpected value", return -1);
   8543 
   8544 	return 0;
   8545 }
   8546 
   8547 /* Check that isl_qpolynomial_eval handles getting called on a void point.
   8548  */
   8549 static int test_eval_2(isl_ctx *ctx)
   8550 {
   8551 	const char *str;
   8552 	isl_point *pnt;
   8553 	isl_set *set;
   8554 	isl_qpolynomial *qp;
   8555 	isl_val *v;
   8556 	isl_bool ok;
   8557 
   8558 	str = "{ A[x] -> [x] }";
   8559 	qp = isl_qpolynomial_from_aff(isl_aff_read_from_str(ctx, str));
   8560 	str = "{ A[x] : false }";
   8561 	set = isl_set_read_from_str(ctx, str);
   8562 	pnt = isl_set_sample_point(set);
   8563 	v = isl_qpolynomial_eval(qp, pnt);
   8564 	ok = isl_val_is_nan(v);
   8565 	isl_val_free(v);
   8566 
   8567 	if (ok < 0)
   8568 		return -1;
   8569 	if (!ok)
   8570 		isl_die(ctx, isl_error_unknown, "expecting NaN", return -1);
   8571 
   8572 	return 0;
   8573 }
   8574 
   8575 /* Check that a polynomial (without local variables) can be evaluated
   8576  * in a rational point.
   8577  */
   8578 static isl_stat test_eval_3(isl_ctx *ctx)
   8579 {
   8580 	isl_pw_qpolynomial *pwqp;
   8581 	isl_point *pnt;
   8582 	isl_val *v;
   8583 	isl_stat r;
   8584 
   8585 	pwqp = isl_pw_qpolynomial_read_from_str(ctx, "{ [x] -> x^2 }");
   8586 	pnt = isl_point_zero(isl_pw_qpolynomial_get_domain_space(pwqp));
   8587 	v = isl_val_read_from_str(ctx, "1/2");
   8588 	pnt = isl_point_set_coordinate_val(pnt, isl_dim_set, 0, v);
   8589 	v = isl_pw_qpolynomial_eval(pwqp, pnt);
   8590 	r = val_check_equal(v, "1/4");
   8591 	isl_val_free(v);
   8592 
   8593 	return r;
   8594 }
   8595 
   8596 /* Inputs for isl_pw_aff_eval test.
   8597  * "f" is the affine function.
   8598  * "p" is the point where the function should be evaluated.
   8599  * "res" is the expected result.
   8600  */
   8601 struct {
   8602 	const char *f;
   8603 	const char *p;
   8604 	const char *res;
   8605 } aff_eval_tests[] = {
   8606 	{ "{ [i] -> [2 * i] }", "{ [4] }", "8" },
   8607 	{ "{ [i] -> [2 * i] }", "{ [x] : false }", "NaN" },
   8608 	{ "{ [i] -> [i + floor(i/2) + floor(i/3)] }", "{ [0] }", "0" },
   8609 	{ "{ [i] -> [i + floor(i/2) + floor(i/3)] }", "{ [1] }", "1" },
   8610 	{ "{ [i] -> [i + floor(i/2) + floor(i/3)] }", "{ [2] }", "3" },
   8611 	{ "{ [i] -> [i + floor(i/2) + floor(i/3)] }", "{ [3] }", "5" },
   8612 	{ "{ [i] -> [i + floor(i/2) + floor(i/3)] }", "{ [4] }", "7" },
   8613 	{ "{ [i] -> [floor((3 * floor(i/2))/5)] }", "{ [0] }", "0" },
   8614 	{ "{ [i] -> [floor((3 * floor(i/2))/5)] }", "{ [1] }", "0" },
   8615 	{ "{ [i] -> [floor((3 * floor(i/2))/5)] }", "{ [2] }", "0" },
   8616 	{ "{ [i] -> [floor((3 * floor(i/2))/5)] }", "{ [3] }", "0" },
   8617 	{ "{ [i] -> [floor((3 * floor(i/2))/5)] }", "{ [4] }", "1" },
   8618 	{ "{ [i] -> [floor((3 * floor(i/2))/5)] }", "{ [6] }", "1" },
   8619 	{ "{ [i] -> [floor((3 * floor(i/2))/5)] }", "{ [8] }", "2" },
   8620 	{ "{ [i] -> [i] : i > 0; [i] -> [-i] : i < 0 }", "{ [4] }", "4" },
   8621 	{ "{ [i] -> [i] : i > 0; [i] -> [-i] : i < 0 }", "{ [-2] }", "2" },
   8622 	{ "{ [i] -> [i] : i > 0; [i] -> [-i] : i < 0 }", "{ [0] }", "NaN" },
   8623 	{ "[N] -> { [2 * N] }", "[N] -> { : N = 4 }", "8" },
   8624 	{ "{ [i, j] -> [(i + j)/2] }", "{ [1, 1] }", "1" },
   8625 	{ "{ [i, j] -> [(i + j)/2] }", "{ [1, 2] }", "3/2" },
   8626 	{ "{ [i] -> [i] : i mod 2 = 0 }", "{ [4] }", "4" },
   8627 	{ "{ [i] -> [i] : i mod 2 = 0 }", "{ [3] }", "NaN" },
   8628 	{ "{ [i] -> [i] : i mod 2 = 0 }", "{ [x] : false }", "NaN" },
   8629 	{ "[m, n] -> { [2m + 3n] }", "[n=1, m=10] -> { : }", "23" },
   8630 };
   8631 
   8632 /* Perform basic isl_pw_aff_eval tests.
   8633  */
   8634 static int test_eval_aff(isl_ctx *ctx)
   8635 {
   8636 	int i;
   8637 
   8638 	for (i = 0; i < ARRAY_SIZE(aff_eval_tests); ++i) {
   8639 		isl_stat r;
   8640 		isl_pw_aff *pa;
   8641 		isl_set *set;
   8642 		isl_point *pnt;
   8643 		isl_val *v;
   8644 
   8645 		pa = isl_pw_aff_read_from_str(ctx, aff_eval_tests[i].f);
   8646 		set = isl_set_read_from_str(ctx, aff_eval_tests[i].p);
   8647 		pnt = isl_set_sample_point(set);
   8648 		v = isl_pw_aff_eval(pa, pnt);
   8649 		r = val_check_equal(v, aff_eval_tests[i].res);
   8650 		isl_val_free(v);
   8651 		if (r < 0)
   8652 			return -1;
   8653 	}
   8654 	return 0;
   8655 }
   8656 
   8657 /* Perform basic evaluation tests.
   8658  */
   8659 static int test_eval(isl_ctx *ctx)
   8660 {
   8661 	if (test_eval_1(ctx) < 0)
   8662 		return -1;
   8663 	if (test_eval_2(ctx) < 0)
   8664 		return -1;
   8665 	if (test_eval_3(ctx) < 0)
   8666 		return -1;
   8667 	if (test_eval_aff(ctx) < 0)
   8668 		return -1;
   8669 	return 0;
   8670 }
   8671 
   8672 /* Descriptions of sets that are tested for reparsing after printing.
   8673  */
   8674 const char *output_tests[] = {
   8675 	"{ [1, y] : 0 <= y <= 1; [x, -x] : 0 <= x <= 1 }",
   8676 	"{ [x] : 1 = 0 }",
   8677 	"{ [x] : false }",
   8678 	"{ [x] : x mod 2 = 0 }",
   8679 	"{ [x] : x mod 2 = 1 }",
   8680 	"{ [x, y] : x mod 2 = 0 and 3*floor(y/2) < x }",
   8681 	"{ [y, x] : x mod 2 = 0 and 3*floor(y/2) < x }",
   8682 	"{ [x, y] : x mod 2 = 0 and 3*floor(y/2) = x + y }",
   8683 	"{ [y, x] : x mod 2 = 0 and 3*floor(y/2) = x + y }",
   8684 	"[n] -> { [y, x] : 2*((x + 2y) mod 3) = n }",
   8685 	"{ [x, y] : (2*floor(x/3) + 3*floor(y/4)) mod 5 = x }",
   8686 };
   8687 
   8688 /* Check that printing a set and reparsing a set from the printed output
   8689  * results in the same set.
   8690  */
   8691 static int test_output_set(isl_ctx *ctx)
   8692 {
   8693 	int i;
   8694 	char *str;
   8695 	isl_set *set1, *set2;
   8696 	isl_bool equal;
   8697 
   8698 	for (i = 0; i < ARRAY_SIZE(output_tests); ++i) {
   8699 		set1 = isl_set_read_from_str(ctx, output_tests[i]);
   8700 		str = isl_set_to_str(set1);
   8701 		set2 = isl_set_read_from_str(ctx, str);
   8702 		free(str);
   8703 		equal = isl_set_is_equal(set1, set2);
   8704 		isl_set_free(set1);
   8705 		isl_set_free(set2);
   8706 		if (equal < 0)
   8707 			return -1;
   8708 		if (!equal)
   8709 			isl_die(ctx, isl_error_unknown,
   8710 				"parsed output not the same", return -1);
   8711 	}
   8712 
   8713 	return 0;
   8714 }
   8715 
   8716 /* Check that an isl_multi_aff is printed using a consistent space.
   8717  */
   8718 static isl_stat test_output_ma(isl_ctx *ctx)
   8719 {
   8720 	char *str;
   8721 	isl_bool equal;
   8722 	isl_aff *aff;
   8723 	isl_multi_aff *ma, *ma2;
   8724 
   8725 	ma = isl_multi_aff_read_from_str(ctx, "{ [a, b] -> [a + b] }");
   8726 	aff = isl_aff_read_from_str(ctx, "{ [c, d] -> [c + d] }");
   8727 	ma = isl_multi_aff_set_aff(ma, 0, aff);
   8728 	str = isl_multi_aff_to_str(ma);
   8729 	ma2 = isl_multi_aff_read_from_str(ctx, str);
   8730 	free(str);
   8731 	equal = isl_multi_aff_plain_is_equal(ma, ma2);
   8732 	isl_multi_aff_free(ma2);
   8733 	isl_multi_aff_free(ma);
   8734 
   8735 	if (equal < 0)
   8736 		return isl_stat_error;
   8737 	if (!equal)
   8738 		isl_die(ctx, isl_error_unknown, "bad conversion",
   8739 			return isl_stat_error);
   8740 
   8741 	return isl_stat_ok;
   8742 }
   8743 
   8744 /* Check that an isl_multi_pw_aff is printed using a consistent space.
   8745  */
   8746 static isl_stat test_output_mpa(isl_ctx *ctx)
   8747 {
   8748 	char *str;
   8749 	isl_bool equal;
   8750 	isl_pw_aff *pa;
   8751 	isl_multi_pw_aff *mpa, *mpa2;
   8752 
   8753 	mpa = isl_multi_pw_aff_read_from_str(ctx, "{ [a, b] -> [a + b] }");
   8754 	pa = isl_pw_aff_read_from_str(ctx, "{ [c, d] -> [c + d] }");
   8755 	mpa = isl_multi_pw_aff_set_pw_aff(mpa, 0, pa);
   8756 	str = isl_multi_pw_aff_to_str(mpa);
   8757 	mpa2 = isl_multi_pw_aff_read_from_str(ctx, str);
   8758 	free(str);
   8759 	equal = isl_multi_pw_aff_plain_is_equal(mpa, mpa2);
   8760 	isl_multi_pw_aff_free(mpa2);
   8761 	isl_multi_pw_aff_free(mpa);
   8762 
   8763 	if (equal < 0)
   8764 		return isl_stat_error;
   8765 	if (!equal)
   8766 		isl_die(ctx, isl_error_unknown, "bad conversion",
   8767 			return isl_stat_error);
   8768 
   8769 	return isl_stat_ok;
   8770 }
   8771 
   8772 int test_output(isl_ctx *ctx)
   8773 {
   8774 	char *s;
   8775 	const char *str;
   8776 	isl_pw_aff *pa;
   8777 	isl_printer *p;
   8778 	int equal;
   8779 
   8780 	if (test_output_set(ctx) < 0)
   8781 		return -1;
   8782 	if (test_output_ma(ctx) < 0)
   8783 		return -1;
   8784 	if (test_output_mpa(ctx) < 0)
   8785 		return -1;
   8786 
   8787 	str = "[x] -> { [1] : x % 4 <= 2; [2] : x = 3 }";
   8788 	pa = isl_pw_aff_read_from_str(ctx, str);
   8789 
   8790 	p = isl_printer_to_str(ctx);
   8791 	p = isl_printer_set_output_format(p, ISL_FORMAT_C);
   8792 	p = isl_printer_print_pw_aff(p, pa);
   8793 	s = isl_printer_get_str(p);
   8794 	isl_printer_free(p);
   8795 	isl_pw_aff_free(pa);
   8796 	if (!s)
   8797 		equal = -1;
   8798 	else
   8799 		equal = !strcmp(s, "4 * floord(x, 4) + 2 >= x ? 1 : 2");
   8800 	free(s);
   8801 	if (equal < 0)
   8802 		return -1;
   8803 	if (!equal)
   8804 		isl_die(ctx, isl_error_unknown, "unexpected result", return -1);
   8805 
   8806 	return 0;
   8807 }
   8808 
   8809 int test_sample(isl_ctx *ctx)
   8810 {
   8811 	const char *str;
   8812 	isl_basic_set *bset1, *bset2;
   8813 	int empty, subset;
   8814 
   8815 	str = "{ [a, b, c, d, e, f, g, h, i, j, k] : "
   8816 	    "3i >= 1073741823b - c - 1073741823e + f and c >= 0 and "
   8817 	    "3i >= -1 + 3221225466b + c + d - 3221225466e - f and "
   8818 	    "2e >= a - b and 3e <= 2a and 3k <= -a and f <= -1 + a and "
   8819 	    "3i <= 4 - a + 4b + 2c - e - 2f and 3k <= -a + c - f and "
   8820 	    "3h >= -2 + a and 3g >= -3 - a and 3k >= -2 - a and "
   8821 	    "3i >= -2 - a - 2c + 3e + 2f and 3h <= a + c - f and "
   8822 	    "3h >= a + 2147483646b + 2c - 2147483646e - 2f and "
   8823 	    "3g <= -1 - a and 3i <= 1 + c + d - f and a <= 1073741823 and "
   8824 	    "f >= 1 - a + 1073741822b + c + d - 1073741822e and "
   8825 	    "3i >= 1 + 2b - 2c + e + 2f + 3g and "
   8826 	    "1073741822f <= 1073741822 - a + 1073741821b + 1073741822c +"
   8827 		"d - 1073741821e and "
   8828 	    "3j <= 3 - a + 3b and 3g <= -2 - 2b + c + d - e - f and "
   8829 	    "3j >= 1 - a + b + 2e and "
   8830 	    "3f >= -3 + a + 3221225462b + 3c + d - 3221225465e and "
   8831 	    "3i <= 4 - a + 4b - e and "
   8832 	    "f <= 1073741822 + 1073741822b - 1073741822e and 3h <= a and "
   8833 	    "f >= 0 and 2e <= 4 - a + 5b - d and 2e <= a - b + d and "
   8834 	    "c <= -1 + a and 3i >= -2 - a + 3e and "
   8835 	    "1073741822e <= 1073741823 - a + 1073741822b + c and "
   8836 	    "3g >= -4 + 3221225464b + 3c + d - 3221225467e - 3f and "
   8837 	    "3i >= -1 + 3221225466b + 3c + d - 3221225466e - 3f and "
   8838 	    "1073741823e >= 1 + 1073741823b - d and "
   8839 	    "3i >= 1073741823b + c - 1073741823e - f and "
   8840 	    "3i >= 1 + 2b + e + 3g }";
   8841 	bset1 = isl_basic_set_read_from_str(ctx, str);
   8842 	bset2 = isl_basic_set_sample(isl_basic_set_copy(bset1));
   8843 	empty = isl_basic_set_is_empty(bset2);
   8844 	subset = isl_basic_set_is_subset(bset2, bset1);
   8845 	isl_basic_set_free(bset1);
   8846 	isl_basic_set_free(bset2);
   8847 	if (empty < 0 || subset < 0)
   8848 		return -1;
   8849 	if (empty)
   8850 		isl_die(ctx, isl_error_unknown, "point not found", return -1);
   8851 	if (!subset)
   8852 		isl_die(ctx, isl_error_unknown, "bad point found", return -1);
   8853 
   8854 	return 0;
   8855 }
   8856 
   8857 /* Perform a projection on a basic set that is known to be empty
   8858  * but that has not been assigned a canonical representation.
   8859  * Earlier versions of isl would run into a stack overflow
   8860  * on this example.
   8861  */
   8862 static int test_empty_projection(isl_ctx *ctx)
   8863 {
   8864 	const char *str;
   8865 	isl_bool empty;
   8866 	isl_basic_set *bset;
   8867 
   8868 	str = "{ [a, b, c, d, e, f, g, h] : 5f = 1 + 4a - b + 5c - d - 2e and "
   8869 		"3h = 2 + b + c and 14c >= 9 - 3a + 25b and "
   8870 		"4c <= 50 - 3a + 23b and 6b <= -39 + a and "
   8871 		"9g >= -6 + 3a + b + c and e < a + b - 2d and "
   8872 		"7d >= -5 + 2a + 2b and 5g >= -14 + a - 4b + d + 2e and "
   8873 		"9g <= -28 - 5b - 2c + 3d + 6e }";
   8874 	bset = isl_basic_set_read_from_str(ctx, str);
   8875 	empty = isl_basic_set_is_empty(bset);
   8876 	bset = isl_basic_set_params(bset);
   8877 	isl_basic_set_free(bset);
   8878 
   8879 	if (empty < 0)
   8880 		return -1;
   8881 
   8882 	return 0;
   8883 }
   8884 
   8885 int test_slice(isl_ctx *ctx)
   8886 {
   8887 	const char *str;
   8888 	isl_map *map;
   8889 	int equal;
   8890 
   8891 	str = "{ [i] -> [j] }";
   8892 	map = isl_map_read_from_str(ctx, str);
   8893 	map = isl_map_equate(map, isl_dim_in, 0, isl_dim_out, 0);
   8894 	equal = map_check_equal(map, "{ [i] -> [i] }");
   8895 	isl_map_free(map);
   8896 	if (equal < 0)
   8897 		return -1;
   8898 
   8899 	str = "{ [i] -> [j] }";
   8900 	map = isl_map_read_from_str(ctx, str);
   8901 	map = isl_map_equate(map, isl_dim_in, 0, isl_dim_in, 0);
   8902 	equal = map_check_equal(map, "{ [i] -> [j] }");
   8903 	isl_map_free(map);
   8904 	if (equal < 0)
   8905 		return -1;
   8906 
   8907 	str = "{ [i] -> [j] }";
   8908 	map = isl_map_read_from_str(ctx, str);
   8909 	map = isl_map_oppose(map, isl_dim_in, 0, isl_dim_out, 0);
   8910 	equal = map_check_equal(map, "{ [i] -> [-i] }");
   8911 	isl_map_free(map);
   8912 	if (equal < 0)
   8913 		return -1;
   8914 
   8915 	str = "{ [i] -> [j] }";
   8916 	map = isl_map_read_from_str(ctx, str);
   8917 	map = isl_map_oppose(map, isl_dim_in, 0, isl_dim_in, 0);
   8918 	equal = map_check_equal(map, "{ [0] -> [j] }");
   8919 	isl_map_free(map);
   8920 	if (equal < 0)
   8921 		return -1;
   8922 
   8923 	str = "{ [i] -> [j] }";
   8924 	map = isl_map_read_from_str(ctx, str);
   8925 	map = isl_map_order_gt(map, isl_dim_in, 0, isl_dim_out, 0);
   8926 	equal = map_check_equal(map, "{ [i] -> [j] : i > j }");
   8927 	isl_map_free(map);
   8928 	if (equal < 0)
   8929 		return -1;
   8930 
   8931 	str = "{ [i] -> [j] }";
   8932 	map = isl_map_read_from_str(ctx, str);
   8933 	map = isl_map_order_gt(map, isl_dim_in, 0, isl_dim_in, 0);
   8934 	equal = map_check_equal(map, "{ [i] -> [j] : false }");
   8935 	isl_map_free(map);
   8936 	if (equal < 0)
   8937 		return -1;
   8938 
   8939 	return 0;
   8940 }
   8941 
   8942 int test_eliminate(isl_ctx *ctx)
   8943 {
   8944 	const char *str;
   8945 	isl_map *map;
   8946 	int equal;
   8947 
   8948 	str = "{ [i] -> [j] : i = 2j }";
   8949 	map = isl_map_read_from_str(ctx, str);
   8950 	map = isl_map_eliminate(map, isl_dim_out, 0, 1);
   8951 	equal = map_check_equal(map, "{ [i] -> [j] : exists a : i = 2a }");
   8952 	isl_map_free(map);
   8953 	if (equal < 0)
   8954 		return -1;
   8955 
   8956 	return 0;
   8957 }
   8958 
   8959 /* Check basic functionality of isl_map_deltas_map.
   8960  */
   8961 static int test_deltas_map(isl_ctx *ctx)
   8962 {
   8963 	const char *str;
   8964 	isl_map *map;
   8965 	int equal;
   8966 
   8967 	str = "{ A[i] -> A[i + 1] }";
   8968 	map = isl_map_read_from_str(ctx, str);
   8969 	map = isl_map_deltas_map(map);
   8970 	equal = map_check_equal(map, "{ [A[i] -> A[i + 1]] -> A[1] }");
   8971 	isl_map_free(map);
   8972 	if (equal < 0)
   8973 		return -1;
   8974 
   8975 	return 0;
   8976 }
   8977 
   8978 /* Check that isl_set_dim_residue_class detects that the values of j
   8979  * in the set below are all odd and that it does not detect any spurious
   8980  * strides.
   8981  */
   8982 static int test_residue_class(isl_ctx *ctx)
   8983 {
   8984 	const char *str;
   8985 	isl_set *set;
   8986 	isl_int m, r;
   8987 	isl_stat res;
   8988 
   8989 	str = "{ [i,j] : j = 4 i + 1 and 0 <= i <= 100; "
   8990 		"[i,j] : j = 4 i + 3 and 500 <= i <= 600 }";
   8991 	set = isl_set_read_from_str(ctx, str);
   8992 	isl_int_init(m);
   8993 	isl_int_init(r);
   8994 	res = isl_set_dim_residue_class(set, 1, &m, &r);
   8995 	if (res >= 0 &&
   8996 	    (isl_int_cmp_si(m, 2) != 0 || isl_int_cmp_si(r, 1) != 0))
   8997 		isl_die(ctx, isl_error_unknown, "incorrect residue class",
   8998 			res = isl_stat_error);
   8999 	isl_int_clear(r);
   9000 	isl_int_clear(m);
   9001 	isl_set_free(set);
   9002 
   9003 	return res;
   9004 }
   9005 
   9006 static int test_align_parameters_1(isl_ctx *ctx)
   9007 {
   9008 	const char *str;
   9009 	isl_space *space;
   9010 	isl_multi_aff *ma1, *ma2;
   9011 	int equal;
   9012 
   9013 	str = "{ A[B[] -> C[]] -> D[E[] -> F[]] }";
   9014 	ma1 = isl_multi_aff_read_from_str(ctx, str);
   9015 
   9016 	space = isl_space_params_alloc(ctx, 1);
   9017 	space = isl_space_set_dim_name(space, isl_dim_param, 0, "N");
   9018 	ma1 = isl_multi_aff_align_params(ma1, space);
   9019 
   9020 	str = "[N] -> { A[B[] -> C[]] -> D[E[] -> F[]] }";
   9021 	ma2 = isl_multi_aff_read_from_str(ctx, str);
   9022 
   9023 	equal = isl_multi_aff_plain_is_equal(ma1, ma2);
   9024 
   9025 	isl_multi_aff_free(ma1);
   9026 	isl_multi_aff_free(ma2);
   9027 
   9028 	if (equal < 0)
   9029 		return -1;
   9030 	if (!equal)
   9031 		isl_die(ctx, isl_error_unknown,
   9032 			"result not as expected", return -1);
   9033 
   9034 	return 0;
   9035 }
   9036 
   9037 /* Check the isl_multi_*_from_*_list operation in case inputs
   9038  * have unaligned parameters.
   9039  * In particular, older versions of isl would simply fail
   9040  * (without printing any error message).
   9041  */
   9042 static isl_stat test_align_parameters_2(isl_ctx *ctx)
   9043 {
   9044 	isl_space *space;
   9045 	isl_map *map;
   9046 	isl_aff *aff;
   9047 	isl_multi_aff *ma;
   9048 
   9049 	map = isl_map_read_from_str(ctx, "{ A[] -> M[x] }");
   9050 	space = isl_map_get_space(map);
   9051 	isl_map_free(map);
   9052 
   9053 	aff = isl_aff_read_from_str(ctx, "[N] -> { A[] -> [N] }");
   9054 	ma = isl_multi_aff_from_aff_list(space, isl_aff_list_from_aff(aff));
   9055 	isl_multi_aff_free(ma);
   9056 
   9057 	if (!ma)
   9058 		return isl_stat_error;
   9059 	return isl_stat_ok;
   9060 }
   9061 
   9062 /* Perform basic parameter alignment tests.
   9063  */
   9064 static int test_align_parameters(isl_ctx *ctx)
   9065 {
   9066 	if (test_align_parameters_1(ctx) < 0)
   9067 		return -1;
   9068 	if (test_align_parameters_2(ctx) < 0)
   9069 		return -1;
   9070 
   9071 	return 0;
   9072 }
   9073 
   9074 /* Check that isl_*_drop_unused_params actually drops the unused parameters
   9075  * by comparing the result using isl_*_plain_is_equal.
   9076  * Note that this assumes that isl_*_plain_is_equal does not consider
   9077  * objects that only differ by unused parameters to be equal.
   9078  */
   9079 int test_drop_unused_parameters(isl_ctx *ctx)
   9080 {
   9081 	const char *str_with, *str_without;
   9082 	isl_basic_set *bset1, *bset2;
   9083 	isl_set *set1, *set2;
   9084 	isl_pw_aff *pwa1, *pwa2;
   9085 	int equal;
   9086 
   9087 	str_with = "[n, m, o] -> { [m] }";
   9088 	str_without = "[m] -> { [m] }";
   9089 
   9090 	bset1 = isl_basic_set_read_from_str(ctx, str_with);
   9091 	bset2 = isl_basic_set_read_from_str(ctx, str_without);
   9092 	bset1 = isl_basic_set_drop_unused_params(bset1);
   9093 	equal = isl_basic_set_plain_is_equal(bset1, bset2);
   9094 	isl_basic_set_free(bset1);
   9095 	isl_basic_set_free(bset2);
   9096 
   9097 	if (equal < 0)
   9098 		return -1;
   9099 	if (!equal)
   9100 		isl_die(ctx, isl_error_unknown,
   9101 			"result not as expected", return -1);
   9102 
   9103 	set1 = isl_set_read_from_str(ctx, str_with);
   9104 	set2 = isl_set_read_from_str(ctx, str_without);
   9105 	set1 = isl_set_drop_unused_params(set1);
   9106 	equal = isl_set_plain_is_equal(set1, set2);
   9107 	isl_set_free(set1);
   9108 	isl_set_free(set2);
   9109 
   9110 	if (equal < 0)
   9111 		return -1;
   9112 	if (!equal)
   9113 		isl_die(ctx, isl_error_unknown,
   9114 			"result not as expected", return -1);
   9115 
   9116 	pwa1 = isl_pw_aff_read_from_str(ctx, str_with);
   9117 	pwa2 = isl_pw_aff_read_from_str(ctx, str_without);
   9118 	pwa1 = isl_pw_aff_drop_unused_params(pwa1);
   9119 	equal = isl_pw_aff_plain_is_equal(pwa1, pwa2);
   9120 	isl_pw_aff_free(pwa1);
   9121 	isl_pw_aff_free(pwa2);
   9122 
   9123 	if (equal < 0)
   9124 		return -1;
   9125 	if (!equal)
   9126 		isl_die(ctx, isl_error_unknown,
   9127 			"result not as expected", return -1);
   9128 
   9129 	return 0;
   9130 }
   9131 
   9132 static int test_list(isl_ctx *ctx)
   9133 {
   9134 	isl_id *a, *b, *c, *d, *id;
   9135 	isl_id_list *list;
   9136 	isl_size n;
   9137 	int ok;
   9138 
   9139 	a = isl_id_alloc(ctx, "a", NULL);
   9140 	b = isl_id_alloc(ctx, "b", NULL);
   9141 	c = isl_id_alloc(ctx, "c", NULL);
   9142 	d = isl_id_alloc(ctx, "d", NULL);
   9143 
   9144 	list = isl_id_list_alloc(ctx, 4);
   9145 	list = isl_id_list_add(list, b);
   9146 	list = isl_id_list_insert(list, 0, a);
   9147 	list = isl_id_list_add(list, c);
   9148 	list = isl_id_list_add(list, d);
   9149 	list = isl_id_list_drop(list, 1, 1);
   9150 
   9151 	n = isl_id_list_n_id(list);
   9152 	if (n < 0)
   9153 		return -1;
   9154 	if (n != 3) {
   9155 		isl_id_list_free(list);
   9156 		isl_die(ctx, isl_error_unknown,
   9157 			"unexpected number of elements in list", return -1);
   9158 	}
   9159 
   9160 	id = isl_id_list_get_id(list, 0);
   9161 	ok = id == a;
   9162 	isl_id_free(id);
   9163 	id = isl_id_list_get_id(list, 1);
   9164 	ok = ok && id == c;
   9165 	isl_id_free(id);
   9166 	id = isl_id_list_get_id(list, 2);
   9167 	ok = ok && id == d;
   9168 	isl_id_free(id);
   9169 
   9170 	isl_id_list_free(list);
   9171 
   9172 	if (!ok)
   9173 		isl_die(ctx, isl_error_unknown,
   9174 			"unexpected elements in list", return -1);
   9175 
   9176 	return 0;
   9177 }
   9178 
   9179 /* Check the conversion from an isl_multi_aff to an isl_basic_set.
   9180  */
   9181 static isl_stat test_ma_conversion(isl_ctx *ctx)
   9182 {
   9183 	const char *str;
   9184 	isl_bool equal;
   9185 	isl_multi_aff *ma;
   9186 	isl_basic_set *bset1, *bset2;
   9187 
   9188 	str = "[N] -> { A[0, N + 1] }";
   9189 	ma = isl_multi_aff_read_from_str(ctx, str);
   9190 	bset1 = isl_basic_set_read_from_str(ctx, str);
   9191 	bset2 = isl_basic_set_from_multi_aff(ma);
   9192 	equal = isl_basic_set_is_equal(bset1, bset2);
   9193 	isl_basic_set_free(bset1);
   9194 	isl_basic_set_free(bset2);
   9195 	if (equal < 0)
   9196 		return isl_stat_error;
   9197 	if (!equal)
   9198 		isl_die(ctx, isl_error_unknown, "bad conversion",
   9199 			return isl_stat_error);
   9200 	return isl_stat_ok;
   9201 }
   9202 
   9203 const char *set_conversion_tests[] = {
   9204 	"[N] -> { [i] : N - 1 <= 2 i <= N }",
   9205 	"[N] -> { [i] : exists a : i = 4 a and N - 1 <= i <= N }",
   9206 	"[N] -> { [i,j] : exists a : i = 4 a and N - 1 <= i, 2j <= N }",
   9207 	"[N] -> { [[i]->[j]] : exists a : i = 4 a and N - 1 <= i, 2j <= N }",
   9208 	"[N] -> { [3*floor(N/2) + 5*floor(N/3)] }",
   9209 	"[a, b] -> { [c, d] : (4*floor((-a + c)/4) = -a + c and "
   9210 			"32*floor((-b + d)/32) = -b + d and 5 <= c <= 8 and "
   9211 			"-3 + c <= d <= 28 + c) }",
   9212 };
   9213 
   9214 /* Check that converting from isl_set to isl_pw_multi_aff and back
   9215  * to isl_set produces the original isl_set.
   9216  */
   9217 static int test_set_conversion(isl_ctx *ctx)
   9218 {
   9219 	int i;
   9220 	const char *str;
   9221 	isl_set *set1, *set2;
   9222 	isl_pw_multi_aff *pma;
   9223 	int equal;
   9224 
   9225 	for (i = 0; i < ARRAY_SIZE(set_conversion_tests); ++i) {
   9226 		str = set_conversion_tests[i];
   9227 		set1 = isl_set_read_from_str(ctx, str);
   9228 		pma = isl_pw_multi_aff_from_set(isl_set_copy(set1));
   9229 		set2 = isl_set_from_pw_multi_aff(pma);
   9230 		equal = isl_set_is_equal(set1, set2);
   9231 		isl_set_free(set1);
   9232 		isl_set_free(set2);
   9233 
   9234 		if (equal < 0)
   9235 			return -1;
   9236 		if (!equal)
   9237 			isl_die(ctx, isl_error_unknown, "bad conversion",
   9238 				return -1);
   9239 	}
   9240 
   9241 	return 0;
   9242 }
   9243 
   9244 const char *conversion_tests[] = {
   9245 	"{ [a, b, c, d] -> s0[a, b, e, f] : "
   9246 	    "exists (e0 = [(a - 2c)/3], e1 = [(-4 + b - 5d)/9], "
   9247 	    "e2 = [(-d + f)/9]: 3e0 = a - 2c and 9e1 = -4 + b - 5d and "
   9248 	    "9e2 = -d + f and f >= 0 and f <= 8 and 9e >= -5 - 2a and "
   9249 	    "9e <= -2 - 2a) }",
   9250 	"{ [a, b] -> [c] : exists (e0 = floor((-a - b + c)/5): "
   9251 	    "5e0 = -a - b + c and c >= -a and c <= 4 - a) }",
   9252 	"{ [a, b] -> [c] : exists d : 18 * d = -3 - a + 2c and 1 <= c <= 3 }",
   9253 };
   9254 
   9255 /* Check that converting from isl_map to isl_pw_multi_aff and back
   9256  * to isl_map produces the original isl_map.
   9257  */
   9258 static int test_map_conversion(isl_ctx *ctx)
   9259 {
   9260 	int i;
   9261 	isl_map *map1, *map2;
   9262 	isl_pw_multi_aff *pma;
   9263 	int equal;
   9264 
   9265 	for (i = 0; i < ARRAY_SIZE(conversion_tests); ++i) {
   9266 		map1 = isl_map_read_from_str(ctx, conversion_tests[i]);
   9267 		pma = isl_pw_multi_aff_from_map(isl_map_copy(map1));
   9268 		map2 = isl_map_from_pw_multi_aff(pma);
   9269 		equal = isl_map_is_equal(map1, map2);
   9270 		isl_map_free(map1);
   9271 		isl_map_free(map2);
   9272 
   9273 		if (equal < 0)
   9274 			return -1;
   9275 		if (!equal)
   9276 			isl_die(ctx, isl_error_unknown, "bad conversion",
   9277 				return -1);
   9278 	}
   9279 
   9280 	return 0;
   9281 }
   9282 
   9283 /* Descriptions of isl_pw_multi_aff objects for testing conversion
   9284  * to isl_multi_pw_aff and back.
   9285  */
   9286 const char *mpa_conversion_tests[] = {
   9287 	"{ [x] -> A[x] }",
   9288 	"{ [x] -> A[x] : x >= 0 }",
   9289 	"{ [x] -> A[x] : x >= 0; [x] -> A[-x] : x < 0 }",
   9290 	"{ [x] -> A[x, x + 1] }",
   9291 	"{ [x] -> A[] }",
   9292 	"{ [x] -> A[] : x >= 0 }",
   9293 };
   9294 
   9295 /* Check that conversion from isl_pw_multi_aff to isl_multi_pw_aff and
   9296  * back to isl_pw_multi_aff preserves the original meaning.
   9297  */
   9298 static int test_mpa_conversion(isl_ctx *ctx)
   9299 {
   9300 	int i;
   9301 	isl_pw_multi_aff *pma1, *pma2;
   9302 	isl_multi_pw_aff *mpa;
   9303 	int equal;
   9304 
   9305 	for (i = 0; i < ARRAY_SIZE(mpa_conversion_tests); ++i) {
   9306 		const char *str;
   9307 		str = mpa_conversion_tests[i];
   9308 		pma1 = isl_pw_multi_aff_read_from_str(ctx, str);
   9309 		pma2 = isl_pw_multi_aff_copy(pma1);
   9310 		mpa = isl_multi_pw_aff_from_pw_multi_aff(pma1);
   9311 		pma1 = isl_pw_multi_aff_from_multi_pw_aff(mpa);
   9312 		equal = isl_pw_multi_aff_plain_is_equal(pma1, pma2);
   9313 		isl_pw_multi_aff_free(pma1);
   9314 		isl_pw_multi_aff_free(pma2);
   9315 
   9316 		if (equal < 0)
   9317 			return -1;
   9318 		if (!equal)
   9319 			isl_die(ctx, isl_error_unknown, "bad conversion",
   9320 				return -1);
   9321 	}
   9322 
   9323 	return 0;
   9324 }
   9325 
   9326 /* Descriptions of union maps that should be convertible
   9327  * to an isl_multi_union_pw_aff.
   9328  */
   9329 const char *umap_mupa_conversion_tests[] = {
   9330 	"{ [a, b, c, d] -> s0[a, b, e, f] : "
   9331 	    "exists (e0 = [(a - 2c)/3], e1 = [(-4 + b - 5d)/9], "
   9332 	    "e2 = [(-d + f)/9]: 3e0 = a - 2c and 9e1 = -4 + b - 5d and "
   9333 	    "9e2 = -d + f and f >= 0 and f <= 8 and 9e >= -5 - 2a and "
   9334 	    "9e <= -2 - 2a) }",
   9335 	"{ [a, b] -> [c] : exists (e0 = floor((-a - b + c)/5): "
   9336 	    "5e0 = -a - b + c and c >= -a and c <= 4 - a) }",
   9337 	"{ [a, b] -> [c] : exists d : 18 * d = -3 - a + 2c and 1 <= c <= 3 }",
   9338 	"{ A[] -> B[0]; C[] -> B[1] }",
   9339 	"{ A[] -> B[]; C[] -> B[] }",
   9340 };
   9341 
   9342 /* Check that converting from isl_union_map to isl_multi_union_pw_aff and back
   9343  * to isl_union_map produces the original isl_union_map.
   9344  */
   9345 static int test_union_map_mupa_conversion(isl_ctx *ctx)
   9346 {
   9347 	int i;
   9348 	isl_union_map *umap1, *umap2;
   9349 	isl_multi_union_pw_aff *mupa;
   9350 	int equal;
   9351 
   9352 	for (i = 0; i < ARRAY_SIZE(umap_mupa_conversion_tests); ++i) {
   9353 		const char *str;
   9354 		str = umap_mupa_conversion_tests[i];
   9355 		umap1 = isl_union_map_read_from_str(ctx, str);
   9356 		umap2 = isl_union_map_copy(umap1);
   9357 		mupa = isl_multi_union_pw_aff_from_union_map(umap2);
   9358 		umap2 = isl_union_map_from_multi_union_pw_aff(mupa);
   9359 		equal = isl_union_map_is_equal(umap1, umap2);
   9360 		isl_union_map_free(umap1);
   9361 		isl_union_map_free(umap2);
   9362 
   9363 		if (equal < 0)
   9364 			return -1;
   9365 		if (!equal)
   9366 			isl_die(ctx, isl_error_unknown, "bad conversion",
   9367 				return -1);
   9368 	}
   9369 
   9370 	return 0;
   9371 }
   9372 
   9373 static int test_conversion(isl_ctx *ctx)
   9374 {
   9375 	if (test_ma_conversion(ctx) < 0)
   9376 		return -1;
   9377 	if (test_set_conversion(ctx) < 0)
   9378 		return -1;
   9379 	if (test_map_conversion(ctx) < 0)
   9380 		return -1;
   9381 	if (test_mpa_conversion(ctx) < 0)
   9382 		return -1;
   9383 	if (test_union_map_mupa_conversion(ctx) < 0)
   9384 		return -1;
   9385 	return 0;
   9386 }
   9387 
   9388 /* Check that isl_basic_map_curry does not modify input.
   9389  */
   9390 static int test_curry(isl_ctx *ctx)
   9391 {
   9392 	const char *str;
   9393 	isl_basic_map *bmap1, *bmap2;
   9394 	int equal;
   9395 
   9396 	str = "{ [A[] -> B[]] -> C[] }";
   9397 	bmap1 = isl_basic_map_read_from_str(ctx, str);
   9398 	bmap2 = isl_basic_map_curry(isl_basic_map_copy(bmap1));
   9399 	equal = isl_basic_map_is_equal(bmap1, bmap2);
   9400 	isl_basic_map_free(bmap1);
   9401 	isl_basic_map_free(bmap2);
   9402 
   9403 	if (equal < 0)
   9404 		return -1;
   9405 	if (equal)
   9406 		isl_die(ctx, isl_error_unknown,
   9407 			"curried map should not be equal to original",
   9408 			return -1);
   9409 
   9410 	return 0;
   9411 }
   9412 
   9413 struct {
   9414 	const char *ma1;
   9415 	const char *ma;
   9416 	const char *res;
   9417 } pullback_tests[] = {
   9418 	{ "{ B[i,j] -> C[i + 2j] }" , "{ A[a,b] -> B[b,a] }",
   9419 	  "{ A[a,b] -> C[b + 2a] }" },
   9420 	{ "{ B[i] -> C[2i] }", "{ A[a] -> B[(a)/2] }", "{ A[a] -> C[a] }" },
   9421 	{ "{ B[i] -> C[(i)/2] }", "{ A[a] -> B[2a] }", "{ A[a] -> C[a] }" },
   9422 	{ "{ B[i] -> C[(i)/2] }", "{ A[a] -> B[(a)/3] }",
   9423 	  "{ A[a] -> C[(a)/6] }" },
   9424 	{ "{ B[i] -> C[2i] }", "{ A[a] -> B[5a] }", "{ A[a] -> C[10a] }" },
   9425 	{ "{ B[i] -> C[2i] }", "{ A[a] -> B[(a)/3] }",
   9426 	  "{ A[a] -> C[(2a)/3] }" },
   9427 	{ "{ B[i,j] -> C[i + j] }", "{ A[a] -> B[a,a] }", "{ A[a] -> C[2a] }"},
   9428 	{ "{ B[a] -> C[a,a] }", "{ A[i,j] -> B[i + j] }",
   9429 	  "{ A[i,j] -> C[i + j, i + j] }"},
   9430 	{ "{ B[i] -> C[([i/2])] }", "{ B[5] }", "{ C[2] }" },
   9431 	{ "[n] -> { B[i,j] -> C[([i/2]) + 2j] }",
   9432 	  "[n] -> { B[n,[n/3]] }", "[n] -> { C[([n/2]) + 2*[n/3]] }", },
   9433 	{ "{ [i, j] -> [floor((i)/4) + floor((2*i+j)/5)] }",
   9434 	  "{ [i, j] -> [floor((i)/3), j] }",
   9435 	  "{ [i, j] -> [(floor((i)/12) + floor((j + 2*floor((i)/3))/5))] }" },
   9436 };
   9437 
   9438 static int test_pullback(isl_ctx *ctx)
   9439 {
   9440 	int i;
   9441 	isl_multi_aff *ma1, *ma2;
   9442 	isl_multi_aff *ma;
   9443 	int equal;
   9444 
   9445 	for (i = 0; i < ARRAY_SIZE(pullback_tests); ++i) {
   9446 		ma1 = isl_multi_aff_read_from_str(ctx, pullback_tests[i].ma1);
   9447 		ma = isl_multi_aff_read_from_str(ctx, pullback_tests[i].ma);
   9448 		ma2 = isl_multi_aff_read_from_str(ctx, pullback_tests[i].res);
   9449 		ma1 = isl_multi_aff_pullback_multi_aff(ma1, ma);
   9450 		equal = isl_multi_aff_plain_is_equal(ma1, ma2);
   9451 		isl_multi_aff_free(ma1);
   9452 		isl_multi_aff_free(ma2);
   9453 		if (equal < 0)
   9454 			return -1;
   9455 		if (!equal)
   9456 			isl_die(ctx, isl_error_unknown, "bad pullback",
   9457 				return -1);
   9458 	}
   9459 
   9460 	return 0;
   9461 }
   9462 
   9463 /* Check that negation is printed correctly and that equal expressions
   9464  * are correctly identified.
   9465  */
   9466 static int test_ast(isl_ctx *ctx)
   9467 {
   9468 	isl_ast_expr *expr, *expr1, *expr2, *expr3;
   9469 	char *str;
   9470 	int ok, equal;
   9471 
   9472 	expr1 = isl_ast_expr_from_id(isl_id_alloc(ctx, "A", NULL));
   9473 	expr2 = isl_ast_expr_from_id(isl_id_alloc(ctx, "B", NULL));
   9474 	expr = isl_ast_expr_add(expr1, expr2);
   9475 	expr2 = isl_ast_expr_copy(expr);
   9476 	expr = isl_ast_expr_neg(expr);
   9477 	expr2 = isl_ast_expr_neg(expr2);
   9478 	equal = isl_ast_expr_is_equal(expr, expr2);
   9479 	str = isl_ast_expr_to_C_str(expr);
   9480 	ok = str ? !strcmp(str, "-(A + B)") : -1;
   9481 	free(str);
   9482 	isl_ast_expr_free(expr);
   9483 	isl_ast_expr_free(expr2);
   9484 
   9485 	if (ok < 0 || equal < 0)
   9486 		return -1;
   9487 	if (!equal)
   9488 		isl_die(ctx, isl_error_unknown,
   9489 			"equal expressions not considered equal", return -1);
   9490 	if (!ok)
   9491 		isl_die(ctx, isl_error_unknown,
   9492 			"isl_ast_expr printed incorrectly", return -1);
   9493 
   9494 	expr1 = isl_ast_expr_from_id(isl_id_alloc(ctx, "A", NULL));
   9495 	expr2 = isl_ast_expr_from_id(isl_id_alloc(ctx, "B", NULL));
   9496 	expr = isl_ast_expr_add(expr1, expr2);
   9497 	expr3 = isl_ast_expr_from_id(isl_id_alloc(ctx, "C", NULL));
   9498 	expr = isl_ast_expr_sub(expr3, expr);
   9499 	str = isl_ast_expr_to_C_str(expr);
   9500 	ok = str ? !strcmp(str, "C - (A + B)") : -1;
   9501 	free(str);
   9502 	isl_ast_expr_free(expr);
   9503 
   9504 	if (ok < 0)
   9505 		return -1;
   9506 	if (!ok)
   9507 		isl_die(ctx, isl_error_unknown,
   9508 			"isl_ast_expr printed incorrectly", return -1);
   9509 
   9510 	return 0;
   9511 }
   9512 
   9513 /* Check that isl_ast_build_expr_from_set returns a valid expression
   9514  * for an empty set.  Note that isl_ast_build_expr_from_set getting
   9515  * called on an empty set probably indicates a bug in the caller.
   9516  */
   9517 static int test_ast_build(isl_ctx *ctx)
   9518 {
   9519 	isl_set *set;
   9520 	isl_ast_build *build;
   9521 	isl_ast_expr *expr;
   9522 
   9523 	set = isl_set_universe(isl_space_params_alloc(ctx, 0));
   9524 	build = isl_ast_build_from_context(set);
   9525 
   9526 	set = isl_set_empty(isl_space_params_alloc(ctx, 0));
   9527 	expr = isl_ast_build_expr_from_set(build, set);
   9528 
   9529 	isl_ast_expr_free(expr);
   9530 	isl_ast_build_free(build);
   9531 
   9532 	if (!expr)
   9533 		return -1;
   9534 
   9535 	return 0;
   9536 }
   9537 
   9538 /* Internal data structure for before_for and after_for callbacks.
   9539  *
   9540  * depth is the current depth
   9541  * before is the number of times before_for has been called
   9542  * after is the number of times after_for has been called
   9543  */
   9544 struct isl_test_codegen_data {
   9545 	int depth;
   9546 	int before;
   9547 	int after;
   9548 };
   9549 
   9550 /* This function is called before each for loop in the AST generated
   9551  * from test_ast_gen1.
   9552  *
   9553  * Increment the number of calls and the depth.
   9554  * Check that the space returned by isl_ast_build_get_schedule_space
   9555  * matches the target space of the schedule returned by
   9556  * isl_ast_build_get_schedule.
   9557  * Return an isl_id that is checked by the corresponding call
   9558  * to after_for.
   9559  */
   9560 static __isl_give isl_id *before_for(__isl_keep isl_ast_build *build,
   9561 	void *user)
   9562 {
   9563 	struct isl_test_codegen_data *data = user;
   9564 	isl_ctx *ctx;
   9565 	isl_space *space;
   9566 	isl_union_map *schedule;
   9567 	isl_union_set *uset;
   9568 	isl_set *set;
   9569 	isl_bool empty;
   9570 	isl_size n;
   9571 	char name[] = "d0";
   9572 
   9573 	ctx = isl_ast_build_get_ctx(build);
   9574 
   9575 	if (data->before >= 3)
   9576 		isl_die(ctx, isl_error_unknown,
   9577 			"unexpected number of for nodes", return NULL);
   9578 	if (data->depth < 0 || data->depth >= 2)
   9579 		isl_die(ctx, isl_error_unknown,
   9580 			"unexpected depth", return NULL);
   9581 
   9582 	snprintf(name, sizeof(name), "d%d", data->depth);
   9583 	data->before++;
   9584 	data->depth++;
   9585 
   9586 	schedule = isl_ast_build_get_schedule(build);
   9587 	uset = isl_union_map_range(schedule);
   9588 	n = isl_union_set_n_set(uset);
   9589 	if (n != 1) {
   9590 		isl_union_set_free(uset);
   9591 		if (n < 0)
   9592 			return NULL;
   9593 		isl_die(ctx, isl_error_unknown,
   9594 			"expecting single range space", return NULL);
   9595 	}
   9596 
   9597 	space = isl_ast_build_get_schedule_space(build);
   9598 	set = isl_union_set_extract_set(uset, space);
   9599 	isl_union_set_free(uset);
   9600 	empty = isl_set_is_empty(set);
   9601 	isl_set_free(set);
   9602 
   9603 	if (empty < 0)
   9604 		return NULL;
   9605 	if (empty)
   9606 		isl_die(ctx, isl_error_unknown,
   9607 			"spaces don't match", return NULL);
   9608 
   9609 	return isl_id_alloc(ctx, name, NULL);
   9610 }
   9611 
   9612 /* This function is called after each for loop in the AST generated
   9613  * from test_ast_gen1.
   9614  *
   9615  * Increment the number of calls and decrement the depth.
   9616  * Check that the annotation attached to the node matches
   9617  * the isl_id returned by the corresponding call to before_for.
   9618  */
   9619 static __isl_give isl_ast_node *after_for(__isl_take isl_ast_node *node,
   9620 	__isl_keep isl_ast_build *build, void *user)
   9621 {
   9622 	struct isl_test_codegen_data *data = user;
   9623 	isl_id *id;
   9624 	const char *name;
   9625 	int valid;
   9626 
   9627 	data->after++;
   9628 	data->depth--;
   9629 
   9630 	if (data->after > data->before)
   9631 		isl_die(isl_ast_node_get_ctx(node), isl_error_unknown,
   9632 			"mismatch in number of for nodes",
   9633 			return isl_ast_node_free(node));
   9634 
   9635 	id = isl_ast_node_get_annotation(node);
   9636 	if (!id)
   9637 		isl_die(isl_ast_node_get_ctx(node), isl_error_unknown,
   9638 			"missing annotation", return isl_ast_node_free(node));
   9639 
   9640 	name = isl_id_get_name(id);
   9641 	valid = name && atoi(name + 1) == data->depth;
   9642 	isl_id_free(id);
   9643 
   9644 	if (!valid)
   9645 		isl_die(isl_ast_node_get_ctx(node), isl_error_unknown,
   9646 			"wrong annotation", return isl_ast_node_free(node));
   9647 
   9648 	return node;
   9649 }
   9650 
   9651 /* This function is called after node in the AST generated
   9652  * from test_ast_gen1.
   9653  *
   9654  * Increment the count in "user" if this is a for node and
   9655  * return true to indicate that descendant should also be visited.
   9656  */
   9657 static isl_bool count_for(__isl_keep isl_ast_node *node, void *user)
   9658 {
   9659 	int *count = user;
   9660 
   9661 	if (isl_ast_node_get_type(node) == isl_ast_node_for)
   9662 		++*count;
   9663 
   9664 	return isl_bool_true;
   9665 }
   9666 
   9667 /* If "node" is a block node, then replace it by its first child.
   9668  */
   9669 static __isl_give isl_ast_node *select_first(__isl_take isl_ast_node *node,
   9670 	void *user)
   9671 {
   9672 	isl_ast_node_list *children;
   9673 	isl_ast_node *child;
   9674 
   9675 	if (isl_ast_node_get_type(node) != isl_ast_node_block)
   9676 		return node;
   9677 
   9678 	children = isl_ast_node_block_get_children(node);
   9679 	child = isl_ast_node_list_get_at(children, 0);
   9680 	isl_ast_node_list_free(children);
   9681 	isl_ast_node_free(node);
   9682 
   9683 	return child;
   9684 }
   9685 
   9686 /* Check that the before_each_for and after_each_for callbacks
   9687  * are called for each for loop in the generated code,
   9688  * that they are called in the right order and that the isl_id
   9689  * returned from the before_each_for callback is attached to
   9690  * the isl_ast_node passed to the corresponding after_each_for call.
   9691  *
   9692  * Additionally, check the basic functionality of
   9693  * isl_ast_node_foreach_descendant_top_down by counting the number
   9694  * of for loops in the resulting AST,
   9695  * as well as that of isl_ast_node_map_descendant_bottom_up
   9696  * by replacing the block node by its first child and
   9697  * counting the number of for loops again.
   9698  */
   9699 static isl_stat test_ast_gen1(isl_ctx *ctx)
   9700 {
   9701 	int count = 0;
   9702 	int modified_count = 0;
   9703 	const char *str;
   9704 	isl_set *set;
   9705 	isl_union_map *schedule;
   9706 	isl_ast_build *build;
   9707 	isl_ast_node *tree;
   9708 	struct isl_test_codegen_data data;
   9709 
   9710 	str = "[N] -> { : N >= 10 }";
   9711 	set = isl_set_read_from_str(ctx, str);
   9712 	str = "[N] -> { A[i,j] -> S[8,i,3,j] : 0 <= i,j <= N; "
   9713 		    "B[i,j] -> S[8,j,9,i] : 0 <= i,j <= N }";
   9714 	schedule = isl_union_map_read_from_str(ctx, str);
   9715 
   9716 	data.before = 0;
   9717 	data.after = 0;
   9718 	data.depth = 0;
   9719 	build = isl_ast_build_from_context(set);
   9720 	build = isl_ast_build_set_before_each_for(build,
   9721 			&before_for, &data);
   9722 	build = isl_ast_build_set_after_each_for(build,
   9723 			&after_for, &data);
   9724 	tree = isl_ast_build_node_from_schedule_map(build, schedule);
   9725 	isl_ast_build_free(build);
   9726 
   9727 	if (isl_ast_node_foreach_descendant_top_down(tree,
   9728 							&count_for, &count) < 0)
   9729 		tree = isl_ast_node_free(tree);
   9730 
   9731 	tree = isl_ast_node_map_descendant_bottom_up(tree, &select_first, NULL);
   9732 
   9733 	if (isl_ast_node_foreach_descendant_top_down(tree, &count_for,
   9734 							&modified_count) < 0)
   9735 		tree = isl_ast_node_free(tree);
   9736 
   9737 	if (!tree)
   9738 		return isl_stat_error;
   9739 
   9740 	isl_ast_node_free(tree);
   9741 
   9742 	if (data.before != 3 || data.after != 3 || count != 3)
   9743 		isl_die(ctx, isl_error_unknown,
   9744 			"unexpected number of for nodes",
   9745 			return isl_stat_error);
   9746 
   9747 	if (modified_count != 2)
   9748 		isl_die(ctx, isl_error_unknown,
   9749 			"unexpected number of for nodes after changes",
   9750 			return isl_stat_error);
   9751 
   9752 	return isl_stat_ok;
   9753 }
   9754 
   9755 /* Check that the AST generator handles domains that are integrally disjoint
   9756  * but not rationally disjoint.
   9757  */
   9758 static int test_ast_gen2(isl_ctx *ctx)
   9759 {
   9760 	const char *str;
   9761 	isl_set *set;
   9762 	isl_union_map *schedule;
   9763 	isl_union_map *options;
   9764 	isl_ast_build *build;
   9765 	isl_ast_node *tree;
   9766 
   9767 	str = "{ A[i,j] -> [i,j] : 0 <= i,j <= 1 }";
   9768 	schedule = isl_union_map_read_from_str(ctx, str);
   9769 	set = isl_set_universe(isl_space_params_alloc(ctx, 0));
   9770 	build = isl_ast_build_from_context(set);
   9771 
   9772 	str = "{ [i,j] -> atomic[1] : i + j = 1; [i,j] -> unroll[1] : i = j }";
   9773 	options = isl_union_map_read_from_str(ctx, str);
   9774 	build = isl_ast_build_set_options(build, options);
   9775 	tree = isl_ast_build_node_from_schedule_map(build, schedule);
   9776 	isl_ast_build_free(build);
   9777 	if (!tree)
   9778 		return -1;
   9779 	isl_ast_node_free(tree);
   9780 
   9781 	return 0;
   9782 }
   9783 
   9784 /* Increment *user on each call.
   9785  */
   9786 static __isl_give isl_ast_node *count_domains(__isl_take isl_ast_node *node,
   9787 	__isl_keep isl_ast_build *build, void *user)
   9788 {
   9789 	int *n = user;
   9790 
   9791 	(*n)++;
   9792 
   9793 	return node;
   9794 }
   9795 
   9796 /* Test that unrolling tries to minimize the number of instances.
   9797  * In particular, for the schedule given below, make sure it generates
   9798  * 3 nodes (rather than 101).
   9799  */
   9800 static int test_ast_gen3(isl_ctx *ctx)
   9801 {
   9802 	const char *str;
   9803 	isl_set *set;
   9804 	isl_union_map *schedule;
   9805 	isl_union_map *options;
   9806 	isl_ast_build *build;
   9807 	isl_ast_node *tree;
   9808 	int n_domain = 0;
   9809 
   9810 	str = "[n] -> { A[i] -> [i] : 0 <= i <= 100 and n <= i <= n + 2 }";
   9811 	schedule = isl_union_map_read_from_str(ctx, str);
   9812 	set = isl_set_universe(isl_space_params_alloc(ctx, 0));
   9813 
   9814 	str = "{ [i] -> unroll[0] }";
   9815 	options = isl_union_map_read_from_str(ctx, str);
   9816 
   9817 	build = isl_ast_build_from_context(set);
   9818 	build = isl_ast_build_set_options(build, options);
   9819 	build = isl_ast_build_set_at_each_domain(build,
   9820 			&count_domains, &n_domain);
   9821 	tree = isl_ast_build_node_from_schedule_map(build, schedule);
   9822 	isl_ast_build_free(build);
   9823 	if (!tree)
   9824 		return -1;
   9825 
   9826 	isl_ast_node_free(tree);
   9827 
   9828 	if (n_domain != 3)
   9829 		isl_die(ctx, isl_error_unknown,
   9830 			"unexpected number of for nodes", return -1);
   9831 
   9832 	return 0;
   9833 }
   9834 
   9835 /* Check that if the ast_build_exploit_nested_bounds options is set,
   9836  * we do not get an outer if node in the generated AST,
   9837  * while we do get such an outer if node if the options is not set.
   9838  */
   9839 static int test_ast_gen4(isl_ctx *ctx)
   9840 {
   9841 	const char *str;
   9842 	isl_set *set;
   9843 	isl_union_map *schedule;
   9844 	isl_ast_build *build;
   9845 	isl_ast_node *tree;
   9846 	enum isl_ast_node_type type;
   9847 	int enb;
   9848 
   9849 	enb = isl_options_get_ast_build_exploit_nested_bounds(ctx);
   9850 	str = "[N,M] -> { A[i,j] -> [i,j] : 0 <= i <= N and 0 <= j <= M }";
   9851 
   9852 	isl_options_set_ast_build_exploit_nested_bounds(ctx, 1);
   9853 
   9854 	schedule = isl_union_map_read_from_str(ctx, str);
   9855 	set = isl_set_universe(isl_space_params_alloc(ctx, 0));
   9856 	build = isl_ast_build_from_context(set);
   9857 	tree = isl_ast_build_node_from_schedule_map(build, schedule);
   9858 	isl_ast_build_free(build);
   9859 	if (!tree)
   9860 		return -1;
   9861 
   9862 	type = isl_ast_node_get_type(tree);
   9863 	isl_ast_node_free(tree);
   9864 
   9865 	if (type == isl_ast_node_if)
   9866 		isl_die(ctx, isl_error_unknown,
   9867 			"not expecting if node", return -1);
   9868 
   9869 	isl_options_set_ast_build_exploit_nested_bounds(ctx, 0);
   9870 
   9871 	schedule = isl_union_map_read_from_str(ctx, str);
   9872 	set = isl_set_universe(isl_space_params_alloc(ctx, 0));
   9873 	build = isl_ast_build_from_context(set);
   9874 	tree = isl_ast_build_node_from_schedule_map(build, schedule);
   9875 	isl_ast_build_free(build);
   9876 	if (!tree)
   9877 		return -1;
   9878 
   9879 	type = isl_ast_node_get_type(tree);
   9880 	isl_ast_node_free(tree);
   9881 
   9882 	if (type != isl_ast_node_if)
   9883 		isl_die(ctx, isl_error_unknown,
   9884 			"expecting if node", return -1);
   9885 
   9886 	isl_options_set_ast_build_exploit_nested_bounds(ctx, enb);
   9887 
   9888 	return 0;
   9889 }
   9890 
   9891 /* This function is called for each leaf in the AST generated
   9892  * from test_ast_gen5.
   9893  *
   9894  * We finalize the AST generation by extending the outer schedule
   9895  * with a zero-dimensional schedule.  If this results in any for loops,
   9896  * then this means that we did not pass along enough information
   9897  * about the outer schedule to the inner AST generation.
   9898  */
   9899 static __isl_give isl_ast_node *create_leaf(__isl_take isl_ast_build *build,
   9900 	void *user)
   9901 {
   9902 	isl_union_map *schedule, *extra;
   9903 	isl_ast_node *tree;
   9904 
   9905 	schedule = isl_ast_build_get_schedule(build);
   9906 	extra = isl_union_map_copy(schedule);
   9907 	extra = isl_union_map_from_domain(isl_union_map_domain(extra));
   9908 	schedule = isl_union_map_range_product(schedule, extra);
   9909 	tree = isl_ast_build_node_from_schedule_map(build, schedule);
   9910 	isl_ast_build_free(build);
   9911 
   9912 	if (!tree)
   9913 		return NULL;
   9914 
   9915 	if (isl_ast_node_get_type(tree) == isl_ast_node_for)
   9916 		isl_die(isl_ast_node_get_ctx(tree), isl_error_unknown,
   9917 			"code should not contain any for loop",
   9918 			return isl_ast_node_free(tree));
   9919 
   9920 	return tree;
   9921 }
   9922 
   9923 /* Check that we do not lose any information when going back and
   9924  * forth between internal and external schedule.
   9925  *
   9926  * In particular, we create an AST where we unroll the only
   9927  * non-constant dimension in the schedule.  We therefore do
   9928  * not expect any for loops in the AST.  However, older versions
   9929  * of isl would not pass along enough information about the outer
   9930  * schedule when performing an inner code generation from a create_leaf
   9931  * callback, resulting in the inner code generation producing a for loop.
   9932  */
   9933 static int test_ast_gen5(isl_ctx *ctx)
   9934 {
   9935 	const char *str;
   9936 	isl_set *set;
   9937 	isl_union_map *schedule, *options;
   9938 	isl_ast_build *build;
   9939 	isl_ast_node *tree;
   9940 
   9941 	str = "{ A[] -> [1, 1, 2]; B[i] -> [1, i, 0] : i >= 1 and i <= 2 }";
   9942 	schedule = isl_union_map_read_from_str(ctx, str);
   9943 
   9944 	str = "{ [a, b, c] -> unroll[1] : exists (e0 = [(a)/4]: "
   9945 				"4e0 >= -1 + a - b and 4e0 <= -2 + a + b) }";
   9946 	options = isl_union_map_read_from_str(ctx, str);
   9947 
   9948 	set = isl_set_universe(isl_space_params_alloc(ctx, 0));
   9949 	build = isl_ast_build_from_context(set);
   9950 	build = isl_ast_build_set_options(build, options);
   9951         build = isl_ast_build_set_create_leaf(build, &create_leaf, NULL);
   9952 	tree = isl_ast_build_node_from_schedule_map(build, schedule);
   9953 	isl_ast_build_free(build);
   9954 	isl_ast_node_free(tree);
   9955 	if (!tree)
   9956 		return -1;
   9957 
   9958 	return 0;
   9959 }
   9960 
   9961 /* Check that the expression
   9962  *
   9963  *	[n] -> { [n/2] : n <= 0 and n % 2 = 0; [0] : n > 0 }
   9964  *
   9965  * is not combined into
   9966  *
   9967  *	min(n/2, 0)
   9968  *
   9969  * as this would result in n/2 being evaluated in parts of
   9970  * the definition domain where n is not a multiple of 2.
   9971  */
   9972 static int test_ast_expr(isl_ctx *ctx)
   9973 {
   9974 	const char *str;
   9975 	isl_pw_aff *pa;
   9976 	isl_ast_build *build;
   9977 	isl_ast_expr *expr;
   9978 	int min_max;
   9979 	int is_min;
   9980 
   9981 	min_max = isl_options_get_ast_build_detect_min_max(ctx);
   9982 	isl_options_set_ast_build_detect_min_max(ctx, 1);
   9983 
   9984 	str = "[n] -> { [n/2] : n <= 0 and n % 2 = 0; [0] : n > 0 }";
   9985 	pa = isl_pw_aff_read_from_str(ctx, str);
   9986 	build = isl_ast_build_alloc(ctx);
   9987 	expr = isl_ast_build_expr_from_pw_aff(build, pa);
   9988 	is_min = isl_ast_expr_get_type(expr) == isl_ast_expr_op &&
   9989 		 isl_ast_expr_get_op_type(expr) == isl_ast_expr_op_min;
   9990 	isl_ast_build_free(build);
   9991 	isl_ast_expr_free(expr);
   9992 
   9993 	isl_options_set_ast_build_detect_min_max(ctx, min_max);
   9994 
   9995 	if (!expr)
   9996 		return -1;
   9997 	if (is_min)
   9998 		isl_die(ctx, isl_error_unknown,
   9999 			"expressions should not be combined", return -1);
   10000 
   10001 	return 0;
   10002 }
   10003 
   10004 static int test_ast_gen(isl_ctx *ctx)
   10005 {
   10006 	if (test_ast_gen1(ctx) < 0)
   10007 		return -1;
   10008 	if (test_ast_gen2(ctx) < 0)
   10009 		return -1;
   10010 	if (test_ast_gen3(ctx) < 0)
   10011 		return -1;
   10012 	if (test_ast_gen4(ctx) < 0)
   10013 		return -1;
   10014 	if (test_ast_gen5(ctx) < 0)
   10015 		return -1;
   10016 	if (test_ast_expr(ctx) < 0)
   10017 		return -1;
   10018 	return 0;
   10019 }
   10020 
   10021 /* Check if dropping output dimensions from an isl_pw_multi_aff
   10022  * works properly.
   10023  */
   10024 static int test_pw_multi_aff(isl_ctx *ctx)
   10025 {
   10026 	const char *str;
   10027 	isl_pw_multi_aff *pma1, *pma2;
   10028 	int equal;
   10029 
   10030 	str = "{ [i,j] -> [i+j, 4i-j] }";
   10031 	pma1 = isl_pw_multi_aff_read_from_str(ctx, str);
   10032 	str = "{ [i,j] -> [4i-j] }";
   10033 	pma2 = isl_pw_multi_aff_read_from_str(ctx, str);
   10034 
   10035 	pma1 = isl_pw_multi_aff_drop_dims(pma1, isl_dim_out, 0, 1);
   10036 
   10037 	equal = isl_pw_multi_aff_plain_is_equal(pma1, pma2);
   10038 
   10039 	isl_pw_multi_aff_free(pma1);
   10040 	isl_pw_multi_aff_free(pma2);
   10041 	if (equal < 0)
   10042 		return -1;
   10043 	if (!equal)
   10044 		isl_die(ctx, isl_error_unknown,
   10045 			"expressions not equal", return -1);
   10046 
   10047 	return 0;
   10048 }
   10049 
   10050 /* Check that we can properly parse multi piecewise affine expressions
   10051  * where the piecewise affine expressions have different domains.
   10052  */
   10053 static int test_multi_pw_aff_1(isl_ctx *ctx)
   10054 {
   10055 	const char *str;
   10056 	isl_set *dom, *dom2;
   10057 	isl_multi_pw_aff *mpa1, *mpa2;
   10058 	isl_pw_aff *pa;
   10059 	int equal;
   10060 	int equal_domain;
   10061 
   10062 	mpa1 = isl_multi_pw_aff_read_from_str(ctx, "{ [i] -> [i] }");
   10063 	dom = isl_set_read_from_str(ctx, "{ [i] : i > 0 }");
   10064 	mpa1 = isl_multi_pw_aff_intersect_domain(mpa1, dom);
   10065 	mpa2 = isl_multi_pw_aff_read_from_str(ctx, "{ [i] -> [2i] }");
   10066 	mpa2 = isl_multi_pw_aff_flat_range_product(mpa1, mpa2);
   10067 	str = "{ [i] -> [(i : i > 0), 2i] }";
   10068 	mpa1 = isl_multi_pw_aff_read_from_str(ctx, str);
   10069 
   10070 	equal = isl_multi_pw_aff_plain_is_equal(mpa1, mpa2);
   10071 
   10072 	pa = isl_multi_pw_aff_get_pw_aff(mpa1, 0);
   10073 	dom = isl_pw_aff_domain(pa);
   10074 	pa = isl_multi_pw_aff_get_pw_aff(mpa1, 1);
   10075 	dom2 = isl_pw_aff_domain(pa);
   10076 	equal_domain = isl_set_is_equal(dom, dom2);
   10077 
   10078 	isl_set_free(dom);
   10079 	isl_set_free(dom2);
   10080 	isl_multi_pw_aff_free(mpa1);
   10081 	isl_multi_pw_aff_free(mpa2);
   10082 
   10083 	if (equal < 0)
   10084 		return -1;
   10085 	if (!equal)
   10086 		isl_die(ctx, isl_error_unknown,
   10087 			"expressions not equal", return -1);
   10088 
   10089 	if (equal_domain < 0)
   10090 		return -1;
   10091 	if (equal_domain)
   10092 		isl_die(ctx, isl_error_unknown,
   10093 			"domains unexpectedly equal", return -1);
   10094 
   10095 	return 0;
   10096 }
   10097 
   10098 /* Check that the dimensions in the explicit domain
   10099  * of a multi piecewise affine expression are properly
   10100  * taken into account.
   10101  */
   10102 static int test_multi_pw_aff_2(isl_ctx *ctx)
   10103 {
   10104 	const char *str;
   10105 	isl_bool involves1, involves2, involves3, equal;
   10106 	isl_multi_pw_aff *mpa, *mpa1, *mpa2;
   10107 
   10108 	str = "{ A[x,y] -> B[] : x >= y }";
   10109 	mpa = isl_multi_pw_aff_read_from_str(ctx, str);
   10110 	involves1 = isl_multi_pw_aff_involves_dims(mpa, isl_dim_in, 0, 2);
   10111 	mpa1 = isl_multi_pw_aff_copy(mpa);
   10112 
   10113 	mpa = isl_multi_pw_aff_insert_dims(mpa, isl_dim_in, 0, 1);
   10114 	involves2 = isl_multi_pw_aff_involves_dims(mpa, isl_dim_in, 0, 1);
   10115 	involves3 = isl_multi_pw_aff_involves_dims(mpa, isl_dim_in, 1, 2);
   10116 	str = "{ [a,x,y] -> B[] : x >= y }";
   10117 	mpa2 = isl_multi_pw_aff_read_from_str(ctx, str);
   10118 	equal = isl_multi_pw_aff_plain_is_equal(mpa, mpa2);
   10119 	isl_multi_pw_aff_free(mpa2);
   10120 
   10121 	mpa = isl_multi_pw_aff_drop_dims(mpa, isl_dim_in, 0, 1);
   10122 	mpa = isl_multi_pw_aff_set_tuple_name(mpa, isl_dim_in, "A");
   10123 	if (equal >= 0 && equal)
   10124 		equal = isl_multi_pw_aff_plain_is_equal(mpa, mpa1);
   10125 	isl_multi_pw_aff_free(mpa1);
   10126 	isl_multi_pw_aff_free(mpa);
   10127 
   10128 	if (involves1 < 0 || involves2 < 0 || involves3 < 0 || equal < 0)
   10129 		return -1;
   10130 	if (!equal)
   10131 		isl_die(ctx, isl_error_unknown,
   10132 			"incorrect result of dimension insertion/removal",
   10133 			return isl_stat_error);
   10134 	if (!involves1 || involves2 || !involves3)
   10135 		isl_die(ctx, isl_error_unknown,
   10136 			"incorrect characterization of involved dimensions",
   10137 			return isl_stat_error);
   10138 
   10139 	return 0;
   10140 }
   10141 
   10142 /* Check that isl_multi_union_pw_aff_multi_val_on_domain
   10143  * sets the explicit domain of a zero-dimensional result,
   10144  * such that it can be converted to an isl_union_map.
   10145  */
   10146 static isl_stat test_multi_pw_aff_3(isl_ctx *ctx)
   10147 {
   10148 	isl_space *space;
   10149 	isl_union_set *dom;
   10150 	isl_multi_val *mv;
   10151 	isl_multi_union_pw_aff *mupa;
   10152 	isl_union_map *umap;
   10153 
   10154 	dom = isl_union_set_read_from_str(ctx, "{ A[]; B[] }");
   10155 	space = isl_union_set_get_space(dom);
   10156 	mv = isl_multi_val_zero(isl_space_set_from_params(space));
   10157 	mupa = isl_multi_union_pw_aff_multi_val_on_domain(dom, mv);
   10158 	umap = isl_union_map_from_multi_union_pw_aff(mupa);
   10159 	isl_union_map_free(umap);
   10160 	if (!umap)
   10161 		return isl_stat_error;
   10162 
   10163 	return isl_stat_ok;
   10164 }
   10165 
   10166 /* String descriptions of boxes that
   10167  * are used for reconstructing box maps from their lower and upper bounds.
   10168  */
   10169 static const char *multi_pw_aff_box_tests[] = {
   10170 	"{ A[x, y] -> [] : x + y >= 0 }",
   10171 	"[N] -> { A[x, y] -> [x] : x + y <= N }",
   10172 	"[N] -> { A[x, y] -> [x : y] : x + y <= N }",
   10173 };
   10174 
   10175 /* Check that map representations of boxes can be reconstructed
   10176  * from their lower and upper bounds.
   10177  */
   10178 static isl_stat test_multi_pw_aff_box(isl_ctx *ctx)
   10179 {
   10180 	int i;
   10181 
   10182 	for (i = 0; i < ARRAY_SIZE(multi_pw_aff_box_tests); ++i) {
   10183 		const char *str;
   10184 		isl_bool equal;
   10185 		isl_map *map, *box;
   10186 		isl_multi_pw_aff *min, *max;
   10187 
   10188 		str = multi_pw_aff_box_tests[i];
   10189 		map = isl_map_read_from_str(ctx, str);
   10190 		min = isl_map_min_multi_pw_aff(isl_map_copy(map));
   10191 		max = isl_map_max_multi_pw_aff(isl_map_copy(map));
   10192 		box = isl_map_universe(isl_map_get_space(map));
   10193 		box = isl_map_lower_bound_multi_pw_aff(box, min);
   10194 		box = isl_map_upper_bound_multi_pw_aff(box, max);
   10195 		equal = isl_map_is_equal(map, box);
   10196 		isl_map_free(map);
   10197 		isl_map_free(box);
   10198 		if (equal < 0)
   10199 			return isl_stat_error;
   10200 		if (!equal)
   10201 			isl_die(ctx, isl_error_unknown,
   10202 				"unexpected result", return isl_stat_error);
   10203 	}
   10204 
   10205 	return isl_stat_ok;
   10206 }
   10207 
   10208 /* Perform some tests on multi piecewise affine expressions.
   10209  */
   10210 static int test_multi_pw_aff(isl_ctx *ctx)
   10211 {
   10212 	if (test_multi_pw_aff_1(ctx) < 0)
   10213 		return -1;
   10214 	if (test_multi_pw_aff_2(ctx) < 0)
   10215 		return -1;
   10216 	if (test_multi_pw_aff_3(ctx) < 0)
   10217 		return -1;
   10218 	if (test_multi_pw_aff_box(ctx) < 0)
   10219 		return -1;
   10220 	return 0;
   10221 }
   10222 
   10223 /* This is a regression test for a bug where isl_basic_map_simplify
   10224  * would end up in an infinite loop.  In particular, we construct
   10225  * an empty basic set that is not obviously empty.
   10226  * isl_basic_set_is_empty marks the basic set as empty.
   10227  * After projecting out i3, the variable can be dropped completely,
   10228  * but isl_basic_map_simplify refrains from doing so if the basic set
   10229  * is empty and would end up in an infinite loop if it didn't test
   10230  * explicitly for empty basic maps in the outer loop.
   10231  */
   10232 static int test_simplify_1(isl_ctx *ctx)
   10233 {
   10234 	const char *str;
   10235 	isl_basic_set *bset;
   10236 	int empty;
   10237 
   10238 	str = "{ [i0, i1, i2, i3] : i0 >= -2 and 6i2 <= 4 + i0 + 5i1 and "
   10239 		"i2 <= 22 and 75i2 <= 111 + 13i0 + 60i1 and "
   10240 		"25i2 >= 38 + 6i0 + 20i1 and i0 <= -1 and i2 >= 20 and "
   10241 		"i3 >= i2 }";
   10242 	bset = isl_basic_set_read_from_str(ctx, str);
   10243 	empty = isl_basic_set_is_empty(bset);
   10244 	bset = isl_basic_set_project_out(bset, isl_dim_set, 3, 1);
   10245 	isl_basic_set_free(bset);
   10246 	if (!bset)
   10247 		return -1;
   10248 	if (!empty)
   10249 		isl_die(ctx, isl_error_unknown,
   10250 			"basic set should be empty", return -1);
   10251 
   10252 	return 0;
   10253 }
   10254 
   10255 /* Check that the equality in the set description below
   10256  * is simplified away.
   10257  */
   10258 static int test_simplify_2(isl_ctx *ctx)
   10259 {
   10260 	const char *str;
   10261 	isl_basic_set *bset;
   10262 	isl_bool universe;
   10263 
   10264 	str = "{ [a] : exists e0, e1: 32e1 = 31 + 31a + 31e0 }";
   10265 	bset = isl_basic_set_read_from_str(ctx, str);
   10266 	universe = isl_basic_set_plain_is_universe(bset);
   10267 	isl_basic_set_free(bset);
   10268 
   10269 	if (universe < 0)
   10270 		return -1;
   10271 	if (!universe)
   10272 		isl_die(ctx, isl_error_unknown,
   10273 			"equality not simplified away", return -1);
   10274 	return 0;
   10275 }
   10276 
   10277 /* Some simplification tests.
   10278  */
   10279 static int test_simplify(isl_ctx *ctx)
   10280 {
   10281 	if (test_simplify_1(ctx) < 0)
   10282 		return -1;
   10283 	if (test_simplify_2(ctx) < 0)
   10284 		return -1;
   10285 	return 0;
   10286 }
   10287 
   10288 /* This is a regression test for a bug where isl_tab_basic_map_partial_lexopt
   10289  * with gbr context would fail to disable the use of the shifted tableau
   10290  * when transferring equalities for the input to the context, resulting
   10291  * in invalid sample values.
   10292  */
   10293 static int test_partial_lexmin(isl_ctx *ctx)
   10294 {
   10295 	const char *str;
   10296 	isl_basic_set *bset;
   10297 	isl_basic_map *bmap;
   10298 	isl_map *map;
   10299 
   10300 	str = "{ [1, b, c, 1 - c] -> [e] : 2e <= -c and 2e >= -3 + c }";
   10301 	bmap = isl_basic_map_read_from_str(ctx, str);
   10302 	str = "{ [a, b, c, d] : c <= 1 and 2d >= 6 - 4b - c }";
   10303 	bset = isl_basic_set_read_from_str(ctx, str);
   10304 	map = isl_basic_map_partial_lexmin(bmap, bset, NULL);
   10305 	isl_map_free(map);
   10306 
   10307 	if (!map)
   10308 		return -1;
   10309 
   10310 	return 0;
   10311 }
   10312 
   10313 /* Check that the variable compression performed on the existentially
   10314  * quantified variables inside isl_basic_set_compute_divs is not confused
   10315  * by the implicit equalities among the parameters.
   10316  */
   10317 static int test_compute_divs(isl_ctx *ctx)
   10318 {
   10319 	const char *str;
   10320 	isl_basic_set *bset;
   10321 	isl_set *set;
   10322 
   10323 	str = "[a, b, c, d, e] -> { [] : exists (e0: 2d = b and a <= 124 and "
   10324 		"b <= 2046 and b >= 0 and b <= 60 + 64a and 2e >= b + 2c and "
   10325 		"2e >= b and 2e <= 1 + b and 2e <= 1 + b + 2c and "
   10326 		"32768e0 >= -124 + a and 2097152e0 <= 60 + 64a - b) }";
   10327 	bset = isl_basic_set_read_from_str(ctx, str);
   10328 	set = isl_basic_set_compute_divs(bset);
   10329 	isl_set_free(set);
   10330 	if (!set)
   10331 		return -1;
   10332 
   10333 	return 0;
   10334 }
   10335 
   10336 /* Check that isl_schedule_get_map is not confused by a schedule tree
   10337  * with divergent filter node parameters, as can result from a call
   10338  * to isl_schedule_intersect_domain.
   10339  */
   10340 static int test_schedule_tree(isl_ctx *ctx)
   10341 {
   10342 	const char *str;
   10343 	isl_union_set *uset;
   10344 	isl_schedule *sched1, *sched2;
   10345 	isl_union_map *umap;
   10346 
   10347 	uset = isl_union_set_read_from_str(ctx, "{ A[i] }");
   10348 	sched1 = isl_schedule_from_domain(uset);
   10349 	uset = isl_union_set_read_from_str(ctx, "{ B[] }");
   10350 	sched2 = isl_schedule_from_domain(uset);
   10351 
   10352 	sched1 = isl_schedule_sequence(sched1, sched2);
   10353 	str = "[n] -> { A[i] : 0 <= i < n; B[] }";
   10354 	uset = isl_union_set_read_from_str(ctx, str);
   10355 	sched1 = isl_schedule_intersect_domain(sched1, uset);
   10356 	umap = isl_schedule_get_map(sched1);
   10357 	isl_schedule_free(sched1);
   10358 	isl_union_map_free(umap);
   10359 	if (!umap)
   10360 		return -1;
   10361 
   10362 	return 0;
   10363 }
   10364 
   10365 /* Check that a zero-dimensional prefix schedule keeps track
   10366  * of the domain and outer filters.
   10367  */
   10368 static int test_schedule_tree_prefix(isl_ctx *ctx)
   10369 {
   10370 	const char *str;
   10371 	isl_bool equal;
   10372 	isl_union_set *uset;
   10373 	isl_union_set_list *filters;
   10374 	isl_multi_union_pw_aff *mupa, *mupa2;
   10375 	isl_schedule_node *node;
   10376 
   10377 	str = "{ S1[i,j] : 0 <= i,j < 10; S2[i,j] : 0 <= i,j < 10 }";
   10378 	uset = isl_union_set_read_from_str(ctx, str);
   10379 	node = isl_schedule_node_from_domain(uset);
   10380 	node = isl_schedule_node_child(node, 0);
   10381 
   10382 	str = "{ S1[i,j] : i > j }";
   10383 	uset = isl_union_set_read_from_str(ctx, str);
   10384 	filters = isl_union_set_list_from_union_set(uset);
   10385 	str = "{ S1[i,j] : i <= j; S2[i,j] }";
   10386 	uset = isl_union_set_read_from_str(ctx, str);
   10387 	filters = isl_union_set_list_add(filters, uset);
   10388 	node = isl_schedule_node_insert_sequence(node, filters);
   10389 
   10390 	node = isl_schedule_node_grandchild(node, 0, 0);
   10391 	mupa = isl_schedule_node_get_prefix_schedule_multi_union_pw_aff(node);
   10392 	str = "([] : { S1[i,j] : i > j })";
   10393 	mupa2 = isl_multi_union_pw_aff_read_from_str(ctx, str);
   10394 	equal = isl_multi_union_pw_aff_plain_is_equal(mupa, mupa2);
   10395 	isl_multi_union_pw_aff_free(mupa2);
   10396 	isl_multi_union_pw_aff_free(mupa);
   10397 	isl_schedule_node_free(node);
   10398 
   10399 	if (equal < 0)
   10400 		return -1;
   10401 	if (!equal)
   10402 		isl_die(ctx, isl_error_unknown, "unexpected prefix schedule",
   10403 			return -1);
   10404 
   10405 	return 0;
   10406 }
   10407 
   10408 /* Check that the reaching domain elements and the prefix schedule
   10409  * at a leaf node are the same before and after grouping.
   10410  */
   10411 static int test_schedule_tree_group_1(isl_ctx *ctx)
   10412 {
   10413 	int equal;
   10414 	const char *str;
   10415 	isl_id *id;
   10416 	isl_union_set *uset;
   10417 	isl_multi_union_pw_aff *mupa;
   10418 	isl_union_pw_multi_aff *upma1, *upma2;
   10419 	isl_union_set *domain1, *domain2;
   10420 	isl_union_map *umap1, *umap2;
   10421 	isl_schedule_node *node;
   10422 
   10423 	str = "{ S1[i,j] : 0 <= i,j < 10; S2[i,j] : 0 <= i,j < 10 }";
   10424 	uset = isl_union_set_read_from_str(ctx, str);
   10425 	node = isl_schedule_node_from_domain(uset);
   10426 	node = isl_schedule_node_child(node, 0);
   10427 	str = "[{ S1[i,j] -> [i]; S2[i,j] -> [9 - i] }]";
   10428 	mupa = isl_multi_union_pw_aff_read_from_str(ctx, str);
   10429 	node = isl_schedule_node_insert_partial_schedule(node, mupa);
   10430 	node = isl_schedule_node_child(node, 0);
   10431 	str = "[{ S1[i,j] -> [j]; S2[i,j] -> [j] }]";
   10432 	mupa = isl_multi_union_pw_aff_read_from_str(ctx, str);
   10433 	node = isl_schedule_node_insert_partial_schedule(node, mupa);
   10434 	node = isl_schedule_node_child(node, 0);
   10435 	umap1 = isl_schedule_node_get_prefix_schedule_union_map(node);
   10436 	upma1 = isl_schedule_node_get_prefix_schedule_union_pw_multi_aff(node);
   10437 	domain1 = isl_schedule_node_get_domain(node);
   10438 	id = isl_id_alloc(ctx, "group", NULL);
   10439 	node = isl_schedule_node_parent(node);
   10440 	node = isl_schedule_node_group(node, id);
   10441 	node = isl_schedule_node_child(node, 0);
   10442 	umap2 = isl_schedule_node_get_prefix_schedule_union_map(node);
   10443 	upma2 = isl_schedule_node_get_prefix_schedule_union_pw_multi_aff(node);
   10444 	domain2 = isl_schedule_node_get_domain(node);
   10445 	equal = isl_union_pw_multi_aff_plain_is_equal(upma1, upma2);
   10446 	if (equal >= 0 && equal)
   10447 		equal = isl_union_set_is_equal(domain1, domain2);
   10448 	if (equal >= 0 && equal)
   10449 		equal = isl_union_map_is_equal(umap1, umap2);
   10450 	isl_union_map_free(umap1);
   10451 	isl_union_map_free(umap2);
   10452 	isl_union_set_free(domain1);
   10453 	isl_union_set_free(domain2);
   10454 	isl_union_pw_multi_aff_free(upma1);
   10455 	isl_union_pw_multi_aff_free(upma2);
   10456 	isl_schedule_node_free(node);
   10457 
   10458 	if (equal < 0)
   10459 		return -1;
   10460 	if (!equal)
   10461 		isl_die(ctx, isl_error_unknown,
   10462 			"expressions not equal", return -1);
   10463 
   10464 	return 0;
   10465 }
   10466 
   10467 /* Check that we can have nested groupings and that the union map
   10468  * schedule representation is the same before and after the grouping.
   10469  * Note that after the grouping, the union map representation contains
   10470  * the domain constraints from the ranges of the expansion nodes,
   10471  * while they are missing from the union map representation of
   10472  * the tree without expansion nodes.
   10473  *
   10474  * Also check that the global expansion is as expected.
   10475  */
   10476 static int test_schedule_tree_group_2(isl_ctx *ctx)
   10477 {
   10478 	int equal, equal_expansion;
   10479 	const char *str;
   10480 	isl_id *id;
   10481 	isl_union_set *uset;
   10482 	isl_union_map *umap1, *umap2;
   10483 	isl_union_map *expansion1, *expansion2;
   10484 	isl_union_set_list *filters;
   10485 	isl_multi_union_pw_aff *mupa;
   10486 	isl_schedule *schedule;
   10487 	isl_schedule_node *node;
   10488 
   10489 	str = "{ S1[i,j] : 0 <= i,j < 10; S2[i,j] : 0 <= i,j < 10; "
   10490 		"S3[i,j] : 0 <= i,j < 10 }";
   10491 	uset = isl_union_set_read_from_str(ctx, str);
   10492 	node = isl_schedule_node_from_domain(uset);
   10493 	node = isl_schedule_node_child(node, 0);
   10494 	str = "[{ S1[i,j] -> [i]; S2[i,j] -> [i]; S3[i,j] -> [i] }]";
   10495 	mupa = isl_multi_union_pw_aff_read_from_str(ctx, str);
   10496 	node = isl_schedule_node_insert_partial_schedule(node, mupa);
   10497 	node = isl_schedule_node_child(node, 0);
   10498 	str = "{ S1[i,j] }";
   10499 	uset = isl_union_set_read_from_str(ctx, str);
   10500 	filters = isl_union_set_list_from_union_set(uset);
   10501 	str = "{ S2[i,j]; S3[i,j] }";
   10502 	uset = isl_union_set_read_from_str(ctx, str);
   10503 	filters = isl_union_set_list_add(filters, uset);
   10504 	node = isl_schedule_node_insert_sequence(node, filters);
   10505 	node = isl_schedule_node_grandchild(node, 1, 0);
   10506 	str = "{ S2[i,j] }";
   10507 	uset = isl_union_set_read_from_str(ctx, str);
   10508 	filters = isl_union_set_list_from_union_set(uset);
   10509 	str = "{ S3[i,j] }";
   10510 	uset = isl_union_set_read_from_str(ctx, str);
   10511 	filters = isl_union_set_list_add(filters, uset);
   10512 	node = isl_schedule_node_insert_sequence(node, filters);
   10513 
   10514 	schedule = isl_schedule_node_get_schedule(node);
   10515 	umap1 = isl_schedule_get_map(schedule);
   10516 	uset = isl_schedule_get_domain(schedule);
   10517 	umap1 = isl_union_map_intersect_domain(umap1, uset);
   10518 	isl_schedule_free(schedule);
   10519 
   10520 	node = isl_schedule_node_grandparent(node);
   10521 	id = isl_id_alloc(ctx, "group1", NULL);
   10522 	node = isl_schedule_node_group(node, id);
   10523 	node = isl_schedule_node_grandchild(node, 1, 0);
   10524 	id = isl_id_alloc(ctx, "group2", NULL);
   10525 	node = isl_schedule_node_group(node, id);
   10526 
   10527 	schedule = isl_schedule_node_get_schedule(node);
   10528 	umap2 = isl_schedule_get_map(schedule);
   10529 	isl_schedule_free(schedule);
   10530 
   10531 	node = isl_schedule_node_root(node);
   10532 	node = isl_schedule_node_child(node, 0);
   10533 	expansion1 = isl_schedule_node_get_subtree_expansion(node);
   10534 	isl_schedule_node_free(node);
   10535 
   10536 	str = "{ group1[i] -> S1[i,j] : 0 <= i,j < 10; "
   10537 		"group1[i] -> S2[i,j] : 0 <= i,j < 10; "
   10538 		"group1[i] -> S3[i,j] : 0 <= i,j < 10 }";
   10539 
   10540 	expansion2 = isl_union_map_read_from_str(ctx, str);
   10541 
   10542 	equal = isl_union_map_is_equal(umap1, umap2);
   10543 	equal_expansion = isl_union_map_is_equal(expansion1, expansion2);
   10544 
   10545 	isl_union_map_free(umap1);
   10546 	isl_union_map_free(umap2);
   10547 	isl_union_map_free(expansion1);
   10548 	isl_union_map_free(expansion2);
   10549 
   10550 	if (equal < 0 || equal_expansion < 0)
   10551 		return -1;
   10552 	if (!equal)
   10553 		isl_die(ctx, isl_error_unknown,
   10554 			"expressions not equal", return -1);
   10555 	if (!equal_expansion)
   10556 		isl_die(ctx, isl_error_unknown,
   10557 			"unexpected expansion", return -1);
   10558 
   10559 	return 0;
   10560 }
   10561 
   10562 /* Some tests for the isl_schedule_node_group function.
   10563  */
   10564 static int test_schedule_tree_group(isl_ctx *ctx)
   10565 {
   10566 	if (test_schedule_tree_group_1(ctx) < 0)
   10567 		return -1;
   10568 	if (test_schedule_tree_group_2(ctx) < 0)
   10569 		return -1;
   10570 	return 0;
   10571 }
   10572 
   10573 struct {
   10574 	const char *set;
   10575 	const char *dual;
   10576 } coef_tests[] = {
   10577 	{ "{ rat: [i] : 0 <= i <= 10 }",
   10578 	  "{ rat: coefficients[[cst] -> [a]] : cst >= 0 and 10a + cst >= 0 }" },
   10579 	{ "{ rat: [i] : FALSE }",
   10580 	  "{ rat: coefficients[[cst] -> [a]] }" },
   10581 	{ "{ rat: [i] : }",
   10582 	  "{ rat: coefficients[[cst] -> [0]] : cst >= 0 }" },
   10583 	{ "{ [0:,1,2:3] }",
   10584 	  "{ rat: coefficients[[c_cst] -> [a, b, c]] : "
   10585 		"a >= 0 and 2c >= -c_cst - b and 3c >= -c_cst - b }" },
   10586 	{ "[M, N] -> { [x = (1 - N):-1, -4x:(M - 4x)] }",
   10587 	  "{ rat: coefficients[[c_cst, c_M = 0:, c_N = 0:] -> [a, b = -c_M:]] :"
   10588 		"4b >= -c_N + a and 4b >= -c_cst - 2c_N + a }" },
   10589 	{ "{ rat : [x, y] : 1 <= 2x <= 9 and 2 <= 3y <= 16 }",
   10590 	  "{ rat: coefficients[[c_cst] -> [c_x, c_y]] : "
   10591 		"4c_y >= -6c_cst - 3c_x and 4c_y >= -6c_cst - 27c_x and "
   10592 		"32c_y >= -6c_cst - 3c_x and 32c_y >= -6c_cst - 27c_x }" },
   10593 	{ "{ [x, y, z] : 3y <= 2x - 2 and y >= -2 + 2x and 2y >= 2 - x }",
   10594 	  "{ rat: coefficients[[cst] -> [a, b, c]] }" },
   10595 };
   10596 
   10597 struct {
   10598 	const char *set;
   10599 	const char *dual;
   10600 } sol_tests[] = {
   10601 	{ "{ rat: coefficients[[cst] -> [a]] : cst >= 0 and 10a + cst >= 0 }",
   10602 	  "{ rat: [i] : 0 <= i <= 10 }" },
   10603 	{ "{ rat: coefficients[[cst] -> [a]] : FALSE }",
   10604 	  "{ rat: [i] }" },
   10605 	{ "{ rat: coefficients[[cst] -> [a]] }",
   10606 	  "{ rat: [i] : FALSE }" },
   10607 };
   10608 
   10609 /* Test the basic functionality of isl_basic_set_coefficients and
   10610  * isl_basic_set_solutions.
   10611  */
   10612 static int test_dual(isl_ctx *ctx)
   10613 {
   10614 	int i;
   10615 
   10616 	for (i = 0; i < ARRAY_SIZE(coef_tests); ++i) {
   10617 		int equal;
   10618 		isl_basic_set *bset1, *bset2;
   10619 
   10620 		bset1 = isl_basic_set_read_from_str(ctx, coef_tests[i].set);
   10621 		bset2 = isl_basic_set_read_from_str(ctx, coef_tests[i].dual);
   10622 		bset1 = isl_basic_set_coefficients(bset1);
   10623 		equal = isl_basic_set_is_equal(bset1, bset2);
   10624 		isl_basic_set_free(bset1);
   10625 		isl_basic_set_free(bset2);
   10626 		if (equal < 0)
   10627 			return -1;
   10628 		if (!equal)
   10629 			isl_die(ctx, isl_error_unknown,
   10630 				"incorrect dual", return -1);
   10631 	}
   10632 
   10633 	for (i = 0; i < ARRAY_SIZE(sol_tests); ++i) {
   10634 		int equal;
   10635 		isl_basic_set *bset1, *bset2;
   10636 
   10637 		bset1 = isl_basic_set_read_from_str(ctx, sol_tests[i].set);
   10638 		bset2 = isl_basic_set_read_from_str(ctx, sol_tests[i].dual);
   10639 		bset1 = isl_basic_set_solutions(bset1);
   10640 		equal = isl_basic_set_is_equal(bset1, bset2);
   10641 		isl_basic_set_free(bset1);
   10642 		isl_basic_set_free(bset2);
   10643 		if (equal < 0)
   10644 			return -1;
   10645 		if (!equal)
   10646 			isl_die(ctx, isl_error_unknown,
   10647 				"incorrect dual", return -1);
   10648 	}
   10649 
   10650 	return 0;
   10651 }
   10652 
   10653 struct {
   10654 	int scale_tile;
   10655 	int shift_point;
   10656 	const char *domain;
   10657 	const char *schedule;
   10658 	const char *sizes;
   10659 	const char *tile;
   10660 	const char *point;
   10661 } tile_tests[] = {
   10662 	{ 0, 0, "[n] -> { S[i,j] : 0 <= i,j < n }",
   10663 	  "[{ S[i,j] -> [i] }, { S[i,j] -> [j] }]",
   10664 	  "{ [32,32] }",
   10665 	  "[{ S[i,j] -> [floor(i/32)] }, { S[i,j] -> [floor(j/32)] }]",
   10666 	  "[{ S[i,j] -> [i] }, { S[i,j] -> [j] }]",
   10667 	},
   10668 	{ 1, 0, "[n] -> { S[i,j] : 0 <= i,j < n }",
   10669 	  "[{ S[i,j] -> [i] }, { S[i,j] -> [j] }]",
   10670 	  "{ [32,32] }",
   10671 	  "[{ S[i,j] -> [32*floor(i/32)] }, { S[i,j] -> [32*floor(j/32)] }]",
   10672 	  "[{ S[i,j] -> [i] }, { S[i,j] -> [j] }]",
   10673 	},
   10674 	{ 0, 1, "[n] -> { S[i,j] : 0 <= i,j < n }",
   10675 	  "[{ S[i,j] -> [i] }, { S[i,j] -> [j] }]",
   10676 	  "{ [32,32] }",
   10677 	  "[{ S[i,j] -> [floor(i/32)] }, { S[i,j] -> [floor(j/32)] }]",
   10678 	  "[{ S[i,j] -> [i%32] }, { S[i,j] -> [j%32] }]",
   10679 	},
   10680 	{ 1, 1, "[n] -> { S[i,j] : 0 <= i,j < n }",
   10681 	  "[{ S[i,j] -> [i] }, { S[i,j] -> [j] }]",
   10682 	  "{ [32,32] }",
   10683 	  "[{ S[i,j] -> [32*floor(i/32)] }, { S[i,j] -> [32*floor(j/32)] }]",
   10684 	  "[{ S[i,j] -> [i%32] }, { S[i,j] -> [j%32] }]",
   10685 	},
   10686 };
   10687 
   10688 /* Basic tiling tests.  Create a schedule tree with a domain and a band node,
   10689  * tile the band and then check if the tile and point bands have the
   10690  * expected partial schedule.
   10691  */
   10692 static int test_tile(isl_ctx *ctx)
   10693 {
   10694 	int i;
   10695 	int scale;
   10696 	int shift;
   10697 
   10698 	scale = isl_options_get_tile_scale_tile_loops(ctx);
   10699 	shift = isl_options_get_tile_shift_point_loops(ctx);
   10700 
   10701 	for (i = 0; i < ARRAY_SIZE(tile_tests); ++i) {
   10702 		int opt;
   10703 		int equal;
   10704 		const char *str;
   10705 		isl_union_set *domain;
   10706 		isl_multi_union_pw_aff *mupa, *mupa2;
   10707 		isl_schedule_node *node;
   10708 		isl_multi_val *sizes;
   10709 
   10710 		opt = tile_tests[i].scale_tile;
   10711 		isl_options_set_tile_scale_tile_loops(ctx, opt);
   10712 		opt = tile_tests[i].shift_point;
   10713 		isl_options_set_tile_shift_point_loops(ctx, opt);
   10714 
   10715 		str = tile_tests[i].domain;
   10716 		domain = isl_union_set_read_from_str(ctx, str);
   10717 		node = isl_schedule_node_from_domain(domain);
   10718 		node = isl_schedule_node_child(node, 0);
   10719 		str = tile_tests[i].schedule;
   10720 		mupa = isl_multi_union_pw_aff_read_from_str(ctx, str);
   10721 		node = isl_schedule_node_insert_partial_schedule(node, mupa);
   10722 		str = tile_tests[i].sizes;
   10723 		sizes = isl_multi_val_read_from_str(ctx, str);
   10724 		node = isl_schedule_node_band_tile(node, sizes);
   10725 
   10726 		str = tile_tests[i].tile;
   10727 		mupa = isl_multi_union_pw_aff_read_from_str(ctx, str);
   10728 		mupa2 = isl_schedule_node_band_get_partial_schedule(node);
   10729 		equal = isl_multi_union_pw_aff_plain_is_equal(mupa, mupa2);
   10730 		isl_multi_union_pw_aff_free(mupa);
   10731 		isl_multi_union_pw_aff_free(mupa2);
   10732 
   10733 		node = isl_schedule_node_child(node, 0);
   10734 
   10735 		str = tile_tests[i].point;
   10736 		mupa = isl_multi_union_pw_aff_read_from_str(ctx, str);
   10737 		mupa2 = isl_schedule_node_band_get_partial_schedule(node);
   10738 		if (equal >= 0 && equal)
   10739 			equal = isl_multi_union_pw_aff_plain_is_equal(mupa,
   10740 									mupa2);
   10741 		isl_multi_union_pw_aff_free(mupa);
   10742 		isl_multi_union_pw_aff_free(mupa2);
   10743 
   10744 		isl_schedule_node_free(node);
   10745 
   10746 		if (equal < 0)
   10747 			return -1;
   10748 		if (!equal)
   10749 			isl_die(ctx, isl_error_unknown,
   10750 				"unexpected result", return -1);
   10751 	}
   10752 
   10753 	isl_options_set_tile_scale_tile_loops(ctx, scale);
   10754 	isl_options_set_tile_shift_point_loops(ctx, shift);
   10755 
   10756 	return 0;
   10757 }
   10758 
   10759 /* Check that the domain hash of a space is equal to the hash
   10760  * of the domain of the space, both ignoring parameters.
   10761  */
   10762 static int test_domain_hash(isl_ctx *ctx)
   10763 {
   10764 	isl_map *map;
   10765 	isl_space *space;
   10766 	uint32_t hash1, hash2;
   10767 
   10768 	map = isl_map_read_from_str(ctx, "[n] -> { A[B[x] -> C[]] -> D[] }");
   10769 	space = isl_map_get_space(map);
   10770 	isl_map_free(map);
   10771 	hash1 = isl_space_get_tuple_domain_hash(space);
   10772 	space = isl_space_domain(space);
   10773 	hash2 = isl_space_get_tuple_hash(space);
   10774 	isl_space_free(space);
   10775 
   10776 	if (!space)
   10777 		return -1;
   10778 	if (hash1 != hash2)
   10779 		isl_die(ctx, isl_error_unknown,
   10780 			"domain hash not equal to hash of domain", return -1);
   10781 
   10782 	return 0;
   10783 }
   10784 
   10785 /* Check that a universe basic set that is not obviously equal to the universe
   10786  * is still recognized as being equal to the universe.
   10787  */
   10788 static int test_universe(isl_ctx *ctx)
   10789 {
   10790 	const char *s;
   10791 	isl_basic_set *bset;
   10792 	isl_bool is_univ;
   10793 
   10794 	s = "{ [] : exists x, y : 3y <= 2x and y >= -3 + 2x and 2y >= 2 - x }";
   10795 	bset = isl_basic_set_read_from_str(ctx, s);
   10796 	is_univ = isl_basic_set_is_universe(bset);
   10797 	isl_basic_set_free(bset);
   10798 
   10799 	if (is_univ < 0)
   10800 		return -1;
   10801 	if (!is_univ)
   10802 		isl_die(ctx, isl_error_unknown,
   10803 			"not recognized as universe set", return -1);
   10804 
   10805 	return 0;
   10806 }
   10807 
   10808 /* Sets for which chambers are computed and checked.
   10809  */
   10810 const char *chambers_tests[] = {
   10811 	"[A, B, C] -> { [x, y, z] : x >= 0 and y >= 0 and y <= A - x and "
   10812 				"z >= 0 and z <= C - y and z <= B - x - y }",
   10813 };
   10814 
   10815 /* Add the domain of "cell" to "cells".
   10816  */
   10817 static isl_stat add_cell(__isl_take isl_cell *cell, void *user)
   10818 {
   10819 	isl_basic_set_list **cells = user;
   10820 	isl_basic_set *dom;
   10821 
   10822 	dom = isl_cell_get_domain(cell);
   10823 	isl_cell_free(cell);
   10824 	*cells = isl_basic_set_list_add(*cells, dom);
   10825 
   10826 	return *cells ? isl_stat_ok : isl_stat_error;
   10827 }
   10828 
   10829 /* Check that the elements of "list" are pairwise disjoint.
   10830  */
   10831 static isl_stat check_pairwise_disjoint(__isl_keep isl_basic_set_list *list)
   10832 {
   10833 	int i, j;
   10834 	isl_size n;
   10835 
   10836 	n = isl_basic_set_list_n_basic_set(list);
   10837 	if (n < 0)
   10838 		return isl_stat_error;
   10839 
   10840 	for (i = 0; i < n; ++i) {
   10841 		isl_basic_set *bset_i;
   10842 
   10843 		bset_i = isl_basic_set_list_get_basic_set(list, i);
   10844 		for (j = i + 1; j < n; ++j) {
   10845 			isl_basic_set *bset_j;
   10846 			isl_bool disjoint;
   10847 
   10848 			bset_j = isl_basic_set_list_get_basic_set(list, j);
   10849 			disjoint = isl_basic_set_is_disjoint(bset_i, bset_j);
   10850 			isl_basic_set_free(bset_j);
   10851 			if (!disjoint)
   10852 				isl_die(isl_basic_set_list_get_ctx(list),
   10853 					isl_error_unknown, "not disjoint",
   10854 					break);
   10855 			if (disjoint < 0 || !disjoint)
   10856 				break;
   10857 		}
   10858 		isl_basic_set_free(bset_i);
   10859 		if (j < n)
   10860 			return isl_stat_error;
   10861 	}
   10862 
   10863 	return isl_stat_ok;
   10864 }
   10865 
   10866 /* Check that the chambers computed by isl_vertices_foreach_disjoint_cell
   10867  * are pairwise disjoint.
   10868  */
   10869 static int test_chambers(isl_ctx *ctx)
   10870 {
   10871 	int i;
   10872 
   10873 	for (i = 0; i < ARRAY_SIZE(chambers_tests); ++i) {
   10874 		isl_basic_set *bset;
   10875 		isl_vertices *vertices;
   10876 		isl_basic_set_list *cells;
   10877 		isl_stat ok;
   10878 
   10879 		bset = isl_basic_set_read_from_str(ctx, chambers_tests[i]);
   10880 		vertices = isl_basic_set_compute_vertices(bset);
   10881 		cells = isl_basic_set_list_alloc(ctx, 0);
   10882 		if (isl_vertices_foreach_disjoint_cell(vertices, &add_cell,
   10883 							&cells) < 0)
   10884 			cells = isl_basic_set_list_free(cells);
   10885 		ok = check_pairwise_disjoint(cells);
   10886 		isl_basic_set_list_free(cells);
   10887 		isl_vertices_free(vertices);
   10888 		isl_basic_set_free(bset);
   10889 
   10890 		if (ok < 0)
   10891 			return -1;
   10892 	}
   10893 
   10894 	return 0;
   10895 }
   10896 
   10897 struct {
   10898 	const char *name;
   10899 	int (*fn)(isl_ctx *ctx);
   10900 } tests [] = {
   10901 	{ "universe", &test_universe },
   10902 	{ "domain hash", &test_domain_hash },
   10903 	{ "dual", &test_dual },
   10904 	{ "dependence analysis", &test_flow },
   10905 	{ "val", &test_val },
   10906 	{ "compute divs", &test_compute_divs },
   10907 	{ "partial lexmin", &test_partial_lexmin },
   10908 	{ "simplify", &test_simplify },
   10909 	{ "curry", &test_curry },
   10910 	{ "piecewise multi affine expressions", &test_pw_multi_aff },
   10911 	{ "multi piecewise affine expressions", &test_multi_pw_aff },
   10912 	{ "conversion", &test_conversion },
   10913 	{ "list", &test_list },
   10914 	{ "align parameters", &test_align_parameters },
   10915 	{ "drop unused parameters", &test_drop_unused_parameters },
   10916 	{ "pullback", &test_pullback },
   10917 	{ "AST", &test_ast },
   10918 	{ "AST build", &test_ast_build },
   10919 	{ "AST generation", &test_ast_gen },
   10920 	{ "eliminate", &test_eliminate },
   10921 	{ "deltas_map", &test_deltas_map },
   10922 	{ "residue class", &test_residue_class },
   10923 	{ "div", &test_div },
   10924 	{ "slice", &test_slice },
   10925 	{ "sample", &test_sample },
   10926 	{ "empty projection", &test_empty_projection },
   10927 	{ "output", &test_output },
   10928 	{ "vertices", &test_vertices },
   10929 	{ "chambers", &test_chambers },
   10930 	{ "fixed", &test_fixed },
   10931 	{ "equal", &test_equal },
   10932 	{ "disjoint", &test_disjoint },
   10933 	{ "product", &test_product },
   10934 	{ "dim_max", &test_dim_max },
   10935 	{ "affine", &test_aff },
   10936 	{ "injective", &test_injective },
   10937 	{ "schedule (whole component)", &test_schedule_whole },
   10938 	{ "schedule (incremental)", &test_schedule_incremental },
   10939 	{ "schedule tree", &test_schedule_tree },
   10940 	{ "schedule tree prefix", &test_schedule_tree_prefix },
   10941 	{ "schedule tree grouping", &test_schedule_tree_group },
   10942 	{ "tile", &test_tile },
   10943 	{ "union map", &test_union_map },
   10944 	{ "union_pw", &test_union_pw },
   10945 	{ "locus", &test_locus },
   10946 	{ "eval", &test_eval },
   10947 	{ "parse", &test_parse },
   10948 	{ "single-valued", &test_sv },
   10949 	{ "recession cone", &test_recession_cone },
   10950 	{ "affine hull", &test_affine_hull },
   10951 	{ "simple_hull", &test_simple_hull },
   10952 	{ "box hull", &test_box_hull },
   10953 	{ "coalesce", &test_coalesce },
   10954 	{ "factorize", &test_factorize },
   10955 	{ "subset", &test_subset },
   10956 	{ "subtract", &test_subtract },
   10957 	{ "intersect", &test_intersect },
   10958 	{ "lexmin", &test_lexmin },
   10959 	{ "min", &test_min },
   10960 	{ "set lower bounds", &test_min_mpa },
   10961 	{ "gist", &test_gist },
   10962 	{ "piecewise quasi-polynomials", &test_pwqp },
   10963 	{ "lift", &test_lift },
   10964 	{ "bind parameters", &test_bind },
   10965 	{ "unbind parameters", &test_unbind },
   10966 	{ "bound", &test_bound },
   10967 	{ "get lists", &test_get_list },
   10968 	{ "union", &test_union },
   10969 	{ "split periods", &test_split_periods },
   10970 	{ "lexicographic order", &test_lex },
   10971 	{ "bijectivity", &test_bijective },
   10972 	{ "dataflow analysis", &test_dep },
   10973 	{ "reading", &test_read },
   10974 	{ "bounded", &test_bounded },
   10975 	{ "construction", &test_construction },
   10976 	{ "dimension manipulation", &test_dim },
   10977 	{ "map application", &test_application },
   10978 	{ "convex hull", &test_convex_hull },
   10979 	{ "transitive closure", &test_closure },
   10980 	{ "isl_bool", &test_isl_bool},
   10981 };
   10982 
   10983 int main(int argc, char **argv)
   10984 {
   10985 	int i;
   10986 	struct isl_ctx *ctx;
   10987 	struct isl_options *options;
   10988 
   10989 	options = isl_options_new_with_defaults();
   10990 	assert(options);
   10991 	argc = isl_options_parse(options, argc, argv, ISL_ARG_ALL);
   10992 
   10993 	ctx = isl_ctx_alloc_with_options(&isl_options_args, options);
   10994 	for (i = 0; i < ARRAY_SIZE(tests); ++i) {
   10995 		printf("%s\n", tests[i].name);
   10996 		if (tests[i].fn(ctx) < 0)
   10997 			goto error;
   10998 	}
   10999 	isl_ctx_free(ctx);
   11000 	return 0;
   11001 error:
   11002 	isl_ctx_free(ctx);
   11003 	return -1;
   11004 }
   11005