brintos

brintos / llvm-project-archived public Read only

0
0
Text · 328.9 KiB · 7048302 Raw
11045 lines · c
1/*2 * Copyright 2008-2009 Katholieke Universiteit Leuven3 * Copyright 2010      INRIA Saclay4 * Copyright 2012-2013 Ecole Normale Superieure5 * Copyright 2014      INRIA Rocquencourt6 * Copyright 2022      Cerebras Systems7 *8 * Use of this software is governed by the MIT license9 *10 * Written by Sven Verdoolaege, K.U.Leuven, Departement11 * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium12 * and INRIA Saclay - Ile-de-France, Parc Club Orsay Universite,13 * ZAC des vignes, 4 rue Jacques Monod, 91893 Orsay, France14 * and Ecole Normale Superieure, 45 rue d’Ulm, 75230 Paris, France15 * and Inria Paris - Rocquencourt, Domaine de Voluceau - Rocquencourt,16 * B.P. 105 - 78153 Le Chesnay, France17 * and Cerebras Systems, 1237 E Arques Ave, Sunnyvale, CA, USA18 */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 49static 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 66void 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 75int 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 95void 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 104static 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 */115static 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 expressions126 * that are used for testing printing and parsing.127 */128static 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 BASE145#define BASE multi_pw_aff146 147#include "check_reparse_templ.c"148#include "check_reparse_test_templ.c"149 150/* String descriptions that cannot be parsed151 * as multi piecewise affine expressions.152 */153static 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 expressions161 * that are used for testing printing and parsing.162 */163static 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};172 173#undef BASE174#define BASE pw_multi_aff175 176#include "check_reparse_templ.c"177#include "check_reparse_test_templ.c"178 179/* Test parsing of piecewise multi affine expressions by printing180 * the expressions and checking that parsing the output results181 * in the same expression.182 * Do this for an expression converted from a map with an output183 * dimension name that is equal to an automatically generated name, and184 * a set of expressions parsed from strings.185 */186static isl_stat test_parse_pma(isl_ctx *ctx)187{188	isl_map *map;189	isl_pw_multi_aff *pma;190 191	map = isl_map_read_from_str(ctx, "{ [a, a] -> [i1 = a + 1] }");192	pma = isl_pw_multi_aff_from_map(map);193	if (check_reparse_pw_multi_aff(ctx, pma) < 0)194		return isl_stat_error;195 196	if (check_reparse_pw_multi_aff_tests(ctx) < 0)197		return isl_stat_error;198 199	return isl_stat_ok;200}201 202/* String descriptions that cannot be parsed203 * as union piecewise multi affine expressions.204 */205static const char *parse_union_pw_multi_aff_fail_tests[] = {206	"{ [a] -> [b] : b = a }",207	"{ [a] -> [b = a] : b >= 0 }",208};209 210#undef BASE211#define BASE union_pw_multi_aff212 213#include "check_parse_fail_test_templ.c"214 215/* Test parsing of union piecewise multi affine expressions.216 *217 * In particular, check some cases where parsing is supposed to fail.218 */219static isl_stat test_parse_upma(isl_ctx *ctx)220{221	if (check_parse_union_pw_multi_aff_fail_tests(ctx) < 0)222		return isl_stat_error;223 224	return isl_stat_ok;225}226 227/* Test parsing of multi piecewise affine expressions by printing228 * the expressions and checking that parsing the output results229 * in the same expression.230 * Do this for a couple of manually constructed expressions,231 * an expression converted from a map with an output dimension name232 * that is equal to an automatically generated name, and233 * a set of expressions parsed from strings.234 *235 * Additionally, check some cases where parsing is supposed to fail.236 */237static int test_parse_mpa(isl_ctx *ctx)238{239	isl_space *space;240	isl_set *dom;241	isl_map *map;242	isl_pw_multi_aff *pma;243	isl_multi_pw_aff *mpa;244	isl_stat r;245 246	space = isl_space_set_alloc(ctx, 0, 0);247	space = isl_space_set_tuple_name(space, isl_dim_set, "A");248	mpa = isl_multi_pw_aff_zero(space);249	r = check_reparse_multi_pw_aff(ctx, mpa);250	if (r < 0)251		return -1;252 253	space = isl_space_set_alloc(ctx, 1, 0);254	space = isl_space_set_dim_name(space, isl_dim_param, 0, "N");255	space = isl_space_set_tuple_name(space, isl_dim_set, "A");256	dom = isl_set_universe(isl_space_params(isl_space_copy(space)));257	dom = isl_set_lower_bound_si(dom, isl_dim_param, 0, 5);258	mpa = isl_multi_pw_aff_zero(space);259	mpa = isl_multi_pw_aff_intersect_domain(mpa, dom);260	r = check_reparse_multi_pw_aff(ctx, mpa);261	if (r < 0)262		return -1;263 264	map = isl_map_read_from_str(ctx, "{ [a, a] -> [i1 = a + 1] }");265	pma = isl_pw_multi_aff_from_map(map);266	mpa = isl_multi_pw_aff_from_pw_multi_aff(pma);267	if (check_reparse_multi_pw_aff(ctx, mpa) < 0)268		return -1;269 270	if (check_reparse_multi_pw_aff_tests(ctx) < 0)271		return -1;272	if (check_parse_multi_pw_aff_fail_tests(ctx) < 0)273		return -1;274 275	return 0;276}277 278/* String descriptions of multi union piecewise affine expressions279 * that are used for testing printing and parsing.280 */281static const char *reparse_multi_union_pw_aff_tests[] = {282	"[]",283	"A[]",284	"A[B[] -> C[]]",285	"(A[] : { S[x] : x > 0; T[y] : y >= 0 })",286	"(A[] : { })",287	"[N] -> (A[] : { })",288	"[N] -> (A[] : { : N >= 0 })",289	"[N] -> (A[] : { S[x] : x > N; T[y] : y >= 0 })",290	"(A[] : [N] -> { S[x] : x > N; T[y] : y >= 0 })",291	"A[{ S[x] -> [x + 1]; T[x] -> [x] }]",292	"(A[{ S[x] -> [x + 1]; T[x] -> [x] }] : "293		"{ S[x] : x > 0; T[y] : y >= 0 })",294};295 296#undef BASE297#define BASE multi_union_pw_aff298 299#include "check_reparse_templ.c"300#include "check_reparse_test_templ.c"301 302/* Test parsing of multi union piecewise affine expressions by printing303 * the expressions and checking that parsing the output results304 * in the same expression.305 * Do this for a couple of manually constructed expressions and306 * a set of expressions parsed from strings.307 */308static int test_parse_mupa(isl_ctx *ctx)309{310	isl_space *space;311	isl_multi_union_pw_aff *mupa;312	isl_set *dom;313	isl_union_set *uset;314	isl_stat r;315 316	space = isl_space_set_alloc(ctx, 0, 0);317	space = isl_space_set_tuple_name(space, isl_dim_set, "A");318	mupa = isl_multi_union_pw_aff_zero(space);319	r = check_reparse_multi_union_pw_aff(ctx, mupa);320	if (r < 0)321		return -1;322 323	space = isl_space_set_alloc(ctx, 1, 0);324	space = isl_space_set_dim_name(space, isl_dim_param, 0, "N");325	space = isl_space_set_tuple_name(space, isl_dim_set, "A");326	dom = isl_set_universe(space);327	dom = isl_set_lower_bound_si(dom, isl_dim_param, 0, 5);328	uset = isl_union_set_from_set(dom);329	space = isl_space_set_alloc(ctx, 1, 0);330	space = isl_space_set_dim_name(space, isl_dim_param, 0, "N");331	space = isl_space_set_tuple_name(space, isl_dim_set, "B");332	mupa = isl_multi_union_pw_aff_zero(space);333	mupa = isl_multi_union_pw_aff_intersect_domain(mupa, uset);334	r = check_reparse_multi_union_pw_aff(ctx, mupa);335	if (r < 0)336		return -1;337 338	if (check_reparse_multi_union_pw_aff_tests(ctx) < 0)339		return -1;340 341	return 0;342}343 344/* Test parsing of multi expressions.345 */346static int test_parse_multi(isl_ctx *ctx)347{348	if (test_parse_mpa(ctx) < 0)349		return -1;350	if (test_parse_mupa(ctx) < 0)351		return -1;352 353	return 0;354}355 356/* Pairs of binary relation representations that should represent357 * the same binary relations.358 */359struct {360	const char *map1;361	const char *map2;362} parse_map_equal_tests[] = {363	{ "{ [x,y]  : [([x/2]+y)/3] >= 1 }",364	  "{ [x, y] : 2y >= 6 - x }" },365	{ "{ [x,y] : x <= min(y, 2*y+3) }",366	  "{ [x,y] : x <= y, 2*y + 3 }" },367	{ "{ [x,y] : x >= min(y, 2*y+3) }",368	  "{ [x, y] : (y <= x and y >= -3) or (2y <= -3 + x and y <= -4) }" },369	{ "[n] -> { [c1] : c1>=0 and c1<=floord(n-4,3) }",370	  "[n] -> { [c1] : c1 >= 0 and 3c1 <= -4 + n }" },371	{ "{ [i,j] -> [i] : i < j; [i,j] -> [j] : j <= i }",372	  "{ [i,j] -> [min(i,j)] }" },373	{ "{ [i,j] : i != j }",374	  "{ [i,j] : i < j or i > j }" },375	{ "{ [i,j] : (i+1)*2 >= j }",376	  "{ [i, j] : j <= 2 + 2i }" },377	{ "{ [i] -> [i > 0 ? 4 : 5] }",378	  "{ [i] -> [5] : i <= 0; [i] -> [4] : i >= 1 }" },379	{ "[N=2,M] -> { [i=[(M+N)/4]] }",380	  "[N, M] -> { [i] : N = 2 and 4i <= 2 + M and 4i >= -1 + M }" },381	{ "{ [x] : x >= 0 }",382	  "{ [x] : x-0 >= 0 }" },383	{ "{ [i] : ((i > 10)) }",384	  "{ [i] : i >= 11 }" },385	{ "{ [i] -> [0] }",386	  "{ [i] -> [0 * i] }" },387	{ "{ [a] -> [b] : (not false) }",388	  "{ [a] -> [b] : true }" },389	{ "{ [i] : i/2 <= 5 }",390	  "{ [i] : i <= 10 }" },391	{ "{Sym=[n] [i] : i <= n }",392	  "[n] -> { [i] : i <= n }" },393	{ "{ [*] }",394	  "{ [a] }" },395	{ "{ [i] : 2*floor(i/2) = i }",396	  "{ [i] : exists a : i = 2 a }" },397	{ "{ [a] -> [b] : a = 5 implies b = 5 }",398	  "{ [a] -> [b] : a != 5 or b = 5 }" },399	{ "{ [a] -> [a - 1 : a > 0] }",400	  "{ [a] -> [a - 1] : a > 0 }" },401	{ "{ [a] -> [a - 1 : a > 0; a : a <= 0] }",402	  "{ [a] -> [a - 1] : a > 0; [a] -> [a] : a <= 0 }" },403	{ "{ [a] -> [(a) * 2 : a >= 0; 0 : a < 0] }",404	  "{ [a] -> [2a] : a >= 0; [a] -> [0] : a < 0 }" },405	{ "{ [a] -> [(a * 2) : a >= 0; 0 : a < 0] }",406	  "{ [a] -> [2a] : a >= 0; [a] -> [0] : a < 0 }" },407	{ "{ [a] -> [(a * 2 : a >= 0); 0 : a < 0] }",408	  "{ [a] -> [2a] : a >= 0; [a] -> [0] : a < 0 }" },409	{ "{ [a] -> [(a * 2 : a >= 0; 0 : a < 0)] }",410	  "{ [a] -> [2a] : a >= 0; [a] -> [0] : a < 0 }" },411	{ "{ [a,b] -> [i,j] : a,b << i,j }",412	  "{ [a,b] -> [i,j] : a < i or (a = i and b < j) }" },413	{ "{ [a,b] -> [i,j] : a,b <<= i,j }",414	  "{ [a,b] -> [i,j] : a < i or (a = i and b <= j) }" },415	{ "{ [a,b] -> [i,j] : a,b >> i,j }",416	  "{ [a,b] -> [i,j] : a > i or (a = i and b > j) }" },417	{ "{ [a,b] -> [i,j] : a,b >>= i,j }",418	  "{ [a,b] -> [i,j] : a > i or (a = i and b >= j) }" },419	{ "{ [n] -> [i] : exists (a, b, c: 8b <= i - 32a and "420			    "8b >= -7 + i - 32 a and b >= 0 and b <= 3 and "421			    "8c < n - 32a and i < n and c >= 0 and "422			    "c <= 3 and c >= -4a) }",423	  "{ [n] -> [i] : 0 <= i < n }" },424	{ "{ [x] -> [] : exists (a, b: 0 <= a <= 1 and 0 <= b <= 3 and "425			    "2b <= x - 8a and 2b >= -1 + x - 8a) }",426	  "{ [x] -> [] : 0 <= x <= 15 }" },427	{ "{ [x] -> [x] : }",428	  "{ [x] -> [x] }" },429	{ "{ [x=4:5] -> [x + 1] }",430	  "{ [x] -> [x + 1] : 4 <= x <= 5 }" },431	{ "{ [x=4:5] -> [x + 1 : x + 1] }",432	  "{ [x=4:5] -> [x + 1] }" },433	{ "{ [x] -> [x - 1 : x + 1] }",434	  "{ [x] -> [y] : x - 1 <= y <= x + 1 }" },435	{ "{ [x=4:] -> [x + 1] }",436	  "{ [x] -> [x + 1] : 4 <= x }" },437	{ "{ [x=:5] -> [x + 1] }",438	  "{ [x] -> [x + 1] : x <= 5 }" },439	{ "{ [x=:] -> [x + 1] }",440	  "{ [x] -> [x + 1] }" },441	{ "{ [:] -> [:] }",442	  "{ [x] -> [y] }" },443	{ "{ [x, x//4] }",444	  "{ [x, floor(x/4)] }" },445	{ "{ [10//4] }",446	  "{ [2] }" },447	{ "{ [-1//4] }",448	  "{ [-1] }" },449	{ "{ [0-1//4] }",450	  "{ [0] }" },451	{ "{ [- 1//4] }",452	  "{ [-1] }" },453	{ "{ [0 - 1//4] }",454	  "{ [0] }" },455	{ "{ [0--1//4] }",456	  "{ [1] }" },457	{ "{ [0 - -1//4] }",458	  "{ [1] }" },459	{ "{ [-2^2:2^2-1] }",460	  "{ [-4:3] }" },461	{ "{ [2*-2] }",462	  "{ [-4] }" },463	{ "{ [i,i*-2] }",464	  "{ [i,-2i] }" },465	{ "[a, b, c, d] -> { [max(a,b,c,d)] }",466	  "[a, b, c, d] -> { [a] : b < a and c < a and d < a; "467		"[b] : b >= a and c < b and d < b; "468		"[c] : c >= a and c >= b and d < c; "469		"[d] : d >= a and d >= b and d >= c }" },470	{ "[a, b, c, d] -> { [min(a,b,c,d)] }",471	  "[a, b, c, d] -> { [a] : b >= a and c >= a and d >= a; "472		"[b] : b < a and c >= b and d >= b; "473		"[c] : c < b and c < a and d >= c; "474		"[d] : d < c and d < b and d < a }" },475};476 477int test_parse(struct isl_ctx *ctx)478{479	int i;480	isl_map *map, *map2;481	const char *str, *str2;482 483	if (test_parse_multi_val(ctx, "{ A[B[2] -> C[5, 7]] }") < 0)484		return -1;485	if (test_parse_multi_val(ctx, "[n] -> { [2] }") < 0)486		return -1;487	if (test_parse_multi_val(ctx, "{ A[4, infty, NaN, -1/2, 2/3] }") < 0)488		return -1;489	if (test_parse_multi(ctx) < 0)490		return -1;491	if (test_parse_pma(ctx) < 0)492		return -1;493	if (test_parse_upma(ctx) < 0)494		return -1;495 496	str = "{ [i] -> [-i] }";497	map = isl_map_read_from_str(ctx, str);498	assert(map);499	isl_map_free(map);500 501	str = "{ A[i] -> L[([i/3])] }";502	map = isl_map_read_from_str(ctx, str);503	assert(map);504	isl_map_free(map);505 506	test_parse_map(ctx, "{[[s] -> A[i]] -> [[s+1] -> A[i]]}");507	test_parse_map(ctx, "{ [p1, y1, y2] -> [2, y1, y2] : "508				"p1 = 1 && (y1 <= y2 || y2 = 0) }");509 510	for (i = 0; i < ARRAY_SIZE(parse_map_equal_tests); ++i) {511		str = parse_map_equal_tests[i].map1;512		str2 = parse_map_equal_tests[i].map2;513		if (test_parse_map_equal(ctx, str, str2) < 0)514			return -1;515	}516 517	str = "{[new,old] -> [new+1-2*[(new+1)/2],old+1-2*[(old+1)/2]]}";518	map = isl_map_read_from_str(ctx, str);519	str = "{ [new, old] -> [o0, o1] : "520	       "exists (e0 = [(-1 - new + o0)/2], e1 = [(-1 - old + o1)/2]: "521	       "2e0 = -1 - new + o0 and 2e1 = -1 - old + o1 and o0 >= 0 and "522	       "o0 <= 1 and o1 >= 0 and o1 <= 1) }";523	map2 = isl_map_read_from_str(ctx, str);524	assert(isl_map_is_equal(map, map2));525	isl_map_free(map);526	isl_map_free(map2);527 528	str = "{[new,old] -> [new+1-2*[(new+1)/2],old+1-2*[(old+1)/2]]}";529	map = isl_map_read_from_str(ctx, str);530	str = "{[new,old] -> [(new+1)%2,(old+1)%2]}";531	map2 = isl_map_read_from_str(ctx, str);532	assert(isl_map_is_equal(map, map2));533	isl_map_free(map);534	isl_map_free(map2);535 536	test_parse_pwqp(ctx, "{ [i] -> i + [ (i + [i/3])/2 ] }");537	test_parse_map(ctx, "{ S1[i] -> [([i/10]),i%10] : 0 <= i <= 45 }");538	test_parse_pwaff(ctx, "{ [i] -> [i + 1] : i > 0; [a] -> [a] : a < 0 }");539	test_parse_pwqp(ctx, "{ [x] -> ([(x)/2] * [(x)/3]) }");540	test_parse_pwaff(ctx, "{ [] -> [(100)] }");541 542	return 0;543}544 545static int test_read(isl_ctx *ctx)546{547	char *filename;548	FILE *input;549	isl_basic_set *bset1, *bset2;550	const char *str = "{[y]: Exists ( alpha : 2alpha = y)}";551	int equal;552 553	filename = get_filename(ctx, "set", "omega");554	assert(filename);555	input = fopen(filename, "r");556	assert(input);557 558	bset1 = isl_basic_set_read_from_file(ctx, input);559	bset2 = isl_basic_set_read_from_str(ctx, str);560 561	equal = isl_basic_set_is_equal(bset1, bset2);562 563	isl_basic_set_free(bset1);564	isl_basic_set_free(bset2);565	free(filename);566 567	fclose(input);568 569	if (equal < 0)570		return -1;571	if (!equal)572		isl_die(ctx, isl_error_unknown,573			"read sets not equal", return -1);574 575	return 0;576}577 578static int test_bounded(isl_ctx *ctx)579{580	isl_set *set;581	isl_bool bounded;582 583	set = isl_set_read_from_str(ctx, "[n] -> {[i] : 0 <= i <= n }");584	bounded = isl_set_is_bounded(set);585	isl_set_free(set);586 587	if (bounded < 0)588		return -1;589	if (!bounded)590		isl_die(ctx, isl_error_unknown,591			"set not considered bounded", return -1);592 593	set = isl_set_read_from_str(ctx, "{[n, i] : 0 <= i <= n }");594	bounded = isl_set_is_bounded(set);595	assert(!bounded);596	isl_set_free(set);597 598	if (bounded < 0)599		return -1;600	if (bounded)601		isl_die(ctx, isl_error_unknown,602			"set considered bounded", return -1);603 604	set = isl_set_read_from_str(ctx, "[n] -> {[i] : i <= n }");605	bounded = isl_set_is_bounded(set);606	isl_set_free(set);607 608	if (bounded < 0)609		return -1;610	if (bounded)611		isl_die(ctx, isl_error_unknown,612			"set considered bounded", return -1);613 614	return 0;615}616 617/* Construct the basic set { [i] : 5 <= i <= N } */618static int test_construction_1(isl_ctx *ctx)619{620	isl_space *space;621	isl_local_space *ls;622	isl_basic_set *bset;623	isl_constraint *c;624 625	space = isl_space_set_alloc(ctx, 1, 1);626	bset = isl_basic_set_universe(isl_space_copy(space));627	ls = isl_local_space_from_space(space);628 629	c = isl_constraint_alloc_inequality(isl_local_space_copy(ls));630	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, -1);631	c = isl_constraint_set_coefficient_si(c, isl_dim_param, 0, 1);632	bset = isl_basic_set_add_constraint(bset, c);633 634	c = isl_constraint_alloc_inequality(isl_local_space_copy(ls));635	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, 1);636	c = isl_constraint_set_constant_si(c, -5);637	bset = isl_basic_set_add_constraint(bset, c);638 639	isl_local_space_free(ls);640	isl_basic_set_free(bset);641 642	return 0;643}644 645/* Construct the basic set { [x] : -100 <= x <= 100 }646 * using isl_basic_set_{lower,upper}_bound_val and647 * check that it is equal the same basic set parsed from a string.648 */649static int test_construction_2(isl_ctx *ctx)650{651	isl_bool equal;652	isl_val *v;653	isl_space *space;654	isl_basic_set *bset1, *bset2;655 656	v = isl_val_int_from_si(ctx, 100);657	space = isl_space_set_alloc(ctx, 0, 1);658	bset1 = isl_basic_set_universe(space);659	bset1 = isl_basic_set_upper_bound_val(bset1, isl_dim_set, 0,660						isl_val_copy(v));661	bset1 = isl_basic_set_lower_bound_val(bset1, isl_dim_set, 0,662						isl_val_neg(v));663	bset2 = isl_basic_set_read_from_str(ctx, "{ [x] : -100 <= x <= 100 }");664	equal = isl_basic_set_is_equal(bset1, bset2);665	isl_basic_set_free(bset1);666	isl_basic_set_free(bset2);667 668	if (equal < 0)669		return -1;670	if (!equal)671		isl_die(ctx, isl_error_unknown,672			"failed construction", return -1);673 674	return 0;675}676 677/* Basic tests for constructing basic sets.678 */679static int test_construction(isl_ctx *ctx)680{681	if (test_construction_1(ctx) < 0)682		return -1;683	if (test_construction_2(ctx) < 0)684		return -1;685	return 0;686}687 688static int test_dim(isl_ctx *ctx)689{690	const char *str;691	isl_map *map1, *map2;692	int equal;693 694	map1 = isl_map_read_from_str(ctx,695	    "[n] -> { [i] -> [j] : exists (a = [i/10] : i - 10a <= n ) }");696	map1 = isl_map_add_dims(map1, isl_dim_in, 1);697	map2 = isl_map_read_from_str(ctx,698	    "[n] -> { [i,k] -> [j] : exists (a = [i/10] : i - 10a <= n ) }");699	equal = isl_map_is_equal(map1, map2);700	isl_map_free(map2);701 702	map1 = isl_map_project_out(map1, isl_dim_in, 0, 1);703	map2 = isl_map_read_from_str(ctx, "[n] -> { [i] -> [j] : n >= 0 }");704	if (equal >= 0 && equal)705		equal = isl_map_is_equal(map1, map2);706 707	isl_map_free(map1);708	isl_map_free(map2);709 710	if (equal < 0)711		return -1;712	if (!equal)713		isl_die(ctx, isl_error_unknown,714			"unexpected result", return -1);715 716	str = "[n] -> { [i] -> [] : exists a : 0 <= i <= n and i = 2 a }";717	map1 = isl_map_read_from_str(ctx, str);718	str = "{ [i] -> [j] : exists a : 0 <= i <= j and i = 2 a }";719	map2 = isl_map_read_from_str(ctx, str);720	map1 = isl_map_move_dims(map1, isl_dim_out, 0, isl_dim_param, 0, 1);721	equal = isl_map_is_equal(map1, map2);722	isl_map_free(map1);723	isl_map_free(map2);724 725	if (equal < 0)726		return -1;727	if (!equal)728		isl_die(ctx, isl_error_unknown,729			"unexpected result", return -1);730 731	return 0;732}733 734#undef BASE735#define BASE	multi_val736#include "isl_test_plain_equal_templ.c"737 738#undef BASE739#define BASE	multi_aff740#include "isl_test_plain_equal_templ.c"741 742/* Check that "val" is equal to the value described by "str".743 * If "str" is "NaN", then check for a NaN value explicitly.744 */745static isl_stat val_check_equal(__isl_keep isl_val *val, const char *str)746{747	isl_bool ok, is_nan;748	isl_ctx *ctx;749	isl_val *res;750 751	if (!val)752		return isl_stat_error;753 754	ctx = isl_val_get_ctx(val);755	res = isl_val_read_from_str(ctx, str);756	is_nan = isl_val_is_nan(res);757	if (is_nan < 0)758		ok = isl_bool_error;759	else if (is_nan)760		ok = isl_val_is_nan(val);761	else762		ok = isl_val_eq(val, res);763	isl_val_free(res);764	if (ok < 0)765		return isl_stat_error;766	if (!ok)767		isl_die(ctx, isl_error_unknown,768			"unexpected result", return isl_stat_error);769	return isl_stat_ok;770}771 772struct {773	__isl_give isl_val *(*op)(__isl_take isl_val *v);774	const char *arg;775	const char *res;776} val_un_tests[] = {777	{ &isl_val_neg, "0", "0" },778	{ &isl_val_abs, "0", "0" },779	{ &isl_val_pow2, "0", "1" },780	{ &isl_val_floor, "0", "0" },781	{ &isl_val_ceil, "0", "0" },782	{ &isl_val_neg, "1", "-1" },783	{ &isl_val_neg, "-1", "1" },784	{ &isl_val_neg, "1/2", "-1/2" },785	{ &isl_val_neg, "-1/2", "1/2" },786	{ &isl_val_neg, "infty", "-infty" },787	{ &isl_val_neg, "-infty", "infty" },788	{ &isl_val_neg, "NaN", "NaN" },789	{ &isl_val_abs, "1", "1" },790	{ &isl_val_abs, "-1", "1" },791	{ &isl_val_abs, "1/2", "1/2" },792	{ &isl_val_abs, "-1/2", "1/2" },793	{ &isl_val_abs, "infty", "infty" },794	{ &isl_val_abs, "-infty", "infty" },795	{ &isl_val_abs, "NaN", "NaN" },796	{ &isl_val_floor, "1", "1" },797	{ &isl_val_floor, "-1", "-1" },798	{ &isl_val_floor, "1/2", "0" },799	{ &isl_val_floor, "-1/2", "-1" },800	{ &isl_val_floor, "infty", "infty" },801	{ &isl_val_floor, "-infty", "-infty" },802	{ &isl_val_floor, "NaN", "NaN" },803	{ &isl_val_ceil, "1", "1" },804	{ &isl_val_ceil, "-1", "-1" },805	{ &isl_val_ceil, "1/2", "1" },806	{ &isl_val_ceil, "-1/2", "0" },807	{ &isl_val_ceil, "infty", "infty" },808	{ &isl_val_ceil, "-infty", "-infty" },809	{ &isl_val_ceil, "NaN", "NaN" },810	{ &isl_val_pow2, "-3", "1/8" },811	{ &isl_val_pow2, "-1", "1/2" },812	{ &isl_val_pow2, "1", "2" },813	{ &isl_val_pow2, "2", "4" },814	{ &isl_val_pow2, "3", "8" },815	{ &isl_val_inv, "1", "1" },816	{ &isl_val_inv, "2", "1/2" },817	{ &isl_val_inv, "1/2", "2" },818	{ &isl_val_inv, "-2", "-1/2" },819	{ &isl_val_inv, "-1/2", "-2" },820	{ &isl_val_inv, "0", "NaN" },821	{ &isl_val_inv, "NaN", "NaN" },822	{ &isl_val_inv, "infty", "0" },823	{ &isl_val_inv, "-infty", "0" },824};825 826/* Perform some basic tests of unary operations on isl_val objects.827 */828static int test_un_val(isl_ctx *ctx)829{830	int i;831	isl_val *v;832	__isl_give isl_val *(*fn)(__isl_take isl_val *v);833 834	for (i = 0; i < ARRAY_SIZE(val_un_tests); ++i) {835		isl_stat r;836 837		v = isl_val_read_from_str(ctx, val_un_tests[i].arg);838		fn = val_un_tests[i].op;839		v = fn(v);840		r = val_check_equal(v, val_un_tests[i].res);841		isl_val_free(v);842		if (r < 0)843			return -1;844	}845 846	return 0;847}848 849struct {850	__isl_give isl_val *(*fn)(__isl_take isl_val *v1,851				__isl_take isl_val *v2);852} val_bin_op[] = {853	['+'] = { &isl_val_add },854	['-'] = { &isl_val_sub },855	['*'] = { &isl_val_mul },856	['/'] = { &isl_val_div },857	['g'] = { &isl_val_gcd },858	['m'] = { &isl_val_min },859	['M'] = { &isl_val_max },860};861 862struct {863	const char *arg1;864	unsigned char op;865	const char *arg2;866	const char *res;867} val_bin_tests[] = {868	{ "0", '+', "0", "0" },869	{ "1", '+', "0", "1" },870	{ "1", '+', "1", "2" },871	{ "1", '-', "1", "0" },872	{ "1", '*', "1", "1" },873	{ "1", '/', "1", "1" },874	{ "2", '*', "3", "6" },875	{ "2", '*', "1/2", "1" },876	{ "2", '*', "1/3", "2/3" },877	{ "2/3", '*', "3/5", "2/5" },878	{ "2/3", '*', "7/5", "14/15" },879	{ "2", '/', "1/2", "4" },880	{ "-2", '/', "-1/2", "4" },881	{ "-2", '/', "1/2", "-4" },882	{ "2", '/', "-1/2", "-4" },883	{ "2", '/', "2", "1" },884	{ "2", '/', "3", "2/3" },885	{ "2/3", '/', "5/3", "2/5" },886	{ "2/3", '/', "5/7", "14/15" },887	{ "0", '/', "0", "NaN" },888	{ "42", '/', "0", "NaN" },889	{ "-42", '/', "0", "NaN" },890	{ "infty", '/', "0", "NaN" },891	{ "-infty", '/', "0", "NaN" },892	{ "NaN", '/', "0", "NaN" },893	{ "0", '/', "NaN", "NaN" },894	{ "42", '/', "NaN", "NaN" },895	{ "-42", '/', "NaN", "NaN" },896	{ "infty", '/', "NaN", "NaN" },897	{ "-infty", '/', "NaN", "NaN" },898	{ "NaN", '/', "NaN", "NaN" },899	{ "0", '/', "infty", "0" },900	{ "42", '/', "infty", "0" },901	{ "-42", '/', "infty", "0" },902	{ "infty", '/', "infty", "NaN" },903	{ "-infty", '/', "infty", "NaN" },904	{ "NaN", '/', "infty", "NaN" },905	{ "0", '/', "-infty", "0" },906	{ "42", '/', "-infty", "0" },907	{ "-42", '/', "-infty", "0" },908	{ "infty", '/', "-infty", "NaN" },909	{ "-infty", '/', "-infty", "NaN" },910	{ "NaN", '/', "-infty", "NaN" },911	{ "1", '-', "1/3", "2/3" },912	{ "1/3", '+', "1/2", "5/6" },913	{ "1/2", '+', "1/2", "1" },914	{ "3/4", '-', "1/4", "1/2" },915	{ "1/2", '-', "1/3", "1/6" },916	{ "infty", '+', "42", "infty" },917	{ "infty", '+', "infty", "infty" },918	{ "42", '+', "infty", "infty" },919	{ "infty", '-', "infty", "NaN" },920	{ "infty", '*', "infty", "infty" },921	{ "infty", '*', "-infty", "-infty" },922	{ "-infty", '*', "infty", "-infty" },923	{ "-infty", '*', "-infty", "infty" },924	{ "0", '*', "infty", "NaN" },925	{ "1", '*', "infty", "infty" },926	{ "infty", '*', "0", "NaN" },927	{ "infty", '*', "42", "infty" },928	{ "42", '-', "infty", "-infty" },929	{ "infty", '+', "-infty", "NaN" },930	{ "4", 'g', "6", "2" },931	{ "5", 'g', "6", "1" },932	{ "42", 'm', "3", "3" },933	{ "42", 'M', "3", "42" },934	{ "3", 'm', "42", "3" },935	{ "3", 'M', "42", "42" },936	{ "42", 'm', "infty", "42" },937	{ "42", 'M', "infty", "infty" },938	{ "42", 'm', "-infty", "-infty" },939	{ "42", 'M', "-infty", "42" },940	{ "42", 'm', "NaN", "NaN" },941	{ "42", 'M', "NaN", "NaN" },942	{ "infty", 'm', "-infty", "-infty" },943	{ "infty", 'M', "-infty", "infty" },944};945 946/* Perform some basic tests of binary operations on isl_val objects.947 */948static int test_bin_val(isl_ctx *ctx)949{950	int i;951	isl_val *v1, *v2, *res;952	__isl_give isl_val *(*fn)(__isl_take isl_val *v1,953				__isl_take isl_val *v2);954	int ok;955 956	for (i = 0; i < ARRAY_SIZE(val_bin_tests); ++i) {957		v1 = isl_val_read_from_str(ctx, val_bin_tests[i].arg1);958		v2 = isl_val_read_from_str(ctx, val_bin_tests[i].arg2);959		res = isl_val_read_from_str(ctx, val_bin_tests[i].res);960		fn = val_bin_op[val_bin_tests[i].op].fn;961		v1 = fn(v1, v2);962		if (isl_val_is_nan(res))963			ok = isl_val_is_nan(v1);964		else965			ok = isl_val_eq(v1, res);966		isl_val_free(v1);967		isl_val_free(res);968		if (ok < 0)969			return -1;970		if (!ok)971			isl_die(ctx, isl_error_unknown,972				"unexpected result", return -1);973	}974 975	return 0;976}977 978/* Perform some basic tests on isl_val objects.979 */980static int test_val(isl_ctx *ctx)981{982	if (test_un_val(ctx) < 0)983		return -1;984	if (test_bin_val(ctx) < 0)985		return -1;986	return 0;987}988 989/* Sets described using existentially quantified variables that990 * can also be described without.991 */992static const char *elimination_tests[] = {993	"{ [i,j] : 2 * [i/2] + 3 * [j/4] <= 10 and 2 i = j }",994	"{ [m, w] : exists a : w - 2m - 5 <= 3a <= m - 2w }",995	"{ [m, w] : exists a : w >= 0 and a < m and -1 + w <= a <= 2m - w }",996};997 998/* Check that redundant existentially quantified variables are999 * getting removed.1000 */1001static int test_elimination(isl_ctx *ctx)1002{1003	int i;1004	isl_size n;1005	isl_basic_set *bset;1006 1007	for (i = 0; i < ARRAY_SIZE(elimination_tests); ++i) {1008		bset = isl_basic_set_read_from_str(ctx, elimination_tests[i]);1009		n = isl_basic_set_dim(bset, isl_dim_div);1010		isl_basic_set_free(bset);1011		if (n < 0)1012			return -1;1013		if (n != 0)1014			isl_die(ctx, isl_error_unknown,1015				"expecting no existentials", return -1);1016	}1017 1018	return 0;1019}1020 1021static int test_div(isl_ctx *ctx)1022{1023	const char *str;1024	int empty;1025	isl_space *space;1026	isl_set *set;1027	isl_local_space *ls;1028	struct isl_basic_set *bset;1029	struct isl_constraint *c;1030 1031	/* test 1 */1032	space = isl_space_set_alloc(ctx, 0, 3);1033	bset = isl_basic_set_universe(isl_space_copy(space));1034	ls = isl_local_space_from_space(space);1035 1036	c = isl_constraint_alloc_equality(isl_local_space_copy(ls));1037	c = isl_constraint_set_constant_si(c, -1);1038	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, 1);1039	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 1, 3);1040	bset = isl_basic_set_add_constraint(bset, c);1041 1042	c = isl_constraint_alloc_equality(isl_local_space_copy(ls));1043	c = isl_constraint_set_constant_si(c, 1);1044	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, -1);1045	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 2, 3);1046	bset = isl_basic_set_add_constraint(bset, c);1047 1048	bset = isl_basic_set_project_out(bset, isl_dim_set, 1, 2);1049 1050	assert(bset && bset->n_div == 1);1051	isl_local_space_free(ls);1052	isl_basic_set_free(bset);1053 1054	/* test 2 */1055	space = isl_space_set_alloc(ctx, 0, 3);1056	bset = isl_basic_set_universe(isl_space_copy(space));1057	ls = isl_local_space_from_space(space);1058 1059	c = isl_constraint_alloc_equality(isl_local_space_copy(ls));1060	c = isl_constraint_set_constant_si(c, 1);1061	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, -1);1062	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 1, 3);1063	bset = isl_basic_set_add_constraint(bset, c);1064 1065	c = isl_constraint_alloc_equality(isl_local_space_copy(ls));1066	c = isl_constraint_set_constant_si(c, -1);1067	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, 1);1068	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 2, 3);1069	bset = isl_basic_set_add_constraint(bset, c);1070 1071	bset = isl_basic_set_project_out(bset, isl_dim_set, 1, 2);1072 1073	assert(bset && bset->n_div == 1);1074	isl_local_space_free(ls);1075	isl_basic_set_free(bset);1076 1077	/* test 3 */1078	space = isl_space_set_alloc(ctx, 0, 3);1079	bset = isl_basic_set_universe(isl_space_copy(space));1080	ls = isl_local_space_from_space(space);1081 1082	c = isl_constraint_alloc_equality(isl_local_space_copy(ls));1083	c = isl_constraint_set_constant_si(c, 1);1084	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, -1);1085	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 1, 3);1086	bset = isl_basic_set_add_constraint(bset, c);1087 1088	c = isl_constraint_alloc_equality(isl_local_space_copy(ls));1089	c = isl_constraint_set_constant_si(c, -3);1090	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, 1);1091	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 2, 4);1092	bset = isl_basic_set_add_constraint(bset, c);1093 1094	bset = isl_basic_set_project_out(bset, isl_dim_set, 1, 2);1095 1096	assert(bset && bset->n_div == 1);1097	isl_local_space_free(ls);1098	isl_basic_set_free(bset);1099 1100	/* test 4 */1101	space = isl_space_set_alloc(ctx, 0, 3);1102	bset = isl_basic_set_universe(isl_space_copy(space));1103	ls = isl_local_space_from_space(space);1104 1105	c = isl_constraint_alloc_equality(isl_local_space_copy(ls));1106	c = isl_constraint_set_constant_si(c, 2);1107	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, -1);1108	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 1, 3);1109	bset = isl_basic_set_add_constraint(bset, c);1110 1111	c = isl_constraint_alloc_equality(isl_local_space_copy(ls));1112	c = isl_constraint_set_constant_si(c, -1);1113	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, 1);1114	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 2, 6);1115	bset = isl_basic_set_add_constraint(bset, c);1116 1117	bset = isl_basic_set_project_out(bset, isl_dim_set, 1, 2);1118 1119	assert(isl_basic_set_is_empty(bset));1120	isl_local_space_free(ls);1121	isl_basic_set_free(bset);1122 1123	/* test 5 */1124	space = isl_space_set_alloc(ctx, 0, 3);1125	bset = isl_basic_set_universe(isl_space_copy(space));1126	ls = isl_local_space_from_space(space);1127 1128	c = isl_constraint_alloc_equality(isl_local_space_copy(ls));1129	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, -1);1130	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 2, 3);1131	bset = isl_basic_set_add_constraint(bset, c);1132 1133	c = isl_constraint_alloc_equality(isl_local_space_copy(ls));1134	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, 1);1135	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 1, -3);1136	bset = isl_basic_set_add_constraint(bset, c);1137 1138	bset = isl_basic_set_project_out(bset, isl_dim_set, 2, 1);1139 1140	assert(bset && bset->n_div == 0);1141	isl_basic_set_free(bset);1142	isl_local_space_free(ls);1143 1144	/* test 6 */1145	space = isl_space_set_alloc(ctx, 0, 3);1146	bset = isl_basic_set_universe(isl_space_copy(space));1147	ls = isl_local_space_from_space(space);1148 1149	c = isl_constraint_alloc_equality(isl_local_space_copy(ls));1150	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, -1);1151	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 2, 6);1152	bset = isl_basic_set_add_constraint(bset, c);1153 1154	c = isl_constraint_alloc_equality(isl_local_space_copy(ls));1155	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, 1);1156	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 1, -3);1157	bset = isl_basic_set_add_constraint(bset, c);1158 1159	bset = isl_basic_set_project_out(bset, isl_dim_set, 2, 1);1160 1161	assert(bset && bset->n_div == 1);1162	isl_basic_set_free(bset);1163	isl_local_space_free(ls);1164 1165	/* test 7 */1166	/* This test is a bit tricky.  We set up an equality1167	 *		a + 3b + 3c = 6 e01168	 * Normalization of divs creates _two_ divs1169	 *		a = 3 e01170	 *		c - b - e0 = 2 e11171	 * Afterwards e0 is removed again because it has coefficient -11172	 * and we end up with the original equality and div again.1173	 * Perhaps we can avoid the introduction of this temporary div.1174	 */1175	space = isl_space_set_alloc(ctx, 0, 4);1176	bset = isl_basic_set_universe(isl_space_copy(space));1177	ls = isl_local_space_from_space(space);1178 1179	c = isl_constraint_alloc_equality(isl_local_space_copy(ls));1180	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, -1);1181	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 1, -3);1182	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 2, -3);1183	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 3, 6);1184	bset = isl_basic_set_add_constraint(bset, c);1185 1186	bset = isl_basic_set_project_out(bset, isl_dim_set, 3, 1);1187 1188	/* Test disabled for now */1189	/*1190	assert(bset && bset->n_div == 1);1191	*/1192	isl_local_space_free(ls);1193	isl_basic_set_free(bset);1194 1195	/* test 8 */1196	space = isl_space_set_alloc(ctx, 0, 5);1197	bset = isl_basic_set_universe(isl_space_copy(space));1198	ls = isl_local_space_from_space(space);1199 1200	c = isl_constraint_alloc_equality(isl_local_space_copy(ls));1201	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, -1);1202	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 1, -3);1203	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 3, -3);1204	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 4, 6);1205	bset = isl_basic_set_add_constraint(bset, c);1206 1207	c = isl_constraint_alloc_equality(isl_local_space_copy(ls));1208	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, -1);1209	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 2, 1);1210	c = isl_constraint_set_constant_si(c, 1);1211	bset = isl_basic_set_add_constraint(bset, c);1212 1213	bset = isl_basic_set_project_out(bset, isl_dim_set, 4, 1);1214 1215	/* Test disabled for now */1216	/*1217	assert(bset && bset->n_div == 1);1218	*/1219	isl_local_space_free(ls);1220	isl_basic_set_free(bset);1221 1222	/* test 9 */1223	space = isl_space_set_alloc(ctx, 0, 4);1224	bset = isl_basic_set_universe(isl_space_copy(space));1225	ls = isl_local_space_from_space(space);1226 1227	c = isl_constraint_alloc_equality(isl_local_space_copy(ls));1228	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, 1);1229	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 1, -1);1230	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 2, -2);1231	bset = isl_basic_set_add_constraint(bset, c);1232 1233	c = isl_constraint_alloc_equality(isl_local_space_copy(ls));1234	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, -1);1235	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 3, 3);1236	c = isl_constraint_set_constant_si(c, 2);1237	bset = isl_basic_set_add_constraint(bset, c);1238 1239	bset = isl_basic_set_project_out(bset, isl_dim_set, 2, 2);1240 1241	bset = isl_basic_set_fix_si(bset, isl_dim_set, 0, 2);1242 1243	assert(!isl_basic_set_is_empty(bset));1244 1245	isl_local_space_free(ls);1246	isl_basic_set_free(bset);1247 1248	/* test 10 */1249	space = isl_space_set_alloc(ctx, 0, 3);1250	bset = isl_basic_set_universe(isl_space_copy(space));1251	ls = isl_local_space_from_space(space);1252 1253	c = isl_constraint_alloc_equality(isl_local_space_copy(ls));1254	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, 1);1255	c = isl_constraint_set_coefficient_si(c, isl_dim_set, 2, -2);1256	bset = isl_basic_set_add_constraint(bset, c);1257 1258	bset = isl_basic_set_project_out(bset, isl_dim_set, 2, 1);1259 1260	bset = isl_basic_set_fix_si(bset, isl_dim_set, 0, 2);1261 1262	isl_local_space_free(ls);1263	isl_basic_set_free(bset);1264 1265	str = "{ [i] : exists (e0, e1: 3e1 >= 1 + 2e0 and "1266	    "8e1 <= -1 + 5i - 5e0 and 2e1 >= 1 + 2i - 5e0) }";1267	set = isl_set_read_from_str(ctx, str);1268	set = isl_set_compute_divs(set);1269	isl_set_free(set);1270	if (!set)1271		return -1;1272 1273	if (test_elimination(ctx) < 0)1274		return -1;1275 1276	str = "{ [i,j,k] : 3 + i + 2j >= 0 and 2 * [(i+2j)/4] <= k }";1277	set = isl_set_read_from_str(ctx, str);1278	set = isl_set_remove_divs_involving_dims(set, isl_dim_set, 0, 2);1279	set = isl_set_fix_si(set, isl_dim_set, 2, -3);1280	empty = isl_set_is_empty(set);1281	isl_set_free(set);1282	if (empty < 0)1283		return -1;1284	if (!empty)1285		isl_die(ctx, isl_error_unknown,1286			"result not as accurate as expected", return -1);1287 1288	return 0;1289}1290 1291void test_application_case(struct isl_ctx *ctx, const char *name)1292{1293	char *filename;1294	FILE *input;1295	struct isl_basic_set *bset1, *bset2;1296	struct isl_basic_map *bmap;1297 1298	filename = get_filename(ctx, name, "omega");1299	assert(filename);1300	input = fopen(filename, "r");1301	assert(input);1302 1303	bset1 = isl_basic_set_read_from_file(ctx, input);1304	bmap = isl_basic_map_read_from_file(ctx, input);1305 1306	bset1 = isl_basic_set_apply(bset1, bmap);1307 1308	bset2 = isl_basic_set_read_from_file(ctx, input);1309 1310	assert(isl_basic_set_is_equal(bset1, bset2) == 1);1311 1312	isl_basic_set_free(bset1);1313	isl_basic_set_free(bset2);1314	free(filename);1315 1316	fclose(input);1317}1318 1319static int test_application(isl_ctx *ctx)1320{1321	test_application_case(ctx, "application");1322	test_application_case(ctx, "application2");1323 1324	return 0;1325}1326 1327void test_affine_hull_case(struct isl_ctx *ctx, const char *name)1328{1329	char *filename;1330	FILE *input;1331	struct isl_basic_set *bset1, *bset2;1332 1333	filename = get_filename(ctx, name, "polylib");1334	assert(filename);1335	input = fopen(filename, "r");1336	assert(input);1337 1338	bset1 = isl_basic_set_read_from_file(ctx, input);1339	bset2 = isl_basic_set_read_from_file(ctx, input);1340 1341	bset1 = isl_basic_set_affine_hull(bset1);1342 1343	assert(isl_basic_set_is_equal(bset1, bset2) == 1);1344 1345	isl_basic_set_free(bset1);1346	isl_basic_set_free(bset2);1347	free(filename);1348 1349	fclose(input);1350}1351 1352/* Pairs of sets and the corresponding expected results of1353 * isl_basic_set_recession_cone.1354 */1355struct {1356	const char *set;1357	const char *cone;1358} recession_cone_tests[] = {1359	{ "{ [i] : 0 <= i <= 10 }", "{ [0] }" },1360	{ "{ [i] : 0 <= i }", "{ [i] : 0 <= i }" },1361	{ "{ [i] : i <= 10 }", "{ [i] : i <= 0 }" },1362	{ "{ [i] : false }", "{ [i] : false }" },1363};1364 1365/* Perform some basic isl_basic_set_recession_cone tests.1366 */1367static int test_recession_cone(struct isl_ctx *ctx)1368{1369	int i;1370 1371	for (i = 0; i < ARRAY_SIZE(recession_cone_tests); ++i) {1372		const char *str;1373		isl_basic_set *bset;1374		isl_basic_set *cone, *expected;1375		isl_bool equal;1376 1377		str = recession_cone_tests[i].set;1378		bset = isl_basic_set_read_from_str(ctx, str);1379		str = recession_cone_tests[i].cone;1380		expected = isl_basic_set_read_from_str(ctx, str);1381		cone = isl_basic_set_recession_cone(bset);1382		equal = isl_basic_set_is_equal(cone, expected);1383		isl_basic_set_free(cone);1384		isl_basic_set_free(expected);1385		if (equal < 0)1386			return -1;1387		if (!equal)1388			isl_die(ctx, isl_error_unknown, "unexpected cone",1389				return -1);1390	}1391 1392	return 0;1393}1394 1395int test_affine_hull(struct isl_ctx *ctx)1396{1397	const char *str;1398	isl_set *set;1399	isl_basic_set *bset, *bset2;1400	isl_size n;1401	isl_bool subset;1402 1403	test_affine_hull_case(ctx, "affine2");1404	test_affine_hull_case(ctx, "affine");1405	test_affine_hull_case(ctx, "affine3");1406 1407	str = "[m] -> { [i0] : exists (e0, e1: e1 <= 1 + i0 and "1408			"m >= 3 and 4i0 <= 2 + m and e1 >= i0 and "1409			"e1 >= 0 and e1 <= 2 and e1 >= 1 + 2e0 and "1410			"2e1 <= 1 + m + 4e0 and 2e1 >= 2 - m + 4i0 - 4e0) }";1411	set = isl_set_read_from_str(ctx, str);1412	bset = isl_set_affine_hull(set);1413	n = isl_basic_set_dim(bset, isl_dim_div);1414	isl_basic_set_free(bset);1415	if (n < 0)1416		return -1;1417	if (n != 0)1418		isl_die(ctx, isl_error_unknown, "not expecting any divs",1419			return -1);1420 1421	/* Check that isl_map_affine_hull is not confused by1422	 * the reordering of divs in isl_map_align_divs.1423	 */1424	str = "{ [a, b, c, 0] : exists (e0 = [(b)/32], e1 = [(c)/32]: "1425				"32e0 = b and 32e1 = c); "1426		"[a, 0, c, 0] : exists (e0 = [(c)/32]: 32e0 = c) }";1427	set = isl_set_read_from_str(ctx, str);1428	bset = isl_set_affine_hull(set);1429	isl_basic_set_free(bset);1430	if (!bset)1431		return -1;1432 1433	str = "{ [a] : exists e0, e1, e2: 32e1 = 31 + 31a + 31e0 and "1434			"32e2 = 31 + 31e0 }";1435	set = isl_set_read_from_str(ctx, str);1436	bset = isl_set_affine_hull(set);1437	str = "{ [a] : exists e : a = 32 e }";1438	bset2 = isl_basic_set_read_from_str(ctx, str);1439	subset = isl_basic_set_is_subset(bset, bset2);1440	isl_basic_set_free(bset);1441	isl_basic_set_free(bset2);1442	if (subset < 0)1443		return -1;1444	if (!subset)1445		isl_die(ctx, isl_error_unknown, "not as accurate as expected",1446			return -1);1447 1448	return 0;1449}1450 1451/* Test a special case of isl_set_plain_unshifted_simple_hull1452 * where older versions of isl would include a redundant constraint1453 * in the result.1454 * Check that the result does not have any constraints.1455 */1456static isl_stat test_plain_unshifted_simple_hull_special(isl_ctx *ctx)1457{1458	const char *str;1459	isl_bool is_universe;1460	isl_set *set;1461	isl_basic_set *bset;1462 1463	str = "{[x, y] : x = 0 or 2*((x+y)//2) <= y + 2 }";1464	set = isl_set_read_from_str(ctx, str);1465	bset = isl_set_plain_unshifted_simple_hull(set);1466	is_universe = isl_basic_set_plain_is_universe(bset);1467	isl_basic_set_free(bset);1468 1469	if (is_universe < 0)1470		return isl_stat_error;1471	if (!is_universe)1472		isl_die(ctx, isl_error_unknown,1473			"hull should not have any constraints",1474			return isl_stat_error);1475 1476	return isl_stat_ok;1477}1478 1479/* Inputs for simple hull tests, consisting of1480 * the specific simple hull function, the input set and the expected result.1481 */1482struct {1483	__isl_give isl_basic_set *(*fn)(__isl_take isl_set *set);1484	const char *set;1485	const char *hull;1486} simple_hull_tests[] = {1487	{ &isl_set_plain_unshifted_simple_hull,1488	  "{ [i,j] : i >= 1 and j >= 1 or i >= 2 and j <= 10 }",1489	  "{ [i,j] : i >= 1 }" },1490	{ &isl_set_plain_unshifted_simple_hull,1491	  "{ [n,i,j,k] : (i mod 3 = 2 and j mod 4 = 2) or "1492		"(j mod 4 = 2 and k mod 6 = n) }",1493	  "{ [n,i,j,k] : j mod 4 = 2 }" },1494	{ &isl_set_unshifted_simple_hull,1495	  "{ [0,x,y] : x <= -1; [1,x,y] : x <= y <= -x; [2,x,y] : x <= 1 }",1496	  "{ [t,x,y] : 0 <= t <= 2 and x <= 1 }" },1497	{ &isl_set_simple_hull,1498	  "{ [a, b] : b <= 0 and "1499			"2*floor((-2*floor((b)/2))/5) >= a - floor((b)/2); "1500	    "[a, b] : a mod 2 = 0 }",1501	  "{ [a, b] }" },1502};1503 1504/* Basic tests for various simple hull functions.1505 */1506static int test_various_simple_hull(isl_ctx *ctx)1507{1508	int i;1509	isl_set *set;1510	isl_basic_set *hull, *expected;1511	isl_bool equal;1512 1513	for (i = 0; i < ARRAY_SIZE(simple_hull_tests); ++i) {1514		const char *str;1515		str = simple_hull_tests[i].set;1516		set = isl_set_read_from_str(ctx, str);1517		str = simple_hull_tests[i].hull;1518		expected = isl_basic_set_read_from_str(ctx, str);1519		hull = simple_hull_tests[i].fn(set);1520		equal = isl_basic_set_is_equal(hull, expected);1521		isl_basic_set_free(hull);1522		isl_basic_set_free(expected);1523		if (equal < 0)1524			return -1;1525		if (!equal)1526			isl_die(ctx, isl_error_unknown, "unexpected hull",1527				return -1);1528	}1529 1530	return 0;1531}1532 1533static int test_simple_hull(struct isl_ctx *ctx)1534{1535	const char *str;1536	isl_set *set;1537	isl_basic_set *bset;1538	isl_bool is_empty;1539 1540	str = "{ [x, y] : 3y <= 2x and y >= -2 + 2x and 2y >= 2 - x;"1541		"[y, x] : 3y <= 2x and y >= -2 + 2x and 2y >= 2 - x }";1542	set = isl_set_read_from_str(ctx, str);1543	bset = isl_set_simple_hull(set);1544	is_empty = isl_basic_set_is_empty(bset);1545	isl_basic_set_free(bset);1546 1547	if (is_empty == isl_bool_error)1548		return -1;1549 1550	if (is_empty == isl_bool_false)1551		isl_die(ctx, isl_error_unknown, "Empty set should be detected",1552			return -1);1553 1554	if (test_plain_unshifted_simple_hull_special(ctx) < 0)1555		return -1;1556	if (test_various_simple_hull(ctx) < 0)1557		return -1;1558 1559	return 0;1560}1561 1562/* Inputs for isl_set_get_simple_fixed_box_hull tests.1563 * "set" is the input set.1564 * "offset" is the expected box offset.1565 * "size" is the expected box size.1566 */1567static struct {1568	const char *set;1569	const char *offset;1570	const char *size;1571} box_hull_tests[] = {1572	{ "{ S[x, y] : 0 <= x, y < 10 }", "{ S[0, 0] }", "{ S[10, 10] }" },1573	{ "[N] -> { S[x, y] : N <= x, y < N + 10 }",1574	  "[N] -> { S[N, N] }", "{ S[10, 10] }" },1575	{ "{ S[x, y] : 0 <= x + y, x - y < 10 }",1576	  "{ S[0, -4] }", "{ S[10, 9] }" },1577	{ "{ [i=0:10] : exists (e0, e1: 3e1 >= 1 + 2e0 and "1578	    "8e1 <= -1 + 5i - 5e0 and 2e1 >= 1 + 2i - 5e0) }",1579	  "{ [3] }", "{ [8] }" },1580	{ "[N] -> { [w = 0:17] : exists (e0: w < 2N and "1581	    "-1 + w <= e0 <= w and 2e0 >= N + w and w <= 2e0 <= 15 + w) }",1582	  "[N] -> { [N] }", "{ [9] }" },1583};1584 1585/* Perform basic isl_set_get_simple_fixed_box_hull tests.1586 */1587static int test_box_hull(struct isl_ctx *ctx)1588{1589	int i;1590 1591	for (i = 0; i < ARRAY_SIZE(box_hull_tests); ++i) {1592		const char *str;1593		isl_stat r;1594		isl_set *set;1595		isl_multi_aff *offset;1596		isl_multi_val *size;1597		isl_fixed_box *box;1598 1599		set = isl_set_read_from_str(ctx, box_hull_tests[i].set);1600		box = isl_set_get_simple_fixed_box_hull(set);1601		offset = isl_fixed_box_get_offset(box);1602		size = isl_fixed_box_get_size(box);1603		str = box_hull_tests[i].offset;1604		r = multi_aff_check_plain_equal(offset, str);1605		str = box_hull_tests[i].size;1606		if (r >= 0)1607			r = multi_val_check_plain_equal(size, str);1608		isl_multi_aff_free(offset);1609		isl_multi_val_free(size);1610		isl_fixed_box_free(box);1611		isl_set_free(set);1612		if (r < 0)1613			return -1;1614	}1615 1616	return 0;1617}1618 1619void test_convex_hull_case(struct isl_ctx *ctx, const char *name)1620{1621	char *filename;1622	FILE *input;1623	struct isl_basic_set *bset1, *bset2;1624	struct isl_set *set;1625 1626	filename = get_filename(ctx, name, "polylib");1627	assert(filename);1628	input = fopen(filename, "r");1629	assert(input);1630 1631	bset1 = isl_basic_set_read_from_file(ctx, input);1632	bset2 = isl_basic_set_read_from_file(ctx, input);1633 1634	set = isl_basic_set_union(bset1, bset2);1635	bset1 = isl_set_convex_hull(set);1636 1637	bset2 = isl_basic_set_read_from_file(ctx, input);1638 1639	assert(isl_basic_set_is_equal(bset1, bset2) == 1);1640 1641	isl_basic_set_free(bset1);1642	isl_basic_set_free(bset2);1643	free(filename);1644 1645	fclose(input);1646}1647 1648struct {1649	const char *set;1650	const char *hull;1651} convex_hull_tests[] = {1652	{ "{ [i0, i1, i2] : (i2 = 1 and i0 = 0 and i1 >= 0) or "1653	       "(i0 = 1 and i1 = 0 and i2 = 1) or "1654	       "(i0 = 0 and i1 = 0 and i2 = 0) }",1655	  "{ [i0, i1, i2] : i0 >= 0 and i2 >= i0 and i2 <= 1 and i1 >= 0 }" },1656	{ "[n] -> { [i0, i1, i0] : i0 <= -4 + n; "1657	    "[i0, i0, i2] : n = 6 and i0 >= 0 and i2 <= 7 - i0 and "1658	    "i2 <= 5 and i2 >= 4; "1659	    "[3, i1, 3] : n = 5 and i1 <= 2 and i1 >= 0 }",1660	  "[n] -> { [i0, i1, i2] : i2 <= -1 + n and 2i2 <= -6 + 3n - i0 and "1661	    "i2 <= 5 + i0 and i2 >= i0 }" },1662	{ "{ [x, y] : 3y <= 2x and y >= -2 + 2x and 2y >= 2 - x }",1663	    "{ [x, y] : 1 = 0 }" },1664	{ "{ [x, y, z] : 0 <= x, y, z <= 10; [x, y, 0] : x >= 0 and y > 0; "1665	    "[x, y, 0] : x >= 0 and y < 0 }",1666	    "{ [x, y, z] : x >= 0 and 0 <= z <= 10 }" },1667	{ "{ [a, b, c] : a <= 1 and -a < b <= 1 and 0 <= c <= 2 - a - b and "1668			    "c <= a; "1669	    "[0, 2, 0]; [3, 1, 0] }",1670	    "{ [a, b, c] : b > -a and 2b >= -1 + a and 0 <= c <= a and "1671			    "5c <= 6 - a - 3b }" },1672};1673 1674static int test_convex_hull_algo(isl_ctx *ctx, int convex)1675{1676	int i;1677	int orig_convex = ctx->opt->convex;1678	ctx->opt->convex = convex;1679 1680	test_convex_hull_case(ctx, "convex0");1681	test_convex_hull_case(ctx, "convex1");1682	test_convex_hull_case(ctx, "convex2");1683	test_convex_hull_case(ctx, "convex3");1684	test_convex_hull_case(ctx, "convex4");1685	test_convex_hull_case(ctx, "convex5");1686	test_convex_hull_case(ctx, "convex6");1687	test_convex_hull_case(ctx, "convex7");1688	test_convex_hull_case(ctx, "convex8");1689	test_convex_hull_case(ctx, "convex9");1690	test_convex_hull_case(ctx, "convex10");1691	test_convex_hull_case(ctx, "convex11");1692	test_convex_hull_case(ctx, "convex12");1693	test_convex_hull_case(ctx, "convex13");1694	test_convex_hull_case(ctx, "convex14");1695	test_convex_hull_case(ctx, "convex15");1696 1697	for (i = 0; i < ARRAY_SIZE(convex_hull_tests); ++i) {1698		isl_set *set1, *set2;1699		int equal;1700 1701		set1 = isl_set_read_from_str(ctx, convex_hull_tests[i].set);1702		set2 = isl_set_read_from_str(ctx, convex_hull_tests[i].hull);1703		set1 = isl_set_from_basic_set(isl_set_convex_hull(set1));1704		equal = isl_set_is_equal(set1, set2);1705		isl_set_free(set1);1706		isl_set_free(set2);1707 1708		if (equal < 0)1709			return -1;1710		if (!equal)1711			isl_die(ctx, isl_error_unknown,1712				"unexpected convex hull", return -1);1713	}1714 1715	ctx->opt->convex = orig_convex;1716 1717	return 0;1718}1719 1720static int test_convex_hull(isl_ctx *ctx)1721{1722	if (test_convex_hull_algo(ctx, ISL_CONVEX_HULL_FM) < 0)1723		return -1;1724	if (test_convex_hull_algo(ctx, ISL_CONVEX_HULL_WRAP) < 0)1725		return -1;1726	return 0;1727}1728 1729/* Check that computing the gist of "map" with respect to "context"1730 * does not make any copy of "map" get marked empty.1731 * Earlier versions of isl would end up doing that.1732 */1733static isl_stat test_gist_empty_pair(isl_ctx *ctx, const char *map,1734	const char *context)1735{1736	isl_map *m1, *m2, *m3;1737	isl_bool empty_before, empty_after;1738 1739	m1 = isl_map_read_from_str(ctx, map);1740	m2 = isl_map_read_from_str(ctx, context);1741	m3 = isl_map_copy(m1);1742	empty_before = isl_map_is_empty(m3);1743	m1 = isl_map_gist(m1, m2);1744	empty_after = isl_map_is_empty(m3);1745	isl_map_free(m1);1746	isl_map_free(m3);1747 1748	if (empty_before < 0 || empty_after < 0)1749		return isl_stat_error;1750	if (empty_before)1751		isl_die(ctx, isl_error_unknown, "map should not be empty",1752			return isl_stat_error);1753	if (empty_after)1754		isl_die(ctx, isl_error_unknown, "map should still not be empty",1755			return isl_stat_error);1756 1757	return isl_stat_ok;1758}1759 1760/* Check that computing a gist does not make any copy of the input1761 * get marked empty.1762 * Earlier versions of isl would end up doing that on some pairs of inputs.1763 */1764static isl_stat test_gist_empty(isl_ctx *ctx)1765{1766	const char *map, *context;1767 1768	map = "{ [] -> [a, b, c] : 2b = 1 + a }";1769	context = "{ [] -> [a, b, c] : 2c = 2 + a }";1770	if (test_gist_empty_pair(ctx, map, context) < 0)1771		return isl_stat_error;1772	map = "{ [] -> [0, 0] }";1773	context = "{ [] -> [a, b] : a > b }";1774	if (test_gist_empty_pair(ctx, map, context) < 0)1775		return isl_stat_error;1776 1777	return isl_stat_ok;1778}1779 1780/* Inputs to isl_map_plain_gist_basic_map, along with the expected output.1781 */1782struct {1783	const char *map;1784	const char *context;1785	const char *gist;1786} plain_gist_tests[] = {1787	{ "{ [i] -> [j] : i >= 1 and j >= 1 or i >= 2 and j <= 10 }",1788	  "{ [i] -> [j] : i >= 1 }",1789	  "{ [i] -> [j] : j >= 1 or i >= 2 and j <= 10 }" },1790	{ "{ [n] -> [i,j,k] : (i mod 3 = 2 and j mod 4 = 2) or "1791		"(j mod 4 = 2 and k mod 6 = n) }",1792	  "{ [n] -> [i,j,k] : j mod 4 = 2 }",1793	  "{ [n] -> [i,j,k] : (i mod 3 = 2) or (k mod 6 = n) }" },1794	{ "{ [i] -> [j] : i > j and (exists a,b : i <= 2a + 5b <= 2) }",1795	  "{ [i] -> [j] : i > j }",1796	  "{ [i] -> [j] : exists a,b : i <= 2a + 5b <= 2 }" },1797};1798 1799/* Basic tests for isl_map_plain_gist_basic_map.1800 */1801static int test_plain_gist(isl_ctx *ctx)1802{1803	int i;1804 1805	for (i = 0; i < ARRAY_SIZE(plain_gist_tests); ++i) {1806		const char *str;1807		int equal;1808		isl_map *map, *gist;1809		isl_basic_map *context;1810 1811		map = isl_map_read_from_str(ctx, plain_gist_tests[i].map);1812		str = plain_gist_tests[i].context;1813		context = isl_basic_map_read_from_str(ctx, str);1814		map = isl_map_plain_gist_basic_map(map, context);1815		gist = isl_map_read_from_str(ctx, plain_gist_tests[i].gist);1816		equal = isl_map_is_equal(map, gist);1817		isl_map_free(map);1818		isl_map_free(gist);1819		if (equal < 0)1820			return -1;1821		if (!equal)1822			isl_die(ctx, isl_error_unknown,1823				"incorrect gist result", return -1);1824	}1825 1826	return 0;1827}1828 1829/* Inputs for isl_basic_set_gist tests that are expected to fail.1830 */1831struct {1832	const char *set;1833	const char *context;1834} gist_fail_tests[] = {1835	{ "{ [i] : exists (e0, e1: 3e1 >= 1 + 2e0 and "1836	    "8e1 <= -1 + 5i - 5e0 and 2e1 >= 1 + 2i - 5e0) }",1837	  "{ [i] : i >= 0 }" },1838};1839 1840/* Check that isl_basic_set_gist fails (gracefully) when expected.1841 * In particular, the user should be able to recover from the failure.1842 */1843static isl_stat test_gist_fail(struct isl_ctx *ctx)1844{1845	int i, n;1846	int on_error;1847 1848	on_error = isl_options_get_on_error(ctx);1849	isl_options_set_on_error(ctx, ISL_ON_ERROR_CONTINUE);1850	n = ARRAY_SIZE(gist_fail_tests);1851	for (i = 0; i < n; ++i) {1852		const char *str;1853		isl_basic_set *bset, *context;1854 1855		bset = isl_basic_set_read_from_str(ctx, gist_fail_tests[i].set);1856		str = gist_fail_tests[i].context;1857		context = isl_basic_set_read_from_str(ctx, str);1858		bset = isl_basic_set_gist(bset, context);1859		isl_basic_set_free(bset);1860		if (bset)1861			break;1862	}1863	isl_options_set_on_error(ctx, on_error);1864	if (i < n)1865		isl_die(ctx, isl_error_unknown,1866			"operation not expected to succeed",1867			return isl_stat_error);1868 1869	return isl_stat_ok;1870}1871 1872struct {1873	const char *set;1874	const char *context;1875	const char *gist;1876} gist_tests[] = {1877	{ "{ [1, -1, 3] }",1878	  "{ [1, b, 2 - b] : -1 <= b <= 2 }",1879	  "{ [a, -1, c] }" },1880	{ "{ [a, b, c] : a <= 15 and a >= 1 }",1881	  "{ [a, b, c] : exists (e0 = floor((-1 + a)/16): a >= 1 and "1882			"c <= 30 and 32e0 >= -62 + 2a + 2b - c and b >= 0) }",1883	  "{ [a, b, c] : a <= 15 }" },1884	{ "{ : }", "{ : 1 = 0 }", "{ : }" },1885	{ "{ : 1 = 0 }", "{ : 1 = 0 }", "{ : }" },1886	{ "[M] -> { [x] : exists (e0 = floor((-2 + x)/3): 3e0 = -2 + x) }",1887	  "[M] -> { [3M] }" , "[M] -> { [x] : 1 = 0 }" },1888	{ "{ [m, n, a, b] : a <= 2147 + n }",1889	  "{ [m, n, a, b] : (m >= 1 and n >= 1 and a <= 2148 - m and "1890			"b <= 2148 - n and b >= 0 and b >= 2149 - n - a) or "1891			"(n >= 1 and a >= 0 and b <= 2148 - n - a and "1892			"b >= 0) }",1893	  "{ [m, n, ku, kl] }" },1894	{ "{ [a, a, b] : a >= 10 }",1895	  "{ [a, b, c] : c >= a and c <= b and c >= 2 }",1896	  "{ [a, a, b] : a >= 10 }" },1897	{ "{ [i, j] : i >= 0 and i + j >= 0 }", "{ [i, j] : i <= 0 }",1898	  "{ [0, j] : j >= 0 }" },1899	/* Check that no constraints on i6 are introduced in the gist */1900	{ "[t1] -> { [i4, i6] : exists (e0 = floor((1530 - 4t1 - 5i4)/20): "1901		"20e0 <= 1530 - 4t1 - 5i4 and 20e0 >= 1511 - 4t1 - 5i4 and "1902		"5e0 <= 381 - t1 and i4 <= 1) }",1903	  "[t1] -> { [i4, i6] : exists (e0 = floor((-t1 + i6)/5): "1904		"5e0 = -t1 + i6 and i6 <= 6 and i6 >= 3) }",1905	  "[t1] -> { [i4, i6] : exists (e0 = floor((1530 - 4t1 - 5i4)/20): "1906		"i4 <= 1 and 5e0 <= 381 - t1 and 20e0 <= 1530 - 4t1 - 5i4 and "1907		"20e0 >= 1511 - 4t1 - 5i4) }" },1908	/* Check that no constraints on i6 are introduced in the gist */1909	{ "[t1, t2] -> { [i4, i5, i6] : exists (e0 = floor((1 + i4)/2), "1910		"e1 = floor((1530 - 4t1 - 5i4)/20), "1911		"e2 = floor((-4t1 - 5i4 + 10*floor((1 + i4)/2))/20), "1912		"e3 = floor((-1 + i4)/2): t2 = 0 and 2e3 = -1 + i4 and "1913			"20e2 >= -19 - 4t1 - 5i4 + 10e0 and 5e2 <= 1 - t1 and "1914			"2e0 <= 1 + i4 and 2e0 >= i4 and "1915			"20e1 <= 1530 - 4t1 - 5i4 and "1916			"20e1 >= 1511 - 4t1 - 5i4 and i4 <= 1 and "1917			"5e1 <= 381 - t1 and 20e2 <= -4t1 - 5i4 + 10e0) }",1918	  "[t1, t2] -> { [i4, i5, i6] : exists (e0 = floor((-17 + i4)/2), "1919		"e1 = floor((-t1 + i6)/5): 5e1 = -t1 + i6 and "1920			"2e0 <= -17 + i4 and 2e0 >= -18 + i4 and "1921			"10e0 <= -91 + 5i4 + 4i6 and "1922			"10e0 >= -105 + 5i4 + 4i6) }",1923	  "[t1, t2] -> { [i4, i5, i6] : exists (e0 = floor((381 - t1)/5), "1924		"e1 = floor((-1 + i4)/2): t2 = 0 and 2e1 = -1 + i4 and "1925		"i4 <= 1 and 5e0 <= 381 - t1 and 20e0 >= 1511 - 4t1 - 5i4) }" },1926	{ "{ [0, 0, q, p] : -5 <= q <= 5 and p >= 0 }",1927	  "{ [a, b, q, p] : b >= 1 + a }",1928	  "{ [a, b, q, p] : false }" },1929	{ "[n] -> { [x] : x = n && x mod 32 = 0 }",1930	  "[n] -> { [x] : x mod 32 = 0 }",1931	  "[n] -> { [x = n] }" },1932	{ "{ [x] : x mod 6 = 0 }", "{ [x] : x mod 3 = 0 }",1933	  "{ [x] : x mod 2 = 0 }" },1934	{ "{ [x] : x mod 3200 = 0 }", "{ [x] : x mod 10000 = 0 }",1935	  "{ [x] : x mod 128 = 0 }" },1936	{ "{ [x] : x mod 3200 = 0 }", "{ [x] : x mod 10 = 0 }",1937	  "{ [x] : x mod 3200 = 0 }" },1938	{ "{ [a, b, c] : a mod 2 = 0 and a = c }",1939	  "{ [a, b, c] : b mod 2 = 0 and b = c }",1940	  "{ [a, b, c = a] }" },1941	{ "{ [a, b, c] : a mod 6 = 0 and a = c }",1942	  "{ [a, b, c] : b mod 2 = 0 and b = c }",1943	  "{ [a, b, c = a] : a mod 3 = 0 }" },1944	{ "{ [x] : 0 <= x <= 4 or 6 <= x <= 9 }",1945	  "{ [x] : 1 <= x <= 3 or 7 <= x <= 8 }",1946	  "{ [x] }" },1947	{ "{ [x,y] : x < 0 and 0 <= y <= 4 or x >= -2 and -x <= y <= 10 + x }",1948	  "{ [x,y] : 1 <= y <= 3 }",1949	  "{ [x,y] }" },1950};1951 1952/* Check that isl_set_gist behaves as expected.1953 *1954 * For the test cases in gist_tests, besides checking that the result1955 * is as expected, also check that applying the gist operation does1956 * not modify the input set (an earlier version of isl would do that) and1957 * that the test case is consistent, i.e., that the gist has the same1958 * intersection with the context as the input set.1959 */1960static int test_gist(struct isl_ctx *ctx)1961{1962	int i;1963	const char *str;1964	isl_basic_set *bset1, *bset2;1965	isl_map *map1, *map2;1966	isl_bool equal;1967	isl_size n_div;1968 1969	for (i = 0; i < ARRAY_SIZE(gist_tests); ++i) {1970		isl_bool equal_input, equal_intersection;1971		isl_set *set1, *set2, *copy, *context;1972 1973		set1 = isl_set_read_from_str(ctx, gist_tests[i].set);1974		context = isl_set_read_from_str(ctx, gist_tests[i].context);1975		copy = isl_set_copy(set1);1976		set1 = isl_set_gist(set1, isl_set_copy(context));1977		set2 = isl_set_read_from_str(ctx, gist_tests[i].gist);1978		equal = isl_set_is_equal(set1, set2);1979		isl_set_free(set1);1980		set1 = isl_set_read_from_str(ctx, gist_tests[i].set);1981		equal_input = isl_set_is_equal(set1, copy);1982		isl_set_free(copy);1983		set1 = isl_set_intersect(set1, isl_set_copy(context));1984		set2 = isl_set_intersect(set2, context);1985		equal_intersection = isl_set_is_equal(set1, set2);1986		isl_set_free(set2);1987		isl_set_free(set1);1988		if (equal < 0 || equal_input < 0 || equal_intersection < 0)1989			return -1;1990		if (!equal)1991			isl_die(ctx, isl_error_unknown,1992				"incorrect gist result", return -1);1993		if (!equal_input)1994			isl_die(ctx, isl_error_unknown,1995				"gist modified input", return -1);1996		if (!equal_input)1997			isl_die(ctx, isl_error_unknown,1998				"inconsistent gist test case", return -1);1999	}2000 2001	if (test_gist_fail(ctx) < 0)2002		return -1;2003 2004	str = "[p0, p2, p3, p5, p6, p10] -> { [] : "2005	    "exists (e0 = [(15 + p0 + 15p6 + 15p10)/16], e1 = [(p5)/8], "2006	    "e2 = [(p6)/128], e3 = [(8p2 - p5)/128], "2007	    "e4 = [(128p3 - p6)/4096]: 8e1 = p5 and 128e2 = p6 and "2008	    "128e3 = 8p2 - p5 and 4096e4 = 128p3 - p6 and p2 >= 0 and "2009	    "16e0 >= 16 + 16p6 + 15p10 and  p2 <= 15 and p3 >= 0 and "2010	    "p3 <= 31 and  p6 >= 128p3 and p5 >= 8p2 and p10 >= 0 and "2011	    "16e0 <= 15 + p0 + 15p6 + 15p10 and 16e0 >= p0 + 15p6 + 15p10 and "2012	    "p10 <= 15 and p10 <= -1 + p0 - p6) }";2013	bset1 = isl_basic_set_read_from_str(ctx, str);2014	str = "[p0, p2, p3, p5, p6, p10] -> { [] : exists (e0 = [(p5)/8], "2015	    "e1 = [(p6)/128], e2 = [(8p2 - p5)/128], "2016	    "e3 = [(128p3 - p6)/4096]: 8e0 = p5 and 128e1 = p6 and "2017	    "128e2 = 8p2 - p5 and 4096e3 = 128p3 - p6 and p5 >= -7 and "2018	    "p2 >= 0 and 8p2 <= -1 + p0 and p2 <= 15 and p3 >= 0 and "2019	    "p3 <= 31 and 128p3 <= -1 + p0 and p6 >= -127 and "2020	    "p5 <= -1 + p0 and p6 <= -1 + p0 and p6 >= 128p3 and "2021	    "p0 >= 1 and p5 >= 8p2 and p10 >= 0 and p10 <= 15 ) }";2022	bset2 = isl_basic_set_read_from_str(ctx, str);2023	bset1 = isl_basic_set_gist(bset1, bset2);2024	assert(bset1 && bset1->n_div == 0);2025	isl_basic_set_free(bset1);2026 2027	/* Check that the integer divisions of the second disjunct2028	 * do not spread to the first disjunct.2029	 */2030	str = "[t1] -> { S_0[] -> A[o0] : (exists (e0 = [(-t1 + o0)/16]: "2031		"16e0 = -t1 + o0 and o0 >= 0 and o0 <= 15 and t1 >= 0)) or "2032		"(exists (e0 = [(-1 + t1)/16], "2033			"e1 = [(-16 + t1 - 16e0)/4294967296]: "2034			"4294967296e1 = -16 + t1 - o0 - 16e0 and "2035			"16e0 <= -1 + t1 and 16e0 >= -16 + t1 and o0 >= 0 and "2036			"o0 <= 4294967295 and t1 <= -1)) }";2037	map1 = isl_map_read_from_str(ctx, str);2038	str = "[t1] -> { S_0[] -> A[o0] : t1 >= 0 and t1 <= 4294967295 }";2039	map2 = isl_map_read_from_str(ctx, str);2040	map1 = isl_map_gist(map1, map2);2041	if (!map1)2042		return -1;2043	if (map1->n != 1)2044		isl_die(ctx, isl_error_unknown, "expecting single disjunct",2045			isl_map_free(map1); return -1);2046	n_div = isl_basic_map_dim(map1->p[0], isl_dim_div);2047	isl_map_free(map1);2048	if (n_div < 0)2049		return -1;2050	if (n_div != 1)2051		isl_die(ctx, isl_error_unknown, "expecting single div",2052			return -1);2053 2054	if (test_gist_empty(ctx) < 0)2055		return -1;2056	if (test_plain_gist(ctx) < 0)2057		return -1;2058 2059	return 0;2060}2061 2062int test_coalesce_set(isl_ctx *ctx, const char *str, int check_one)2063{2064	isl_set *set, *set2;2065	int equal;2066	int one;2067 2068	set = isl_set_read_from_str(ctx, str);2069	set = isl_set_coalesce(set);2070	set2 = isl_set_read_from_str(ctx, str);2071	equal = isl_set_is_equal(set, set2);2072	one = set && set->n == 1;2073	isl_set_free(set);2074	isl_set_free(set2);2075 2076	if (equal < 0)2077		return -1;2078	if (!equal)2079		isl_die(ctx, isl_error_unknown,2080			"coalesced set not equal to input", return -1);2081	if (check_one && !one)2082		isl_die(ctx, isl_error_unknown,2083			"coalesced set should not be a union", return -1);2084 2085	return 0;2086}2087 2088/* Inputs for coalescing tests with unbounded wrapping.2089 * "str" is a string representation of the input set.2090 * "single_disjunct" is set if we expect the result to consist of2091 *	a single disjunct.2092 */2093struct {2094	int single_disjunct;2095	const char *str;2096} coalesce_unbounded_tests[] = {2097	{ 1, "{ [x,y,z] : y + 2 >= 0 and x - y + 1 >= 0 and "2098			"-x - y + 1 >= 0 and -3 <= z <= 3;"2099		"[x,y,z] : -x+z + 20 >= 0 and -x-z + 20 >= 0 and "2100			"x-z + 20 >= 0 and x+z + 20 >= 0 and "2101			"-10 <= y <= 0}" },2102	{ 1, "{ [x,y] : 0 <= x,y <= 10; [5,y]: 4 <= y <= 11 }" },2103	{ 1, "{ [x,0,0] : -5 <= x <= 5; [0,y,1] : -5 <= y <= 5 }" },2104	{ 1, "{ [x,y] : 0 <= x <= 10 and 0 >= y >= -1 and x+y >= 0; [0,1] }" },2105	{ 1, "{ [x,y] : (0 <= x,y <= 4) or (2 <= x,y <= 5 and x + y <= 9) }" },2106	{ 0, "{ [x, y, z] : 0 <= x,y,z <= 100 and 0 < z <= 2 + 2x + 2y; "2107		"[x, y, 0] : x,y <= 100 and y <= 9 + 11x and x <= 9 + 11y }" },2108	{ 1, "{ [0:1, 0:1]; [0, 2:3] }" },2109	{ 1, "{ [0:1, 0:1]; [0, 2:3]; [1, -2:-1] }" },2110	{ 1, "{ [0:3, 0:1]; [1:2, 2:5] }" },2111	{ 1, "{ [0:3, 0:1]; [0:2, 2:5] }" },2112	{ 1, "{ [0:3, 0:1]; [1:3, 2:5] }" },2113	{ 0, "{ [0:3, 0:1]; [1:4, 2:5] }" },2114	{ 0, "{ [0:3, 0:1]; [1:5, 2:5] }" },2115};2116 2117/* Test the functionality of isl_set_coalesce with the bounded wrapping2118 * option turned off.2119 */2120int test_coalesce_unbounded_wrapping(isl_ctx *ctx)2121{2122	int i;2123	int r = 0;2124	int bounded;2125 2126	bounded = isl_options_get_coalesce_bounded_wrapping(ctx);2127	isl_options_set_coalesce_bounded_wrapping(ctx, 0);2128 2129	for (i = 0; i < ARRAY_SIZE(coalesce_unbounded_tests); ++i) {2130		const char *str = coalesce_unbounded_tests[i].str;2131		int check_one = coalesce_unbounded_tests[i].single_disjunct;2132		if (test_coalesce_set(ctx, str, check_one) >= 0)2133			continue;2134		r = -1;2135		break;2136	}2137 2138	isl_options_set_coalesce_bounded_wrapping(ctx, bounded);2139 2140	return r;2141}2142 2143/* Inputs for coalescing tests.2144 * "str" is a string representation of the input set.2145 * "single_disjunct" is set if we expect the result to consist of2146 *	a single disjunct.2147 */2148struct {2149	int single_disjunct;2150	const char *str;2151} coalesce_tests[] = {2152	{ 1, "{[x,y]: x >= 0 & x <= 10 & y >= 0 & y <= 10 or "2153		       "y >= x & x >= 2 & 5 >= y }" },2154	{ 1, "{[x,y]: y >= 0 & 2x + y <= 30 & y <= 10 & x >= 0 or "2155		       "x + y >= 10 & y <= x & x + y <= 20 & y >= 0}" },2156	{ 0, "{[x,y]: y >= 0 & 2x + y <= 30 & y <= 10 & x >= 0 or "2157		       "x + y >= 10 & y <= x & x + y <= 19 & y >= 0}" },2158	{ 1, "{[x,y]: y >= 0 & x <= 5 & y <= x or "2159		       "y >= 0 & x >= 6 & x <= 10 & y <= x}" },2160	{ 0, "{[x,y]: y >= 0 & x <= 5 & y <= x or "2161		       "y >= 0 & x >= 7 & x <= 10 & y <= x}" },2162	{ 0, "{[x,y]: y >= 0 & x <= 5 & y <= x or "2163		       "y >= 0 & x >= 6 & x <= 10 & y + 1 <= x}" },2164	{ 1, "{[x,y]: y >= 0 & x <= 5 & y <= x or y >= 0 & x = 6 & y <= 6}" },2165	{ 0, "{[x,y]: y >= 0 & x <= 5 & y <= x or y >= 0 & x = 7 & y <= 6}" },2166	{ 1, "{[x,y]: y >= 0 & x <= 5 & y <= x or y >= 0 & x = 6 & y <= 5}" },2167	{ 0, "{[x,y]: y >= 0 & x <= 5 & y <= x or y >= 0 & x = 6 & y <= 7}" },2168	{ 1, "[n] -> { [i] : i = 1 and n >= 2 or 2 <= i and i <= n }" },2169	{ 0, "{[x,y] : x >= 0 and y >= 0 or 0 <= y and y <= 5 and x = -1}" },2170	{ 1, "[n] -> { [i] : 1 <= i and i <= n - 1 or 2 <= i and i <= n }" },2171	{ 0, "[n] -> { [[i0] -> [o0]] : exists (e0 = [(i0)/4], e1 = [(o0)/4], "2172		"e2 = [(n)/2], e3 = [(-2 + i0)/4], e4 = [(-2 + o0)/4], "2173		"e5 = [(-2n + i0)/4]: 2e2 = n and 4e3 = -2 + i0 and "2174		"4e4 = -2 + o0 and i0 >= 8 + 2n and o0 >= 2 + i0 and "2175		"o0 <= 56 + 2n and o0 <= -12 + 4n and i0 <= 57 + 2n and "2176		"i0 <= -11 + 4n and o0 >= 6 + 2n and 4e0 <= i0 and "2177		"4e0 >= -3 + i0 and 4e1 <= o0 and 4e1 >= -3 + o0 and "2178		"4e5 <= -2n + i0 and 4e5 >= -3 - 2n + i0);"2179		"[[i0] -> [o0]] : exists (e0 = [(i0)/4], e1 = [(o0)/4], "2180		"e2 = [(n)/2], e3 = [(-2 + i0)/4], e4 = [(-2 + o0)/4], "2181		"e5 = [(-2n + i0)/4]: 2e2 = n and 4e3 = -2 + i0 and "2182		"4e4 = -2 + o0 and 2e0 >= 3 + n and e0 <= -4 + n and "2183		"2e0 <= 27 + n and e1 <= -4 + n and 2e1 <= 27 + n and "2184		"2e1 >= 2 + n and e1 >= 1 + e0 and i0 >= 7 + 2n and "2185		"i0 <= -11 + 4n and i0 <= 57 + 2n and 4e0 <= -2 + i0 and "2186		"4e0 >= -3 + i0 and o0 >= 6 + 2n and o0 <= -11 + 4n and "2187		"o0 <= 57 + 2n and 4e1 <= -2 + o0 and 4e1 >= -3 + o0 and "2188		"4e5 <= -2n + i0 and 4e5 >= -3 - 2n + i0 ) }" },2189	{ 0, "[n, m] -> { [o0, o2, o3] : (o3 = 1 and o0 >= 1 + m and "2190	      "o0 <= n + m and o2 <= m and o0 >= 2 + n and o2 >= 3) or "2191	      "(o0 >= 2 + n and o0 >= 1 + m and o0 <= n + m and n >= 1 and "2192	      "o3 <= -1 + o2 and o3 >= 1 - m + o2 and o3 >= 2 and o3 <= n) }" },2193	{ 0, "[M, N] -> { [[i0, i1, i2, i3, i4, i5, i6] -> "2194	  "[o0, o1, o2, o3, o4, o5, o6]] : "2195	  "(o6 <= -4 + 2M - 2N + i0 + i1 - i2 + i6 - o0 - o1 + o2 and "2196	  "o3 <= -2 + i3 and o6 >= 2 + i0 + i3 + i6 - o0 - o3 and "2197	  "o6 >= 2 - M + N + i3 + i4 + i6 - o3 - o4 and o0 <= -1 + i0 and "2198	  "o4 >= 4 - 3M + 3N - i0 - i1 + i2 + 2i3 + i4 + o0 + o1 - o2 - 2o3 "2199	  "and o6 <= -3 + 2M - 2N + i3 + i4 - i5 + i6 - o3 - o4 + o5 and "2200	  "2o6 <= -5 + 5M - 5N + 2i0 + i1 - i2 - i5 + 2i6 - 2o0 - o1 + o2 + o5 "2201	  "and o6 >= 2i0 + i1 + i6 - 2o0 - o1 and "2202	  "3o6 <= -5 + 4M - 4N + 2i0 + i1 - i2 + 2i3 + i4 - i5 + 3i6 "2203	  "- 2o0 - o1 + o2 - 2o3 - o4 + o5) or "2204	  "(N >= 2 and o3 <= -1 + i3 and o0 <= -1 + i0 and "2205	  "o6 >= i3 + i6 - o3 and M >= 0 and "2206	  "2o6 >= 1 + i0 + i3 + 2i6 - o0 - o3 and "2207	  "o6 >= 1 - M + i0 + i6 - o0 and N >= 2M and o6 >= i0 + i6 - o0) }" },2208	{ 0, "[M, N] -> { [o0] : (o0 = 0 and M >= 1 and N >= 2) or "2209		"(o0 = 0 and M >= 1 and N >= 2M and N >= 2 + M) or "2210		"(o0 = 0 and M >= 2 and N >= 3) or "2211		"(M = 0 and o0 = 0 and N >= 3) }" },2212	{ 0, "{ [i0, i1, i2, i3] : (i1 = 10i0 and i0 >= 1 and 10i0 <= 100 and "2213	    "i3 <= 9 + 10 i2 and i3 >= 1 + 10i2 and i3 >= 0) or "2214	    "(i1 <= 9 + 10i0 and i1 >= 1 + 10i0 and i2 >= 0 and "2215	    "i0 >= 0 and i1 <= 100 and i3 <= 9 + 10i2 and i3 >= 1 + 10i2) }" },2216	{ 0, "[M] -> { [i1] : (i1 >= 2 and i1 <= M) or (i1 = M and M >= 1) }" },2217	{ 0, "{[x,y] : x,y >= 0; [x,y] : 10 <= x <= 20 and y >= -1 }" },2218	{ 1, "{ [x, y] : (x >= 1 and y >= 1 and x <= 2 and y <= 2) or "2219		"(y = 3 and x = 1) }" },2220	{ 1, "[M] -> { [i0, i1, i2, i3, i4] : (i1 >= 3 and i4 >= 2 + i2 and "2221		"i2 >= 2 and i0 >= 2 and i3 >= 1 + i2 and i0 <= M and "2222		"i1 <= M and i3 <= M and i4 <= M) or "2223		"(i1 >= 2 and i4 >= 1 + i2 and i2 >= 2 and i0 >= 2 and "2224		"i3 >= 1 + i2 and i0 <= M and i1 <= -1 + M and i3 <= M and "2225		"i4 <= -1 + M) }" },2226	{ 1, "{ [x, y] : (x >= 0 and y >= 0 and x <= 10 and y <= 10) or "2227		"(x >= 1 and y >= 1 and x <= 11 and y <= 11) }" },2228	{ 0, "{[x,0] : x >= 0; [x,1] : x <= 20}" },2229	{ 1, "{ [x, 1 - x] : 0 <= x <= 1; [0,0] }" },2230	{ 1, "{ [0,0]; [i,i] : 1 <= i <= 10 }" },2231	{ 0, "{ [0,0]; [i,j] : 1 <= i,j <= 10 }" },2232	{ 1, "{ [0,0]; [i,2i] : 1 <= i <= 10 }" },2233	{ 0, "{ [0,0]; [i,2i] : 2 <= i <= 10 }" },2234	{ 0, "{ [1,0]; [i,2i] : 1 <= i <= 10 }" },2235	{ 0, "{ [0,1]; [i,2i] : 1 <= i <= 10 }" },2236	{ 0, "{ [a, b] : exists e : 2e = a and "2237		    "a >= 0 and (a <= 3 or (b <= 0 and b >= -4 + a)) }" },2238	{ 0, "{ [i, j, i', j'] : i <= 2 and j <= 2 and "2239			"j' >= -1 + 2i + j - 2i' and i' <= -1 + i and "2240			"j >= 1 and j' <= i + j - i' and i >= 1; "2241		"[1, 1, 1, 1] }" },2242	{ 1, "{ [i,j] : exists a,b : i = 2a and j = 3b; "2243		 "[i,j] : exists a : j = 3a }" },2244	{ 1, "{ [a, b, c] : (c <= 7 - b and b <= 1 and b >= 0 and "2245			"c >= 3 + b and b <= 3 + 8a and b >= -26 + 8a and "2246			"a >= 3) or "2247		    "(b <= 1 and c <= 7 and b >= 0 and c >= 4 + b and "2248			"b <= 3 + 8a and b >= -26 + 8a and a >= 3) }" },2249	{ 1, "{ [a, 0, c] : c >= 1 and c <= 29 and c >= -1 + 8a and "2250				"c <= 6 + 8a and a >= 3; "2251		"[a, -1, c] : c >= 1 and c <= 30 and c >= 8a and "2252				"c <= 7 + 8a and a >= 3 and a <= 4 }" },2253	{ 1, "{ [x,y] : 0 <= x <= 2 and y >= 0 and x + 2y <= 4; "2254		"[x,0] : 3 <= x <= 4 }" },2255	{ 1, "{ [x,y] : 0 <= x <= 3 and y >= 0 and x + 3y <= 6; "2256		"[x,0] : 4 <= x <= 5 }" },2257	{ 0, "{ [x,y] : 0 <= x <= 2 and y >= 0 and x + 2y <= 4; "2258		"[x,0] : 3 <= x <= 5 }" },2259	{ 0, "{ [x,y] : 0 <= x <= 2 and y >= 0 and x + y <= 4; "2260		"[x,0] : 3 <= x <= 4 }" },2261	{ 1, "{ [i0, i1] : i0 <= 122 and i0 >= 1 and 128i1 >= -249 + i0 and "2262			"i1 <= 0; "2263		"[i0, 0] : i0 >= 123 and i0 <= 124 }" },2264	{ 1, "{ [0,0]; [1,1] }" },2265	{ 1, "[n] -> { [k] : 16k <= -1 + n and k >= 1; [0] : n >= 2 }" },2266	{ 1, "{ [k, ii, k - ii] : ii >= -6 + k and ii <= 6 and ii >= 1 and "2267				"ii <= k;"2268		"[k, 0, k] : k <= 6 and k >= 1 }" },2269	{ 1, "{ [i,j] : i = 4 j and 0 <= i <= 100;"2270		"[i,j] : 1 <= i <= 100 and i >= 4j + 1 and i <= 4j + 2 }" },2271	{ 1, "{ [x,y] : x % 2 = 0 and y % 2 = 0; [x,x] : x % 2 = 0 }" },2272	{ 1, "[n] -> { [1] : n >= 0;"2273		    "[x] : exists (e0 = floor((x)/2): x >= 2 and "2274			"2e0 >= -1 + x and 2e0 <= x and 2e0 <= n) }" },2275	{ 1, "[n] -> { [x, y] : exists (e0 = floor((x)/2), e1 = floor((y)/3): "2276			"3e1 = y and x >= 2 and 2e0 >= -1 + x and "2277			"2e0 <= x and 2e0 <= n);"2278		    "[1, y] : exists (e0 = floor((y)/3): 3e0 = y and "2279			"n >= 0) }" },2280	{ 1, "[t1] -> { [i0] : (exists (e0 = floor((63t1)/64): "2281				"128e0 >= -134 + 127t1 and t1 >= 2 and "2282				"64e0 <= 63t1 and 64e0 >= -63 + 63t1)) or "2283				"t1 = 1 }" },2284	{ 1, "{ [i, i] : exists (e0 = floor((1 + 2i)/3): 3e0 <= 2i and "2285				"3e0 >= -1 + 2i and i <= 9 and i >= 1);"2286		"[0, 0] }" },2287	{ 1, "{ [t1] : exists (e0 = floor((-11 + t1)/2): 2e0 = -11 + t1 and "2288				"t1 >= 13 and t1 <= 16);"2289		"[t1] : t1 <= 15 and t1 >= 12 }" },2290	{ 1, "{ [x,y] : x = 3y and 0 <= y <= 2; [-3,-1] }" },2291	{ 1, "{ [x,y] : 2x = 3y and 0 <= y <= 4; [-3,-2] }" },2292	{ 0, "{ [x,y] : 2x = 3y and 0 <= y <= 4; [-2,-2] }" },2293	{ 0, "{ [x,y] : 2x = 3y and 0 <= y <= 4; [-3,-1] }" },2294	{ 1, "{ [i] : exists j : i = 4 j and 0 <= i <= 100;"2295		"[i] : exists j : 1 <= i <= 100 and i >= 4j + 1 and "2296				"i <= 4j + 2 }" },2297	{ 1, "{ [c0] : (exists (e0 : c0 - 1 <= 3e0 <= c0)) or "2298		"(exists (e0 : 3e0 = -2 + c0)) }" },2299	{ 0, "[n, b0, t0] -> "2300		"{ [i0, i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11, i12] : "2301		"(exists (e0 = floor((-32b0 + i4)/1048576), "2302		"e1 = floor((i8)/32): 1048576e0 = -32b0 + i4 and 32e1 = i8 and "2303		"n <= 2147483647 and b0 <= 32767 and b0 >= 0 and "2304		"32b0 <= -2 + n and t0 <= 31 and t0 >= 0 and i0 >= 8 + n and "2305		"3i4 <= -96 + 3t0 + i0 and 3i4 >= -95 - n + 3t0 + i0 and "2306		"i8 >= -157 + i0 - 4i4 and i8 >= 0 and "2307		"i8 <= -33 + i0 - 4i4 and 3i8 <= -91 + 4n - i0)) or "2308		"(exists (e0 = floor((-32b0 + i4)/1048576), "2309		"e1 = floor((i8)/32): 1048576e0 = -32b0 + i4 and 32e1 = i8 and "2310		"n <= 2147483647 and b0 <= 32767 and b0 >= 0 and "2311		"32b0 <= -2 + n and t0 <= 31 and t0 >= 0 and i0 <= 7 + n and "2312		"4i4 <= -3 + i0 and 3i4 <= -96 + 3t0 + i0 and "2313		"3i4 >= -95 - n + 3t0 + i0 and i8 >= -157 + i0 - 4i4 and "2314		"i8 >= 0 and i8 <= -4 + i0 - 3i4 and i8 <= -41 + i0));"2315		"[i0, i1, i2, i3, 0, i5, i6, i7, i8, i9, i10, i11, i12] : "2316		"(exists (e0 = floor((i8)/32): b0 = 0 and 32e0 = i8 and "2317		"n <= 2147483647 and t0 <= 31 and t0 >= 0 and i0 >= 11 and "2318		"i0 >= 96 - 3t0 and i0 <= 95 + n - 3t0 and i0 <= 7 + n and "2319		"i8 >= -40 + i0 and i8 <= -10 + i0)) }" },2320	{ 0, "{ [i0, i1, i2] : "2321		"(exists (e0, e1 = floor((i0)/32), e2 = floor((i1)/32): "2322		"32e1 = i0 and 32e2 = i1 and i1 >= -31 + i0 and "2323		"i1 <= 31 + i0 and i2 >= -30 + i0 and i2 >= -30 + i1 and "2324		"32e0 >= -30 + i0 and 32e0 >= -30 + i1 and "2325		"32e0 >= -31 + i2 and 32e0 <= 30 + i2 and 32e0 <= 31 + i1 and "2326		"32e0 <= 31 + i0)) or "2327		"i0 >= 0 }" },2328	{ 1, "{ [a, b, c] : 2b = 1 + a and 2c = 2 + a; [0, 0, 0] }" },2329	{ 1, "{ [a, a, b, c] : 32*floor((a)/32) = a and 2*floor((b)/2) = b and "2330				"2*floor((c)/2) = c and 0 <= a <= 192;"2331		"[224, 224, b, c] : 2*floor((b)/2) = b and 2*floor((c)/2) = c }"2332	},2333	{ 1, "[n] -> { [a,b] : (exists e : 1 <= a <= 7e and 9e <= b <= n) or "2334				"(0 <= a <= b <= n) }" },2335	{ 1, "{ [a, b] : 0 <= a <= 2 and b >= 0 and "2336		"((0 < b <= 13) or (2*floor((a + b)/2) >= -5 + a + 2b)) }" },2337	{ 1, "{ [a] : (2 <= a <= 5) or (a mod 2 = 1 and 1 <= a <= 5) }" },2338	{ 1, "{ [a, b, c] : (b = -1 + a and 0 < a <= 3 and "2339				"9*floor((-4a + 2c)/9) <= -3 - 4a + 2c) or "2340			"(exists (e0 = floor((-16 + 2c)/9): a = 4 and "2341				"b = 3 and 9e0 <= -19 + 2c)) }" },2342	{ 1, "{ [a, b, c] : (b = -1 + a and 0 < a <= 3 and "2343				"9*floor((-4a + 2c)/9) <= -3 - 4a + 2c) or "2344			"(a = 4 and b = 3 and "2345				"9*floor((-16 + 2c)/9) <= -19 + 2c) }" },2346	{ 0, "{ [a, b, c] : (b <= 2 and b <= -2 + a) or "2347			"(b = -1 + a and 0 < a <= 3 and "2348				"9*floor((-4a + 2c)/9) <= -3 - 4a + 2c) or "2349			"(exists (e0 = floor((-16 + 2c)/9): a = 4 and "2350				"b = 3 and 9e0 <= -19 + 2c)) }" },2351	{ 1, "{ [y, x] : (x - y) mod 3 = 2 and 2 <= y <= 200 and 0 <= x <= 2;"2352		"[1, 0] }" },2353	{ 1, "{ [x, y] : (x - y) mod 3 = 2 and 2 <= y <= 200 and 0 <= x <= 2;"2354		"[0, 1] }" },2355	{ 1, "{ [1, y] : -1 <= y <= 1; [x, -x] : 0 <= x <= 1 }" },2356	{ 1, "{ [1, y] : 0 <= y <= 1; [x, -x] : 0 <= x <= 1 }" },2357	{ 1, "{ [x, y] : 0 <= x <= 10 and x - 4*floor(x/4) <= 1 and y <= 0; "2358	       "[x, y] : 0 <= x <= 10 and x - 4*floor(x/4) > 1 and y <= 0; "2359	       "[x, y] : 0 <= x <= 10 and x - 5*floor(x/5) <= 1 and 0 < y; "2360	       "[x, y] : 0 <= x <= 10 and x - 5*floor(x/5) > 1 and 0 < y }" },2361	{ 1, "{ [x, 0] : 0 <= x <= 10 and x mod 2 = 0; "2362	       "[x, 0] : 0 <= x <= 10 and x mod 2 = 1; "2363	       "[x, y] : 0 <= x <= 10 and 1 <= y <= 10 }" },2364	{ 1, "{ [a] : a <= 8 and "2365			"(a mod 10 = 7 or a mod 10 = 8 or a mod 10 = 9) }" },2366	{ 1, "{ [x, y] : 2y = -x and x <= 0 or "2367			"x <= -1 and 2y <= -x - 1 and 2y >= x - 1 }" },2368	{ 0, "{ [x, y] : 2y = -x and x <= 0 or "2369			"x <= -2 and 2y <= -x - 1 and 2y >= x - 1 }" },2370	{ 1, "{ [a] : (a <= 0 and 3*floor((a)/3) = a) or "2371			"(a < 0 and 3*floor((a)/3) < a) }" },2372	{ 1, "{ [a] : (a <= 0 and 3*floor((a)/3) = a) or "2373			"(a < -1 and 3*floor((a)/3) < a) }" },2374	{ 1, "{ [a, b] : a <= 1024 and b >= 0 and "2375		"((-31 - a + b <= 32*floor((-1 - a)/32) <= -33 + b and "2376		  "32*floor((-1 - a)/32) <= -16 + b + 16*floor((-1 - a)/16))"2377		"or (2 <= a <= 15 and b < a)) }" },2378	{ 1, "{ [a] : a > 0 and ((16*floor((a)/16) < a and "2379			"32*floor((a)/32) < a) or a <= 15) }" },2380	{ 1, "{ [a, b, c, d] : (-a + d) mod 64 = 0 and a <= 8 and b <= 1 and "2381			"10 - a <= c <= 3 and d >= 5 and 9 - 64b <= d <= 70;"2382	    "[a, b = 1, c, d] : (-a + d) mod 64 = 0 and a <= 8 and c >= 4 and "2383			"10 - a <= c <= 5 and 5 <= d <= 73 - c }" },2384	{ 1, "[n, m] -> { S_0[i] : (-n + i) mod 3 = 0 and m >= 3 + n and "2385			    "i >= n and 3*floor((2 + n + 2m)/3) <= n + 3m - i; "2386			 "S_0[n] : n <= m <= 2 + n }" },2387	{ 1, "{ [a, b] : exists (e0: 0 <= a <= 1 and b >= 0 and "2388			"2e0 >= -5 + a + 2b and 2e0 >= -1 + a + b and "2389			"2e0 <= a + b); "2390		"[a, b] : exists (e0: 0 <= a <= 1 and 2e0 >= -5 + a + 2b and "2391			"2e0 >= -1 - a + b and 2e0 <= -a + b and "2392			"2e0 < -a + 2b) }" },2393	{ 1, "{ [i, j, i - 8j] : 8 <= i <= 63 and -7 + i <= 8j <= i; "2394		"[i, 0, i] : 0 <= i <= 7 }" },2395	{ 1, "{ [a, b] : a >= 0 and 0 <= b <= 1 - a; [1, 1] }" },2396	{ 0, "{ [a, b] : a >= 0 and 0 <= b <= 1 - a; [0, 2] }" },2397	{ 0, "{ [a, b] : a >= 0 and 0 <= b <= 1 - a; [-1, 3] }" },2398	{ 1, "{ [a, b] : a, b >= 0 and a + 2b <= 2; [1, 1] }" },2399	{ 0, "{ [a, b] : a, b >= 0 and a + 2b <= 2; [2, 1] }" },2400	{ 0, "{ [a, c] : (2 + a) mod 4 = 0 or "2401		"(c = 4 + a and 4 * floor((a)/4) = a and a >= 0 and a <= 4) or "2402		"(c = 3 + a and 4 * floor((-1 + a)/4) = -1 + a and "2403		    "a > 0 and a <= 5) }" },2404	{ 1, "{ [1, 0, 0]; [a, b, c] : -1 <= -a < b <= 0 and 2c > b }" },2405	{ 0, "{ [j, a, l] : a mod 2 = 0 and j <= 29 and a >= 2 and "2406			"2a <= -5 + j and 32j + 2a + 2 <= 4l < 33j; "2407		"[j, 0, l] : 4 <= j <= 29 and -3 + 33j <= 4l <= 33j }" },2408	{ 0, "{ [0:1, 0:1]; [0, 2:3] }" },2409	{ 1, "{ [a] : (a = 0 or ((1 + a) mod 2 = 0 and 0 < a <= 15) or "2410		"((a) mod 2 = 0 and 0 < a <= 15)) }" },2411	{ 1, "{ rat: [0:2]; rat: [1:3] }" },2412};2413 2414/* A specialized coalescing test case that would result2415 * in a segmentation fault or a failed assertion in earlier versions of isl.2416 */2417static int test_coalesce_special(struct isl_ctx *ctx)2418{2419	const char *str;2420	isl_map *map1, *map2;2421 2422	str = "[y] -> { [S_L220_OUT[] -> T7[]] -> "2423	    "[[S_L309_IN[] -> T11[]] -> ce_imag2[1, o1]] : "2424	    "(y = 201 and o1 <= 239 and o1 >= 212) or "2425	    "(exists (e0 = [(y)/3]: 3e0 = y and y <= 198 and y >= 3 and "2426		"o1 <= 239 and o1 >= 212)) or "2427	    "(exists (e0 = [(y)/3]: 3e0 = y and y <= 201 and y >= 3 and "2428		"o1 <= 241 and o1 >= 240));"2429	    "[S_L220_OUT[] -> T7[]] -> "2430	    "[[S_L309_IN[] -> T11[]] -> ce_imag2[0, o1]] : "2431	    "(y = 2 and o1 <= 241 and o1 >= 212) or "2432	    "(exists (e0 = [(-2 + y)/3]: 3e0 = -2 + y and y <= 200 and "2433		"y >= 5 and o1 <= 241 and o1 >= 212)) }";2434	map1 = isl_map_read_from_str(ctx, str);2435	map1 = isl_map_align_divs_internal(map1);2436	map1 = isl_map_coalesce(map1);2437	str = "[y] -> { [S_L220_OUT[] -> T7[]] -> "2438	    "[[S_L309_IN[] -> T11[]] -> ce_imag2[o0, o1]] : "2439	    "exists (e0 = [(-1 - y + o0)/3]: 3e0 = -1 - y + o0 and "2440		"y <= 201 and o0 <= 2 and o1 >= 212 and o1 <= 241 and "2441		"o0 >= 3 - y and o0 <= -2 + y and o0 >= 0) }";2442	map2 = isl_map_read_from_str(ctx, str);2443	map2 = isl_map_union(map2, map1);2444	map2 = isl_map_align_divs_internal(map2);2445	map2 = isl_map_coalesce(map2);2446	isl_map_free(map2);2447	if (!map2)2448		return -1;2449 2450	return 0;2451}2452 2453/* Check that the union of the basic sets described by "str1" and "str2"2454 * can be coalesced and that the result is equal to the union.2455 * The explicit call to isl_basic_set_union prevents the implicit2456 * equality constraints in the basic maps from being detected prior2457 * to the call to isl_set_coalesce, at least at the point2458 * where this function was introduced.2459 */2460static isl_stat test_coalesce_union(isl_ctx *ctx, const char *str1,2461	const char *str2)2462{2463	isl_basic_set *bset1, *bset2;2464	isl_set *set, *set2;2465	isl_bool equal;2466 2467	bset1 = isl_basic_set_read_from_str(ctx, str1);2468	bset2 = isl_basic_set_read_from_str(ctx, str2);2469	set = isl_basic_set_union(bset1, bset2);2470	set = isl_set_coalesce(set);2471 2472	bset1 = isl_basic_set_read_from_str(ctx, str1);2473	bset2 = isl_basic_set_read_from_str(ctx, str2);2474	set2 = isl_basic_set_union(bset1, bset2);2475 2476	equal = isl_set_is_equal(set, set2);2477	isl_set_free(set);2478	isl_set_free(set2);2479 2480	if (equal < 0)2481		return isl_stat_error;2482	if (!equal)2483		isl_die(ctx, isl_error_unknown,2484			"coalesced set not equal to input",2485			return isl_stat_error);2486 2487	return isl_stat_non_null(set);2488}2489 2490/* A specialized coalescing test case that would result in an assertion2491 * in an earlier version of isl.  Use test_coalesce_union with2492 * an explicit call to isl_basic_set_union to prevent the implicit2493 * equality constraints in the first basic map from being detected prior2494 * to the call to isl_set_coalesce, at least at the point2495 * where this test case was introduced.2496 */2497static isl_stat test_coalesce_special2(struct isl_ctx *ctx)2498{2499	const char *str1;2500	const char *str2;2501 2502	str1 = "{ [x, y] : x, y >= 0 and x + 2y <= 1 and 2x + y <= 1 }";2503	str2 = "{ [x,0] : -1 <= x <= 1 and x mod 2 = 1 }";2504	return test_coalesce_union(ctx, str1, str2);2505}2506 2507/* Check that calling isl_set_coalesce does not leave other sets2508 * that may share some information with the input to isl_set_coalesce2509 * in an inconsistent state.2510 * In particular, older versions of isl would modify all copies2511 * of the basic sets in the isl_set_coalesce input in a way2512 * that could leave them in an inconsistent state.2513 * The result of printing any other set containing one of these2514 * basic sets would then result in an invalid set description.2515 */2516static int test_coalesce_special3(isl_ctx *ctx)2517{2518	const char *str;2519	char *s;2520	isl_set *set1, *set2;2521	isl_printer *p;2522 2523	set1 = isl_set_read_from_str(ctx, "{ [0, 0, 0] }");2524	str = "{ [a, b, a + b] : a >= 0 and b >= 0 and 0 < a + b }";2525	set2 = isl_set_read_from_str(ctx, str);2526	set1 = isl_set_union(set1, isl_set_copy(set2));2527	set1 = isl_set_coalesce(set1);2528	isl_set_free(set1);2529 2530	p = isl_printer_to_str(ctx);2531	p = isl_printer_print_set(p, set2);2532	isl_set_free(set2);2533	s = isl_printer_get_str(p);2534	isl_printer_free(p);2535	set1 = isl_set_read_from_str(ctx, s);2536	free(s);2537	isl_set_free(set1);2538 2539	if (!set1)2540		return -1;2541 2542	return 0;2543}2544 2545/* Check that calling isl_set_coalesce on the intersection of2546 * the sets described by "s1" and "s2" does not leave other sets2547 * that may share some information with the input to isl_set_coalesce2548 * in an inconsistent state.2549 * In particular, when isl_set_coalesce detects equality constraints,2550 * it does not immediately perform Gaussian elimination on them,2551 * but then it needs to ensure that it is performed at some point.2552 * The input set has implicit equality constraints in the first disjunct.2553 * It is constructed as an intersection, because otherwise2554 * those equality constraints would already be detected during parsing.2555 */2556static isl_stat test_coalesce_intersection(isl_ctx *ctx,2557	const char *s1, const char *s2)2558{2559	isl_set *set1, *set2;2560 2561	set1 = isl_set_read_from_str(ctx, s1);2562	set2 = isl_set_read_from_str(ctx, s2);2563	set1 = isl_set_intersect(set1, set2);2564	isl_set_free(isl_set_coalesce(isl_set_copy(set1)));2565	set1 = isl_set_coalesce(set1);2566	isl_set_free(set1);2567 2568	if (!set1)2569		return isl_stat_error;2570 2571	return isl_stat_ok;2572}2573 2574/* Check that calling isl_set_coalesce does not leave other sets2575 * that may share some information with the input to isl_set_coalesce2576 * in an inconsistent state, for the case where one disjunct2577 * is a subset of the other.2578 */2579static isl_stat test_coalesce_special4(isl_ctx *ctx)2580{2581	const char *s1, *s2;2582 2583	s1 = "{ [a, b] : b <= 0 or a <= 1 }";2584	s2 = "{ [a, b] : -1 <= -a < b }";2585	return test_coalesce_intersection(ctx, s1, s2);2586}2587 2588/* Check that calling isl_set_coalesce does not leave other sets2589 * that may share some information with the input to isl_set_coalesce2590 * in an inconsistent state, for the case where two disjuncts2591 * can be fused.2592 */2593static isl_stat test_coalesce_special5(isl_ctx *ctx)2594{2595	const char *s1, *s2;2596 2597	s1 = "{ [a, b, c] : b <= 0 }";2598	s2 = "{ [a, b, c] : -1 <= -a < b and (c >= 0 or c < 0) }";2599	return test_coalesce_intersection(ctx, s1, s2);2600}2601 2602/* Check that calling isl_set_coalesce does not leave other sets2603 * that may share some information with the input to isl_set_coalesce2604 * in an inconsistent state, for the case where two disjuncts2605 * can be fused and where both disjuncts have implicit equality constraints.2606 */2607static isl_stat test_coalesce_special6(isl_ctx *ctx)2608{2609	const char *s1, *s2;2610 2611	s1 = "{ [a, b, c] : c <= 0 }";2612	s2 = "{ [a, b, c] : 0 <= a <= b <= c or (0 <= b <= c and a > 0) }";2613	return test_coalesce_intersection(ctx, s1, s2);2614}2615 2616/* A specialized coalescing test case that would result in an assertion failure2617 * in an earlier version of isl.  Use test_coalesce_union with2618 * an explicit call to isl_basic_set_union to prevent the implicit2619 * equality constraints in the basic maps from being detected prior2620 * to the call to isl_set_coalesce, at least at the point2621 * where this test case was introduced.2622 */2623static isl_stat test_coalesce_special7(isl_ctx *ctx)2624{2625	const char *str1;2626	const char *str2;2627 2628	str1 = "{ [a, b, c=0:17] : a <= 7 and 2b <= 11 - a and "2629			"c <= -7 + 2a and 2c >= - 3 + 3a - 2b }";2630	str2 = "{ [a, b, c] : c > -15a and c >= -7 + 2a and c < 0 and "2631			"3c <= -5 + 5a - 3b and 2b >= 11 - a }";2632	return test_coalesce_union(ctx, str1, str2);2633}2634 2635/* A specialized coalescing test case that would result in a disjunct2636 * getting dropped in an earlier version of isl.  Use test_coalesce_union with2637 * an explicit call to isl_basic_set_union to prevent the implicit2638 * equality constraints in the basic maps from being detected prior2639 * to the call to isl_set_coalesce, at least at the point2640 * where this test case was introduced.2641 */2642static isl_stat test_coalesce_special8(isl_ctx *ctx)2643{2644	const char *str1;2645	const char *str2;2646 2647	str1 = "{ [a, b, c] : 2c <= -a and b >= -a and b <= 5 and "2648			"6c > -7a and 11c >= -5a - b and a <= 3 }";2649	str2 = "{ [a, b, c] : 6c > -7a and b >= -a and b <= 5 and "2650			"11c >= -5a - b and a >= 4 and 2b <= a and 2c <= -a }";2651	return test_coalesce_union(ctx, str1, str2);2652}2653 2654/* Test the functionality of isl_set_coalesce.2655 * That is, check that the output is always equal to the input2656 * and in some cases that the result consists of a single disjunct.2657 */2658static int test_coalesce(struct isl_ctx *ctx)2659{2660	int i;2661 2662	for (i = 0; i < ARRAY_SIZE(coalesce_tests); ++i) {2663		const char *str = coalesce_tests[i].str;2664		int check_one = coalesce_tests[i].single_disjunct;2665		if (test_coalesce_set(ctx, str, check_one) < 0)2666			return -1;2667	}2668 2669	if (test_coalesce_unbounded_wrapping(ctx) < 0)2670		return -1;2671	if (test_coalesce_special(ctx) < 0)2672		return -1;2673	if (test_coalesce_special2(ctx) < 0)2674		return -1;2675	if (test_coalesce_special3(ctx) < 0)2676		return -1;2677	if (test_coalesce_special4(ctx) < 0)2678		return -1;2679	if (test_coalesce_special5(ctx) < 0)2680		return -1;2681	if (test_coalesce_special6(ctx) < 0)2682		return -1;2683	if (test_coalesce_special7(ctx) < 0)2684		return -1;2685	if (test_coalesce_special8(ctx) < 0)2686		return -1;2687 2688	return 0;2689}2690 2691/* Construct a representation of the graph on the right of Figure 12692 * in "Computing the Transitive Closure of a Union of2693 * Affine Integer Tuple Relations".2694 */2695static __isl_give isl_map *cocoa_fig_1_right_graph(isl_ctx *ctx)2696{2697	isl_set *dom;2698	isl_map *up, *right;2699 2700	dom = isl_set_read_from_str(ctx,2701		"{ [x,y] : x >= 0 and -2 x + 3 y >= 0 and x <= 3 and "2702			"2 x - 3 y + 3 >= 0 }");2703	right = isl_map_read_from_str(ctx,2704		"{ [x,y] -> [x2,y2] : x2 = x + 1 and y2 = y }");2705	up = isl_map_read_from_str(ctx,2706		"{ [x,y] -> [x2,y2] : x2 = x and y2 = y + 1 }");2707	right = isl_map_intersect_domain(right, isl_set_copy(dom));2708	right = isl_map_intersect_range(right, isl_set_copy(dom));2709	up = isl_map_intersect_domain(up, isl_set_copy(dom));2710	up = isl_map_intersect_range(up, dom);2711	return isl_map_union(up, right);2712}2713 2714/* Construct a representation of the power of the graph2715 * on the right of Figure 1 in "Computing the Transitive Closure of2716 * a Union of Affine Integer Tuple Relations".2717 */2718static __isl_give isl_map *cocoa_fig_1_right_power(isl_ctx *ctx)2719{2720	return isl_map_read_from_str(ctx,2721		"{ [1] -> [[0,0] -> [0,1]]; [2] -> [[0,0] -> [1,1]]; "2722		"  [1] -> [[0,1] -> [1,1]]; [1] -> [[2,2] -> [3,2]]; "2723		"  [2] -> [[2,2] -> [3,3]]; [1] -> [[3,2] -> [3,3]] }");2724}2725 2726/* Construct a representation of the transitive closure of the graph2727 * on the right of Figure 1 in "Computing the Transitive Closure of2728 * a Union of Affine Integer Tuple Relations".2729 */2730static __isl_give isl_map *cocoa_fig_1_right_tc(isl_ctx *ctx)2731{2732	return isl_set_unwrap(isl_map_range(cocoa_fig_1_right_power(ctx)));2733}2734 2735static int test_closure(isl_ctx *ctx)2736{2737	const char *str;2738	isl_map *map, *map2;2739	isl_bool exact, equal;2740 2741	/* COCOA example 1 */2742	map = isl_map_read_from_str(ctx,2743		"[n] -> { [i,j] -> [i2,j2] : i2 = i + 1 and j2 = j + 1 and "2744			"1 <= i and i < n and 1 <= j and j < n or "2745			"i2 = i + 1 and j2 = j - 1 and "2746			"1 <= i and i < n and 2 <= j and j <= n }");2747	map = isl_map_power(map, &exact);2748	assert(exact);2749	isl_map_free(map);2750 2751	/* COCOA example 1 */2752	map = isl_map_read_from_str(ctx,2753		"[n] -> { [i,j] -> [i2,j2] : i2 = i + 1 and j2 = j + 1 and "2754			"1 <= i and i < n and 1 <= j and j < n or "2755			"i2 = i + 1 and j2 = j - 1 and "2756			"1 <= i and i < n and 2 <= j and j <= n }");2757	map = isl_map_transitive_closure(map, &exact);2758	assert(exact);2759	map2 = isl_map_read_from_str(ctx,2760		"[n] -> { [i,j] -> [i2,j2] : exists (k1,k2,k : "2761			"1 <= i and i < n and 1 <= j and j <= n and "2762			"2 <= i2 and i2 <= n and 1 <= j2 and j2 <= n and "2763			"i2 = i + k1 + k2 and j2 = j + k1 - k2 and "2764			"k1 >= 0 and k2 >= 0 and k1 + k2 = k and k >= 1 )}");2765	assert(isl_map_is_equal(map, map2));2766	isl_map_free(map2);2767	isl_map_free(map);2768 2769	map = isl_map_read_from_str(ctx,2770		"[n] -> { [x] -> [y] : y = x + 1 and 0 <= x and x <= n and "2771				     " 0 <= y and y <= n }");2772	map = isl_map_transitive_closure(map, &exact);2773	map2 = isl_map_read_from_str(ctx,2774		"[n] -> { [x] -> [y] : y > x and 0 <= x and x <= n and "2775				     " 0 <= y and y <= n }");2776	assert(isl_map_is_equal(map, map2));2777	isl_map_free(map2);2778	isl_map_free(map);2779 2780	/* COCOA example 2 */2781	map = isl_map_read_from_str(ctx,2782		"[n] -> { [i,j] -> [i2,j2] : i2 = i + 2 and j2 = j + 2 and "2783			"1 <= i and i < n - 1 and 1 <= j and j < n - 1 or "2784			"i2 = i + 2 and j2 = j - 2 and "2785			"1 <= i and i < n - 1 and 3 <= j and j <= n }");2786	map = isl_map_transitive_closure(map, &exact);2787	assert(exact);2788	map2 = isl_map_read_from_str(ctx,2789		"[n] -> { [i,j] -> [i2,j2] : exists (k1,k2,k : "2790			"1 <= i and i < n - 1 and 1 <= j and j <= n and "2791			"3 <= i2 and i2 <= n and 1 <= j2 and j2 <= n and "2792			"i2 = i + 2 k1 + 2 k2 and j2 = j + 2 k1 - 2 k2 and "2793			"k1 >= 0 and k2 >= 0 and k1 + k2 = k and k >= 1) }");2794	assert(isl_map_is_equal(map, map2));2795	isl_map_free(map);2796	isl_map_free(map2);2797 2798	/* COCOA Fig.2 left */2799	map = isl_map_read_from_str(ctx,2800		"[n] -> { [i,j] -> [i2,j2] : i2 = i + 2 and j2 = j and "2801			"i <= 2 j - 3 and i <= n - 2 and j <= 2 i - 1 and "2802			"j <= n or "2803			"i2 = i and j2 = j + 2 and i <= 2 j - 1 and i <= n and "2804			"j <= 2 i - 3 and j <= n - 2 or "2805			"i2 = i + 1 and j2 = j + 1 and i <= 2 j - 1 and "2806			"i <= n - 1 and j <= 2 i - 1 and j <= n - 1 }");2807	map = isl_map_transitive_closure(map, &exact);2808	assert(exact);2809	isl_map_free(map);2810 2811	/* COCOA Fig.2 right */2812	map = isl_map_read_from_str(ctx,2813		"[n] -> { [i,j] -> [i2,j2] : i2 = i + 3 and j2 = j and "2814			"i <= 2 j - 4 and i <= n - 3 and j <= 2 i - 1 and "2815			"j <= n or "2816			"i2 = i and j2 = j + 3 and i <= 2 j - 1 and i <= n and "2817			"j <= 2 i - 4 and j <= n - 3 or "2818			"i2 = i + 1 and j2 = j + 1 and i <= 2 j - 1 and "2819			"i <= n - 1 and j <= 2 i - 1 and j <= n - 1 }");2820	map = isl_map_power(map, &exact);2821	assert(exact);2822	isl_map_free(map);2823 2824	/* COCOA Fig.2 right */2825	map = isl_map_read_from_str(ctx,2826		"[n] -> { [i,j] -> [i2,j2] : i2 = i + 3 and j2 = j and "2827			"i <= 2 j - 4 and i <= n - 3 and j <= 2 i - 1 and "2828			"j <= n or "2829			"i2 = i and j2 = j + 3 and i <= 2 j - 1 and i <= n and "2830			"j <= 2 i - 4 and j <= n - 3 or "2831			"i2 = i + 1 and j2 = j + 1 and i <= 2 j - 1 and "2832			"i <= n - 1 and j <= 2 i - 1 and j <= n - 1 }");2833	map = isl_map_transitive_closure(map, &exact);2834	assert(exact);2835	map2 = isl_map_read_from_str(ctx,2836		"[n] -> { [i,j] -> [i2,j2] : exists (k1,k2,k3,k : "2837			"i <= 2 j - 1 and i <= n and j <= 2 i - 1 and "2838			"j <= n and 3 + i + 2 j <= 3 n and "2839			"3 + 2 i + j <= 3n and i2 <= 2 j2 -1 and i2 <= n and "2840			"i2 <= 3 j2 - 4 and j2 <= 2 i2 -1 and j2 <= n and "2841			"13 + 4 j2 <= 11 i2 and i2 = i + 3 k1 + k3 and "2842			"j2 = j + 3 k2 + k3 and k1 >= 0 and k2 >= 0 and "2843			"k3 >= 0 and k1 + k2 + k3 = k and k > 0) }");2844	assert(isl_map_is_equal(map, map2));2845	isl_map_free(map2);2846	isl_map_free(map);2847 2848	map = cocoa_fig_1_right_graph(ctx);2849	map = isl_map_transitive_closure(map, &exact);2850	assert(exact);2851	map2 = cocoa_fig_1_right_tc(ctx);2852	assert(isl_map_is_equal(map, map2));2853	isl_map_free(map2);2854	isl_map_free(map);2855 2856	map = cocoa_fig_1_right_graph(ctx);2857	map = isl_map_power(map, &exact);2858	map2 = cocoa_fig_1_right_power(ctx);2859	equal = isl_map_is_equal(map, map2);2860	isl_map_free(map2);2861	isl_map_free(map);2862	if (equal < 0)2863		return -1;2864	if (!exact)2865		isl_die(ctx, isl_error_unknown, "power not exact", return -1);2866	if (!equal)2867		isl_die(ctx, isl_error_unknown, "unexpected power", return -1);2868 2869	/* COCOA Theorem 1 counter example */2870	map = isl_map_read_from_str(ctx,2871		"{ [i,j] -> [i2,j2] : i = 0 and 0 <= j and j <= 1 and "2872			"i2 = 1 and j2 = j or "2873			"i = 0 and j = 0 and i2 = 0 and j2 = 1 }");2874	map = isl_map_transitive_closure(map, &exact);2875	assert(exact);2876	isl_map_free(map);2877 2878	map = isl_map_read_from_str(ctx,2879		"[m,n] -> { [i,j] -> [i2,j2] : i2 = i and j2 = j + 2 and "2880			"1 <= i,i2 <= n and 1 <= j,j2 <= m or "2881			"i2 = i + 1 and 3 <= j2 - j <= 4 and "2882			"1 <= i,i2 <= n and 1 <= j,j2 <= m }");2883	map = isl_map_transitive_closure(map, &exact);2884	assert(exact);2885	isl_map_free(map);2886 2887	/* Kelly et al 1996, fig 12 */2888	map = isl_map_read_from_str(ctx,2889		"[n] -> { [i,j] -> [i2,j2] : i2 = i and j2 = j + 1 and "2890			"1 <= i,j,j+1 <= n or "2891			"j = n and j2 = 1 and i2 = i + 1 and "2892			"1 <= i,i+1 <= n }");2893	map = isl_map_transitive_closure(map, &exact);2894	assert(exact);2895	map2 = isl_map_read_from_str(ctx,2896		"[n] -> { [i,j] -> [i2,j2] : 1 <= j < j2 <= n and "2897			"1 <= i <= n and i = i2 or "2898			"1 <= i < i2 <= n and 1 <= j <= n and "2899			"1 <= j2 <= n }");2900	assert(isl_map_is_equal(map, map2));2901	isl_map_free(map2);2902	isl_map_free(map);2903 2904	/* Omega's closure4 */2905	map = isl_map_read_from_str(ctx,2906		"[m,n] -> { [x,y] -> [x2,y2] : x2 = x and y2 = y + 1 and "2907			"1 <= x,y <= 10 or "2908			"x2 = x + 1 and y2 = y and "2909			"1 <= x <= 20 && 5 <= y <= 15 }");2910	map = isl_map_transitive_closure(map, &exact);2911	assert(exact);2912	isl_map_free(map);2913 2914	map = isl_map_read_from_str(ctx,2915		"[n] -> { [x] -> [y]: 1 <= n <= y - x <= 10 }");2916	map = isl_map_transitive_closure(map, &exact);2917	assert(!exact);2918	map2 = isl_map_read_from_str(ctx,2919		"[n] -> { [x] -> [y] : 1 <= n <= 10 and y >= n + x }");2920	assert(isl_map_is_equal(map, map2));2921	isl_map_free(map);2922	isl_map_free(map2);2923 2924	str = "[n, m] -> { [i0, i1, i2, i3] -> [o0, o1, o2, o3] : "2925	    "i3 = 1 and o0 = i0 and o1 = -1 + i1 and o2 = -1 + i2 and "2926	    "o3 = -2 + i2 and i1 <= -1 + i0 and i1 >= 1 - m + i0 and "2927	    "i1 >= 2 and i1 <= n and i2 >= 3 and i2 <= 1 + n and i2 <= m }";2928	map = isl_map_read_from_str(ctx, str);2929	map = isl_map_transitive_closure(map, &exact);2930	assert(exact);2931	map2 = isl_map_read_from_str(ctx, str);2932	assert(isl_map_is_equal(map, map2));2933	isl_map_free(map);2934	isl_map_free(map2);2935 2936	str = "{[0] -> [1]; [2] -> [3]}";2937	map = isl_map_read_from_str(ctx, str);2938	map = isl_map_transitive_closure(map, &exact);2939	assert(exact);2940	map2 = isl_map_read_from_str(ctx, str);2941	assert(isl_map_is_equal(map, map2));2942	isl_map_free(map);2943	isl_map_free(map2);2944 2945	str = "[n] -> { [[i0, i1, 1, 0, i0] -> [i5, 1]] -> "2946	    "[[i0, -1 + i1, 2, 0, i0] -> [-1 + i5, 2]] : "2947	    "exists (e0 = [(3 - n)/3]: i5 >= 2 and i1 >= 2 and "2948	    "3i0 <= -1 + n and i1 <= -1 + n and i5 <= -1 + n and "2949	    "3e0 >= 1 - n and 3e0 <= 2 - n and 3i0 >= -2 + n); "2950	    "[[i0, i1, 2, 0, i0] -> [i5, 1]] -> "2951	    "[[i0, i1, 1, 0, i0] -> [-1 + i5, 2]] : "2952	    "exists (e0 = [(3 - n)/3]: i5 >= 2 and i1 >= 1 and "2953	    "3i0 <= -1 + n and i1 <= -1 + n and i5 <= -1 + n and "2954	    "3e0 >= 1 - n and 3e0 <= 2 - n and 3i0 >= -2 + n); "2955	    "[[i0, i1, 1, 0, i0] -> [i5, 2]] -> "2956	    "[[i0, -1 + i1, 2, 0, i0] -> [i5, 1]] : "2957	    "exists (e0 = [(3 - n)/3]: i1 >= 2 and i5 >= 1 and "2958	    "3i0 <= -1 + n and i1 <= -1 + n and i5 <= -1 + n and "2959	    "3e0 >= 1 - n and 3e0 <= 2 - n and 3i0 >= -2 + n); "2960	    "[[i0, i1, 2, 0, i0] -> [i5, 2]] -> "2961	    "[[i0, i1, 1, 0, i0] -> [i5, 1]] : "2962	    "exists (e0 = [(3 - n)/3]: i5 >= 1 and i1 >= 1 and "2963	    "3i0 <= -1 + n and i1 <= -1 + n and i5 <= -1 + n and "2964	    "3e0 >= 1 - n and 3e0 <= 2 - n and 3i0 >= -2 + n) }";2965	map = isl_map_read_from_str(ctx, str);2966	map = isl_map_transitive_closure(map, NULL);2967	assert(map);2968	isl_map_free(map);2969 2970	return 0;2971}2972 2973/* Check that the actual result of a boolean operation is equal2974 * to the expected result.2975 */2976static isl_stat check_bool(isl_ctx *ctx, isl_bool actual, isl_bool expected)2977{2978	if (actual != expected)2979		isl_die(ctx, isl_error_unknown,2980			"incorrect boolean operation", return isl_stat_error);2981	return isl_stat_ok;2982}2983 2984/* Test operations on isl_bool values.2985 *2986 * This tests:2987 *2988 * 	isl_bool_not2989 * 	isl_bool_ok2990 */2991static int test_isl_bool(isl_ctx *ctx)2992{2993	if (check_bool(ctx, isl_bool_not(isl_bool_true), isl_bool_false) < 0)2994		return -1;2995	if (check_bool(ctx, isl_bool_not(isl_bool_false), isl_bool_true) < 0)2996		return -1;2997	if (check_bool(ctx, isl_bool_not(isl_bool_error), isl_bool_error) < 0)2998		return -1;2999	if (check_bool(ctx, isl_bool_ok(0), isl_bool_false) < 0)3000		return -1;3001	if (check_bool(ctx, isl_bool_ok(1), isl_bool_true) < 0)3002		return -1;3003	if (check_bool(ctx, isl_bool_ok(-1), isl_bool_true) < 0)3004		return -1;3005	if (check_bool(ctx, isl_bool_ok(2), isl_bool_true) < 0)3006		return -1;3007	if (check_bool(ctx, isl_bool_ok(-2), isl_bool_true) < 0)3008		return -1;3009 3010	return 0;3011}3012 3013static int test_lex(struct isl_ctx *ctx)3014{3015	isl_space *space;3016	isl_map *map;3017	int empty;3018 3019	space = isl_space_set_alloc(ctx, 0, 0);3020	map = isl_map_lex_le(space);3021	empty = isl_map_is_empty(map);3022	isl_map_free(map);3023 3024	if (empty < 0)3025		return -1;3026	if (empty)3027		isl_die(ctx, isl_error_unknown,3028			"expecting non-empty result", return -1);3029 3030	return 0;3031}3032 3033/* Inputs for isl_map_lexmin tests.3034 * "map" is the input and "lexmin" is the expected result.3035 */3036struct {3037	const char *map;3038	const char *lexmin;3039} lexmin_tests [] = {3040	{ "{ [x] -> [y] : x <= y <= 10; [x] -> [5] : -8 <= x <= 8 }",3041	  "{ [x] -> [5] : 6 <= x <= 8; "3042	    "[x] -> [x] : x <= 5 or (9 <= x <= 10) }" },3043	{ "{ [x] -> [y] : 4y = x or 4y = -1 + x or 4y = -2 + x }",3044	  "{ [x] -> [y] : 4y = x or 4y = -1 + x or 4y = -2 + x }" },3045	{ "{ [x] -> [y] : x = 4y; [x] -> [y] : x = 2y }",3046	  "{ [x] -> [y] : (4y = x and x >= 0) or "3047		"(exists (e0 = [(x)/4], e1 = [(-2 + x)/4]: 2y = x and "3048		"4e1 = -2 + x and 4e0 <= -1 + x and 4e0 >= -3 + x)) or "3049		"(exists (e0 = [(x)/4]: 2y = x and 4e0 = x and x <= -4)) }" },3050	{ "{ T[a] -> S[b, c] : a = 4b-2c and c >= b }",3051	  "{ T[a] -> S[b, c] : 2b = a and 2c = a }" },3052	/* Check that empty pieces are properly combined. */3053	{ "[K, N] -> { [x, y] -> [a, b] : K+2<=N<=K+4 and x>=4 and "3054		"2N-6<=x<K+N and N-1<=a<=K+N-1 and N+b-6<=a<=2N-4 and "3055		"b<=2N-3K+a and 3b<=4N-K+1 and b>=N and a>=x+1 }",3056	  "[K, N] -> { [x, y] -> [1 + x, N] : x >= -6 + 2N and "3057		"x <= -5 + 2N and x >= -1 + 3K - N and x <= -2 + K + N and "3058		"x >= 4 }" },3059	{ "{ [i, k, j] -> [a, b, c, d] : 8*floor((b)/8) = b and k <= 255 and "3060		"a <= 255 and c <= 255 and d <= 255 - j and "3061		"255 - j <= 7d <= 7 - i and 240d <= 239 + a and "3062		"247d <= 247 + k - j and 247d <= 247 + k - b and "3063		"247d <= 247 + i and 248 - b <= 248d <= c and "3064		"254d >= i - a + b and 254d >= -a + b and "3065		"255d >= -i + a - b and 1792d >= -63736 + 257b }",3066	  "{ [i, k, j] -> "3067	    "[-127762 + i + 502j, -62992 + 248j, 63240 - 248j, 255 - j] : "3068		"k <= 255 and 7j >= 1778 + i and 246j >= 62738 - k and "3069		"247j >= 62738 - i and 509j <= 129795 + i and "3070		"742j >= 188724 - i; "3071	    "[0, k, j] -> [1, 0, 248, 1] : k <= 255 and 248 <= j <= 254, k }" },3072	{ "{ [a] -> [b] : 0 <= b <= 255 and -509 + a <= 512b < a and "3073			"16*floor((8 + b)/16) <= 7 + b; "3074	    "[a] -> [1] }",3075	  "{ [a] -> [b = 1] : a >= 510 or a <= 0; "3076	    "[a] -> [b = 0] : 0 < a <= 509 }" },3077	{ "{ rat: [i] : 1 <= 2i <= 9 }", "{ rat: [i] : 2i = 1 }" },3078	{ "{ rat: [i] : 1 <= 2i <= 9 or i >= 10 }", "{ rat: [i] : 2i = 1 }" },3079	{ "{ rat: [i] : 21 <= 2i <= 29 or i = 5 }", "{ rat: [5] }" },3080};3081 3082static int test_lexmin(struct isl_ctx *ctx)3083{3084	int i;3085	int equal;3086	const char *str;3087	isl_basic_map *bmap;3088	isl_map *map, *map2;3089	isl_set *set;3090	isl_set *set2;3091	isl_pw_multi_aff *pma;3092 3093	str = "[p0, p1] -> { [] -> [] : "3094	    "exists (e0 = [(2p1)/3], e1, e2, e3 = [(3 - p1 + 3e0)/3], "3095	    "e4 = [(p1)/3], e5 = [(p1 + 3e4)/3]: "3096	    "3e0 >= -2 + 2p1 and 3e0 >= p1 and 3e3 >= 1 - p1 + 3e0 and "3097	    "3e0 <= 2p1 and 3e3 >= -2 + p1 and 3e3 <= -1 + p1 and p1 >= 3 and "3098	    "3e5 >= -2 + 2p1 and 3e5 >= p1 and 3e5 <= -1 + p1 + 3e4 and "3099	    "3e4 <= p1 and 3e4 >= -2 + p1 and e3 <= -1 + e0 and "3100	    "3e4 >= 6 - p1 + 3e1 and 3e1 >= p1 and 3e5 >= -2 + p1 + 3e4 and "3101	    "2e4 >= 3 - p1 + 2e1 and e4 <= e1 and 3e3 <= 2 - p1 + 3e0 and "3102	    "e5 >= 1 + e1 and 3e4 >= 6 - 2p1 + 3e1 and "3103	    "p0 >= 2 and p1 >= p0 and 3e2 >= p1 and 3e4 >= 6 - p1 + 3e2 and "3104	    "e2 <= e1 and e3 >= 1 and e4 <= e2) }";3105	map = isl_map_read_from_str(ctx, str);3106	map = isl_map_lexmin(map);3107	isl_map_free(map);3108	if (!map)3109		return -1;3110 3111	str = "[C] -> { [obj,a,b,c] : obj <= 38 a + 7 b + 10 c and "3112	    "a + b <= 1 and c <= 10 b and c <= C and a,b,c,C >= 0 }";3113	set = isl_set_read_from_str(ctx, str);3114	set = isl_set_lexmax(set);3115	str = "[C] -> { [obj,a,b,c] : C = 8 }";3116	set2 = isl_set_read_from_str(ctx, str);3117	set = isl_set_intersect(set, set2);3118	assert(!isl_set_is_empty(set));3119	isl_set_free(set);3120 3121	for (i = 0; i < ARRAY_SIZE(lexmin_tests); ++i) {3122		map = isl_map_read_from_str(ctx, lexmin_tests[i].map);3123		map = isl_map_lexmin(map);3124		map2 = isl_map_read_from_str(ctx, lexmin_tests[i].lexmin);3125		equal = isl_map_is_equal(map, map2);3126		isl_map_free(map);3127		isl_map_free(map2);3128 3129		if (equal < 0)3130			return -1;3131		if (!equal)3132			isl_die(ctx, isl_error_unknown,3133				"unexpected result", return -1);3134	}3135 3136	str = "{ [i] -> [i', j] : j = i - 8i' and i' >= 0 and i' <= 7 and "3137				" 8i' <= i and 8i' >= -7 + i }";3138	bmap = isl_basic_map_read_from_str(ctx, str);3139	pma = isl_basic_map_lexmin_pw_multi_aff(isl_basic_map_copy(bmap));3140	map2 = isl_map_from_pw_multi_aff(pma);3141	map = isl_map_from_basic_map(bmap);3142	assert(isl_map_is_equal(map, map2));3143	isl_map_free(map);3144	isl_map_free(map2);3145 3146	str = "[i] -> { [i', j] : j = i - 8i' and i' >= 0 and i' <= 7 and "3147				" 8i' <= i and 8i' >= -7 + i }";3148	set = isl_set_read_from_str(ctx, str);3149	pma = isl_set_lexmin_pw_multi_aff(isl_set_copy(set));3150	set2 = isl_set_from_pw_multi_aff(pma);3151	equal = isl_set_is_equal(set, set2);3152	isl_set_free(set);3153	isl_set_free(set2);3154	if (equal < 0)3155		return -1;3156	if (!equal)3157		isl_die(ctx, isl_error_unknown,3158			"unexpected difference between set and "3159			"piecewise affine expression", return -1);3160 3161	return 0;3162}3163 3164/* Inputs for isl_pw_multi_aff_max_multi_val tests.3165 * "pma" is the input.3166 * "res" is the expected result.3167 */3168static struct {3169	const char *pma;3170	const char *res;3171} opt_pw_tests[] = {3172	{ "{ [-1] -> [-1]; [1] -> [1] }", "{ [1] }" },3173	{ "{ [a, b] -> [floor((b - 2*floor((-a)/4))/5)] : "3174	    "0 <= a, b <= 100 and b mod 2 = 0}", "{ [30] }" },3175	{ "[N] -> { [i,j] -> A[i, -i, i + j] : 0 <= i,j <= N <= 10 }",3176	  "{ A[10, 0, 20] }" },3177	{ "[N] -> {A[N, -N, 2N] : 0 <= N }", "{ A[infty, 0, infty] }" },3178};3179 3180/* Perform basic isl_pw_multi_aff_max_multi_val tests.3181 */3182static isl_stat test_pw_max(struct isl_ctx *ctx)3183{3184	int i;3185	isl_pw_multi_aff *pma;3186	isl_multi_val *mv;3187	isl_stat r;3188 3189	for (i = 0; i < ARRAY_SIZE(opt_pw_tests); ++i) {3190		pma = isl_pw_multi_aff_read_from_str(ctx, opt_pw_tests[i].pma);3191		mv = isl_pw_multi_aff_max_multi_val(pma);3192		r = multi_val_check_plain_equal(mv, opt_pw_tests[i].res);3193		isl_multi_val_free(mv);3194 3195		if (r < 0)3196			return isl_stat_error;3197	}3198 3199	return isl_stat_ok;3200}3201 3202/* A specialized isl_set_min_val test case that would return the wrong result3203 * in earlier versions of isl.3204 * The explicit call to isl_basic_set_union prevents the second basic set3205 * from being determined to be empty prior to the call to isl_set_min_val,3206 * at least at the point where this test case was introduced.3207 */3208static int test_min_special(isl_ctx *ctx)3209{3210	const char *str;3211	isl_basic_set *bset1, *bset2;3212	isl_set *set;3213	isl_aff *obj;3214	isl_val *res;3215	int ok;3216 3217	str = "{ [a, b] : a >= 2 and b >= 0 and 14 - a <= b <= 9 }";3218	bset1 = isl_basic_set_read_from_str(ctx, str);3219	str = "{ [a, b] : 1 <= a, b and a + b <= 1 }";3220	bset2 = isl_basic_set_read_from_str(ctx, str);3221	set = isl_basic_set_union(bset1, bset2);3222	obj = isl_aff_read_from_str(ctx, "{ [a, b] -> [a] }");3223 3224	res = isl_set_min_val(set, obj);3225	ok = isl_val_cmp_si(res, 5) == 0;3226 3227	isl_aff_free(obj);3228	isl_set_free(set);3229	isl_val_free(res);3230 3231	if (!res)3232		return -1;3233	if (!ok)3234		isl_die(ctx, isl_error_unknown, "unexpected minimum",3235			return -1);3236 3237	return 0;3238}3239 3240/* A specialized isl_set_min_val test case that would return an error3241 * in earlier versions of isl.3242 */3243static int test_min_special2(isl_ctx *ctx)3244{3245	const char *str;3246	isl_basic_set *bset;3247	isl_aff *obj;3248	isl_val *res;3249 3250	str = "{ [i, j, k] : 2j = i and 2k = i + 1 and i >= 2 }";3251	bset = isl_basic_set_read_from_str(ctx, str);3252 3253	obj = isl_aff_read_from_str(ctx, "{ [i, j, k] -> [i] }");3254 3255	res = isl_basic_set_max_val(bset, obj);3256 3257	isl_basic_set_free(bset);3258	isl_aff_free(obj);3259	isl_val_free(res);3260 3261	if (!res)3262		return -1;3263 3264	return 0;3265}3266 3267/* Check that the result of isl_set_min_multi_pw_aff3268 * on the union of the sets with string descriptions "s1" and "s2"3269 * consists of a single expression (on a single cell).3270 */3271static isl_stat check_single_expr_min(isl_ctx *ctx, const char *s1,3272	const char *s2)3273{3274	isl_size n;3275	isl_set *set1, *set2;3276	isl_multi_pw_aff *mpa;3277	isl_pw_multi_aff *pma;3278 3279	set1 = isl_set_read_from_str(ctx, s1);3280	set2 = isl_set_read_from_str(ctx, s2);3281	set1 = isl_set_union(set1, set2);3282	mpa = isl_set_min_multi_pw_aff(set1);3283	pma = isl_pw_multi_aff_from_multi_pw_aff(mpa);3284	n = isl_pw_multi_aff_n_piece(pma);3285	isl_pw_multi_aff_free(pma);3286 3287	if (n < 0)3288		return isl_stat_error;3289	if (n != 1)3290		isl_die(ctx, isl_error_unknown, "expecting single expression",3291			return isl_stat_error);3292	return isl_stat_ok;3293}3294 3295/* A specialized isl_set_min_multi_pw_aff test that checks3296 * that the minimum of 2N and 3N for N >= 0 is represented3297 * by a single expression, without splitting off the special case N = 0.3298 * Do this for both orderings.3299 */3300static int test_min_mpa(isl_ctx *ctx)3301{3302	const char *s1, *s2;3303 3304	s1 = "[N=0:] -> { [1, 3N:] }";3305	s2 = "[N=0:] -> { [10, 2N:] }";3306	if (check_single_expr_min(ctx, s1, s2) < 0)3307		return -1;3308	if (check_single_expr_min(ctx, s2, s1) < 0)3309		return -1;3310 3311	return 0;3312}3313 3314struct {3315	const char *set;3316	const char *obj;3317	__isl_give isl_val *(*fn)(__isl_keep isl_set *set,3318		__isl_keep isl_aff *obj);3319	const char *res;3320} opt_tests[] = {3321	{ "{ [-1]; [1] }", "{ [x] -> [x] }", &isl_set_min_val, "-1" },3322	{ "{ [-1]; [1] }", "{ [x] -> [x] }", &isl_set_max_val, "1" },3323	{ "{ [a, b] : 0 <= a, b <= 100 and b mod 2 = 0}",3324	  "{ [a, b] -> [floor((b - 2*floor((-a)/4))/5)] }",3325	  &isl_set_max_val, "30" },3326 3327};3328 3329/* Perform basic isl_set_min_val and isl_set_max_val tests.3330 * In particular, check the results on non-convex inputs.3331 */3332static int test_min(struct isl_ctx *ctx)3333{3334	int i;3335	isl_set *set;3336	isl_aff *obj;3337	isl_val *val, *res;3338	isl_bool ok;3339 3340	for (i = 0; i < ARRAY_SIZE(opt_tests); ++i) {3341		set = isl_set_read_from_str(ctx, opt_tests[i].set);3342		obj = isl_aff_read_from_str(ctx, opt_tests[i].obj);3343		res = isl_val_read_from_str(ctx, opt_tests[i].res);3344		val = opt_tests[i].fn(set, obj);3345		ok = isl_val_eq(res, val);3346		isl_val_free(res);3347		isl_val_free(val);3348		isl_aff_free(obj);3349		isl_set_free(set);3350 3351		if (ok < 0)3352			return -1;3353		if (!ok)3354			isl_die(ctx, isl_error_unknown,3355				"unexpected optimum", return -1);3356	}3357 3358	if (test_pw_max(ctx) < 0)3359		return -1;3360	if (test_min_special(ctx) < 0)3361		return -1;3362	if (test_min_special2(ctx) < 0)3363		return -1;3364 3365	return 0;3366}3367 3368struct must_may {3369	isl_map *must;3370	isl_map *may;3371};3372 3373static isl_stat collect_must_may(__isl_take isl_map *dep, int must,3374	void *dep_user, void *user)3375{3376	struct must_may *mm = (struct must_may *)user;3377 3378	if (must)3379		mm->must = isl_map_union(mm->must, dep);3380	else3381		mm->may = isl_map_union(mm->may, dep);3382 3383	return isl_stat_ok;3384}3385 3386static int common_space(void *first, void *second)3387{3388	int depth = *(int *)first;3389	return 2 * depth;3390}3391 3392static int map_is_equal(__isl_keep isl_map *map, const char *str)3393{3394	isl_map *map2;3395	int equal;3396 3397	if (!map)3398		return -1;3399 3400	map2 = isl_map_read_from_str(map->ctx, str);3401	equal = isl_map_is_equal(map, map2);3402	isl_map_free(map2);3403 3404	return equal;3405}3406 3407static int map_check_equal(__isl_keep isl_map *map, const char *str)3408{3409	int equal;3410 3411	equal = map_is_equal(map, str);3412	if (equal < 0)3413		return -1;3414	if (!equal)3415		isl_die(isl_map_get_ctx(map), isl_error_unknown,3416			"result not as expected", return -1);3417	return 0;3418}3419 3420/* Is "set" equal to the set described by "str"?3421 */3422static isl_bool set_is_equal(__isl_keep isl_set *set, const char *str)3423{3424	isl_set *set2;3425	isl_bool equal;3426 3427	if (!set)3428		return isl_bool_error;3429 3430	set2 = isl_set_read_from_str(isl_set_get_ctx(set), str);3431	equal = isl_set_is_equal(set, set2);3432	isl_set_free(set2);3433 3434	return equal;3435}3436 3437/* Check that "set" is equal to the set described by "str".3438 */3439static isl_stat set_check_equal(__isl_keep isl_set *set, const char *str)3440{3441	isl_bool equal;3442 3443	equal = set_is_equal(set, str);3444	if (equal < 0)3445		return isl_stat_error;3446	if (!equal)3447		isl_die(isl_set_get_ctx(set), isl_error_unknown,3448			"result not as expected", return isl_stat_error);3449	return isl_stat_ok;3450}3451 3452/* Is "uset" equal to the union set described by "str"?3453 */3454static isl_bool uset_is_equal(__isl_keep isl_union_set *uset, const char *str)3455{3456	isl_union_set *uset2;3457	isl_bool equal;3458 3459	if (!uset)3460		return isl_bool_error;3461 3462	uset2 = isl_union_set_read_from_str(isl_union_set_get_ctx(uset), str);3463	equal = isl_union_set_is_equal(uset, uset2);3464	isl_union_set_free(uset2);3465 3466	return equal;3467}3468 3469/* Check that "uset" is equal to the union set described by "str".3470 */3471static isl_stat uset_check_equal(__isl_keep isl_union_set *uset,3472	const char *str)3473{3474	isl_bool equal;3475 3476	equal = uset_is_equal(uset, str);3477	if (equal < 0)3478		return isl_stat_error;3479	if (!equal)3480		isl_die(isl_union_set_get_ctx(uset), isl_error_unknown,3481			"result not as expected", return isl_stat_error);3482	return isl_stat_ok;3483}3484 3485static int test_dep(struct isl_ctx *ctx)3486{3487	const char *str;3488	isl_space *space;3489	isl_map *map;3490	isl_access_info *ai;3491	isl_flow *flow;3492	int depth;3493	struct must_may mm;3494 3495	depth = 3;3496 3497	str = "{ [2,i,0] -> [i] : 0 <= i <= 10 }";3498	map = isl_map_read_from_str(ctx, str);3499	ai = isl_access_info_alloc(map, &depth, &common_space, 2);3500 3501	str = "{ [0,i,0] -> [i] : 0 <= i <= 10 }";3502	map = isl_map_read_from_str(ctx, str);3503	ai = isl_access_info_add_source(ai, map, 1, &depth);3504 3505	str = "{ [1,i,0] -> [5] : 0 <= i <= 10 }";3506	map = isl_map_read_from_str(ctx, str);3507	ai = isl_access_info_add_source(ai, map, 1, &depth);3508 3509	flow = isl_access_info_compute_flow(ai);3510	space = isl_space_alloc(ctx, 0, 3, 3);3511	mm.must = isl_map_empty(isl_space_copy(space));3512	mm.may = isl_map_empty(space);3513 3514	isl_flow_foreach(flow, collect_must_may, &mm);3515 3516	str = "{ [0,i,0] -> [2,i,0] : (0 <= i <= 4) or (6 <= i <= 10); "3517	      "  [1,10,0] -> [2,5,0] }";3518	assert(map_is_equal(mm.must, str));3519	str = "{ [i,j,k] -> [l,m,n] : 1 = 0 }";3520	assert(map_is_equal(mm.may, str));3521 3522	isl_map_free(mm.must);3523	isl_map_free(mm.may);3524	isl_flow_free(flow);3525 3526 3527	str = "{ [2,i,0] -> [i] : 0 <= i <= 10 }";3528	map = isl_map_read_from_str(ctx, str);3529	ai = isl_access_info_alloc(map, &depth, &common_space, 2);3530 3531	str = "{ [0,i,0] -> [i] : 0 <= i <= 10 }";3532	map = isl_map_read_from_str(ctx, str);3533	ai = isl_access_info_add_source(ai, map, 1, &depth);3534 3535	str = "{ [1,i,0] -> [5] : 0 <= i <= 10 }";3536	map = isl_map_read_from_str(ctx, str);3537	ai = isl_access_info_add_source(ai, map, 0, &depth);3538 3539	flow = isl_access_info_compute_flow(ai);3540	space = isl_space_alloc(ctx, 0, 3, 3);3541	mm.must = isl_map_empty(isl_space_copy(space));3542	mm.may = isl_map_empty(space);3543 3544	isl_flow_foreach(flow, collect_must_may, &mm);3545 3546	str = "{ [0,i,0] -> [2,i,0] : (0 <= i <= 4) or (6 <= i <= 10) }";3547	assert(map_is_equal(mm.must, str));3548	str = "{ [0,5,0] -> [2,5,0]; [1,i,0] -> [2,5,0] : 0 <= i <= 10 }";3549	assert(map_is_equal(mm.may, str));3550 3551	isl_map_free(mm.must);3552	isl_map_free(mm.may);3553	isl_flow_free(flow);3554 3555 3556	str = "{ [2,i,0] -> [i] : 0 <= i <= 10 }";3557	map = isl_map_read_from_str(ctx, str);3558	ai = isl_access_info_alloc(map, &depth, &common_space, 2);3559 3560	str = "{ [0,i,0] -> [i] : 0 <= i <= 10 }";3561	map = isl_map_read_from_str(ctx, str);3562	ai = isl_access_info_add_source(ai, map, 0, &depth);3563 3564	str = "{ [1,i,0] -> [5] : 0 <= i <= 10 }";3565	map = isl_map_read_from_str(ctx, str);3566	ai = isl_access_info_add_source(ai, map, 0, &depth);3567 3568	flow = isl_access_info_compute_flow(ai);3569	space = isl_space_alloc(ctx, 0, 3, 3);3570	mm.must = isl_map_empty(isl_space_copy(space));3571	mm.may = isl_map_empty(space);3572 3573	isl_flow_foreach(flow, collect_must_may, &mm);3574 3575	str = "{ [0,i,0] -> [2,i,0] : 0 <= i <= 10; "3576	      "  [1,i,0] -> [2,5,0] : 0 <= i <= 10 }";3577	assert(map_is_equal(mm.may, str));3578	str = "{ [i,j,k] -> [l,m,n] : 1 = 0 }";3579	assert(map_is_equal(mm.must, str));3580 3581	isl_map_free(mm.must);3582	isl_map_free(mm.may);3583	isl_flow_free(flow);3584 3585 3586	str = "{ [0,i,2] -> [i] : 0 <= i <= 10 }";3587	map = isl_map_read_from_str(ctx, str);3588	ai = isl_access_info_alloc(map, &depth, &common_space, 2);3589 3590	str = "{ [0,i,0] -> [i] : 0 <= i <= 10 }";3591	map = isl_map_read_from_str(ctx, str);3592	ai = isl_access_info_add_source(ai, map, 0, &depth);3593 3594	str = "{ [0,i,1] -> [5] : 0 <= i <= 10 }";3595	map = isl_map_read_from_str(ctx, str);3596	ai = isl_access_info_add_source(ai, map, 0, &depth);3597 3598	flow = isl_access_info_compute_flow(ai);3599	space = isl_space_alloc(ctx, 0, 3, 3);3600	mm.must = isl_map_empty(isl_space_copy(space));3601	mm.may = isl_map_empty(space);3602 3603	isl_flow_foreach(flow, collect_must_may, &mm);3604 3605	str = "{ [0,i,0] -> [0,i,2] : 0 <= i <= 10; "3606	      "  [0,i,1] -> [0,5,2] : 0 <= i <= 5 }";3607	assert(map_is_equal(mm.may, str));3608	str = "{ [i,j,k] -> [l,m,n] : 1 = 0 }";3609	assert(map_is_equal(mm.must, str));3610 3611	isl_map_free(mm.must);3612	isl_map_free(mm.may);3613	isl_flow_free(flow);3614 3615 3616	str = "{ [0,i,1] -> [i] : 0 <= i <= 10 }";3617	map = isl_map_read_from_str(ctx, str);3618	ai = isl_access_info_alloc(map, &depth, &common_space, 2);3619 3620	str = "{ [0,i,0] -> [i] : 0 <= i <= 10 }";3621	map = isl_map_read_from_str(ctx, str);3622	ai = isl_access_info_add_source(ai, map, 0, &depth);3623 3624	str = "{ [0,i,2] -> [5] : 0 <= i <= 10 }";3625	map = isl_map_read_from_str(ctx, str);3626	ai = isl_access_info_add_source(ai, map, 0, &depth);3627 3628	flow = isl_access_info_compute_flow(ai);3629	space = isl_space_alloc(ctx, 0, 3, 3);3630	mm.must = isl_map_empty(isl_space_copy(space));3631	mm.may = isl_map_empty(space);3632 3633	isl_flow_foreach(flow, collect_must_may, &mm);3634 3635	str = "{ [0,i,0] -> [0,i,1] : 0 <= i <= 10; "3636	      "  [0,i,2] -> [0,5,1] : 0 <= i <= 4 }";3637	assert(map_is_equal(mm.may, str));3638	str = "{ [i,j,k] -> [l,m,n] : 1 = 0 }";3639	assert(map_is_equal(mm.must, str));3640 3641	isl_map_free(mm.must);3642	isl_map_free(mm.may);3643	isl_flow_free(flow);3644 3645 3646	depth = 5;3647 3648	str = "{ [1,i,0,0,0] -> [i,j] : 0 <= i <= 10 and 0 <= j <= 10 }";3649	map = isl_map_read_from_str(ctx, str);3650	ai = isl_access_info_alloc(map, &depth, &common_space, 1);3651 3652	str = "{ [0,i,0,j,0] -> [i,j] : 0 <= i <= 10 and 0 <= j <= 10 }";3653	map = isl_map_read_from_str(ctx, str);3654	ai = isl_access_info_add_source(ai, map, 1, &depth);3655 3656	flow = isl_access_info_compute_flow(ai);3657	space = isl_space_alloc(ctx, 0, 5, 5);3658	mm.must = isl_map_empty(isl_space_copy(space));3659	mm.may = isl_map_empty(space);3660 3661	isl_flow_foreach(flow, collect_must_may, &mm);3662 3663	str = "{ [0,i,0,j,0] -> [1,i,0,0,0] : 0 <= i,j <= 10 }";3664	assert(map_is_equal(mm.must, str));3665	str = "{ [0,0,0,0,0] -> [0,0,0,0,0] : 1 = 0 }";3666	assert(map_is_equal(mm.may, str));3667 3668	isl_map_free(mm.must);3669	isl_map_free(mm.may);3670	isl_flow_free(flow);3671 3672	return 0;3673}3674 3675/* Check that the dependence analysis proceeds without errors.3676 * Earlier versions of isl would break down during the analysis3677 * due to the use of the wrong spaces.3678 */3679static int test_flow(isl_ctx *ctx)3680{3681	const char *str;3682	isl_union_map *access, *schedule;3683	isl_union_map *must_dep, *may_dep;3684	int r;3685 3686	str = "{ S0[j] -> i[]; S1[j,i] -> i[]; S2[] -> i[]; S3[] -> i[] }";3687	access = isl_union_map_read_from_str(ctx, str);3688	str = "{ S0[j] -> [0,j,0,0] : 0 <= j < 10; "3689		"S1[j,i] -> [0,j,1,i] : 0 <= j < i < 10; "3690		"S2[] -> [1,0,0,0]; "3691		"S3[] -> [-1,0,0,0] }";3692	schedule = isl_union_map_read_from_str(ctx, str);3693	r = isl_union_map_compute_flow(access, isl_union_map_copy(access),3694					isl_union_map_copy(access), schedule,3695					&must_dep, &may_dep, NULL, NULL);3696	isl_union_map_free(may_dep);3697	isl_union_map_free(must_dep);3698 3699	return r;3700}3701 3702struct {3703	const char *map;3704	int sv;3705} sv_tests[] = {3706	{ "[N] -> { [i] -> [f] : 0 <= i <= N and 0 <= i - 10 f <= 9 }", 1 },3707	{ "[N] -> { [i] -> [f] : 0 <= i <= N and 0 <= i - 10 f <= 10 }", 0 },3708	{ "{ [i] -> [3*floor(i/2) + 5*floor(i/3)] }", 1 },3709	{ "{ S1[i] -> [i] : 0 <= i <= 9; S2[i] -> [i] : 0 <= i <= 9 }", 1 },3710	{ "{ [i] -> S1[i] : 0 <= i <= 9; [i] -> S2[i] : 0 <= i <= 9 }", 0 },3711	{ "{ A[i] -> [i]; B[i] -> [i]; B[i] -> [i + 1] }", 0 },3712	{ "{ A[i] -> [i]; B[i] -> [i] : i < 0; B[i] -> [i + 1] : i > 0 }", 1 },3713	{ "{ A[i] -> [i]; B[i] -> A[i] : i < 0; B[i] -> [i + 1] : i > 0 }", 1 },3714	{ "{ A[i] -> [i]; B[i] -> [j] : i - 1 <= j <= i }", 0 },3715};3716 3717int test_sv(isl_ctx *ctx)3718{3719	isl_union_map *umap;3720	int i;3721	int sv;3722 3723	for (i = 0; i < ARRAY_SIZE(sv_tests); ++i) {3724		umap = isl_union_map_read_from_str(ctx, sv_tests[i].map);3725		sv = isl_union_map_is_single_valued(umap);3726		isl_union_map_free(umap);3727		if (sv < 0)3728			return -1;3729		if (sv_tests[i].sv && !sv)3730			isl_die(ctx, isl_error_internal,3731				"map not detected as single valued", return -1);3732		if (!sv_tests[i].sv && sv)3733			isl_die(ctx, isl_error_internal,3734				"map detected as single valued", return -1);3735	}3736 3737	return 0;3738}3739 3740struct {3741	const char *str;3742	int bijective;3743} bijective_tests[] = {3744	{ "[N,M]->{[i,j] -> [i]}", 0 },3745	{ "[N,M]->{[i,j] -> [i] : j=i}", 1 },3746	{ "[N,M]->{[i,j] -> [i] : j=0}", 1 },3747	{ "[N,M]->{[i,j] -> [i] : j=N}", 1 },3748	{ "[N,M]->{[i,j] -> [j,i]}", 1 },3749	{ "[N,M]->{[i,j] -> [i+j]}", 0 },3750	{ "[N,M]->{[i,j] -> []}", 0 },3751	{ "[N,M]->{[i,j] -> [i,j,N]}", 1 },3752	{ "[N,M]->{[i,j] -> [2i]}", 0 },3753	{ "[N,M]->{[i,j] -> [i,i]}", 0 },3754	{ "[N,M]->{[i,j] -> [2i,i]}", 0 },3755	{ "[N,M]->{[i,j] -> [2i,j]}", 1 },3756	{ "[N,M]->{[i,j] -> [x,y] : 2x=i & y =j}", 1 },3757};3758 3759static int test_bijective(struct isl_ctx *ctx)3760{3761	isl_map *map;3762	int i;3763	int bijective;3764 3765	for (i = 0; i < ARRAY_SIZE(bijective_tests); ++i) {3766		map = isl_map_read_from_str(ctx, bijective_tests[i].str);3767		bijective = isl_map_is_bijective(map);3768		isl_map_free(map);3769		if (bijective < 0)3770			return -1;3771		if (bijective_tests[i].bijective && !bijective)3772			isl_die(ctx, isl_error_internal,3773				"map not detected as bijective", return -1);3774		if (!bijective_tests[i].bijective && bijective)3775			isl_die(ctx, isl_error_internal,3776				"map detected as bijective", return -1);3777	}3778 3779	return 0;3780}3781 3782/* Inputs for isl_pw_qpolynomial_gist tests.3783 * "pwqp" is the input, "set" is the context and "gist" is the expected result.3784 */3785struct {3786	const char *pwqp;3787	const char *set;3788	const char *gist;3789} pwqp_gist_tests[] = {3790	{ "{ [i] -> i }", "{ [k] : exists a : k = 2a }", "{ [i] -> i }" },3791	{ "{ [i] -> i + [ (i + [i/3])/2 ] }", "{ [10] }", "{ [i] -> 16 }" },3792	{ "{ [i] -> ([(i)/2]) }", "{ [k] : exists a : k = 2a+1 }",3793	  "{ [i] -> -1/2 + 1/2 * i }" },3794	{ "{ [i] -> i^2 : i != 0 }", "{ [i] : i != 0 }", "{ [i] -> i^2 }" },3795	{ "{ [i] -> i^2 : i > 0; [i] -> i^2 : i < 0 }", "{ [i] : i != 0 }",3796	  "{ [i] -> i^2 }" },3797};3798 3799/* Perform some basic isl_pw_qpolynomial_gist tests.3800 */3801static isl_stat test_pwqp_gist(isl_ctx *ctx)3802{3803	int i;3804	const char *str;3805	isl_set *set;3806	isl_pw_qpolynomial *pwqp1, *pwqp2;3807	isl_bool equal;3808 3809	for (i = 0; i < ARRAY_SIZE(pwqp_gist_tests); ++i) {3810		str = pwqp_gist_tests[i].pwqp;3811		pwqp1 = isl_pw_qpolynomial_read_from_str(ctx, str);3812		str = pwqp_gist_tests[i].set;3813		set = isl_set_read_from_str(ctx, str);3814		pwqp1 = isl_pw_qpolynomial_gist(pwqp1, set);3815		str = pwqp_gist_tests[i].gist;3816		pwqp2 = isl_pw_qpolynomial_read_from_str(ctx, str);3817		pwqp1 = isl_pw_qpolynomial_sub(pwqp1, pwqp2);3818		equal = isl_pw_qpolynomial_is_zero(pwqp1);3819		isl_pw_qpolynomial_free(pwqp1);3820 3821		if (equal < 0)3822			return isl_stat_error;3823		if (!equal)3824			isl_die(ctx, isl_error_unknown,3825				"unexpected result", return isl_stat_error);3826	}3827 3828	return isl_stat_ok;3829}3830 3831/* Perform a basic isl_pw_qpolynomial_max test.3832 */3833static isl_stat test_pwqp_max(isl_ctx *ctx)3834{3835	const char *str;3836	isl_pw_qpolynomial *pwqp;3837	isl_val *v;3838	int ok;3839 3840	str = "{ [x=2:9, y] -> floor((x + 1)/4)^3 - floor((2x)/3)^2 }";3841	pwqp = isl_pw_qpolynomial_read_from_str(ctx, str);3842	v = isl_pw_qpolynomial_max(pwqp);3843	ok = isl_val_cmp_si(v, -1) == 0;3844	isl_val_free(v);3845 3846	if (!v)3847		return isl_stat_error;3848	if (!ok)3849		isl_die(ctx, isl_error_unknown, "unexpected maximum",3850			return isl_stat_error);3851 3852	return isl_stat_ok;3853}3854 3855static int test_pwqp(struct isl_ctx *ctx)3856{3857	const char *str;3858	isl_set *set;3859	isl_pw_qpolynomial *pwqp1, *pwqp2;3860	int equal;3861 3862	str = "{ [i,j,k] -> 1 + 9 * [i/5] + 7 * [j/11] + 4 * [k/13] }";3863	pwqp1 = isl_pw_qpolynomial_read_from_str(ctx, str);3864 3865	pwqp1 = isl_pw_qpolynomial_move_dims(pwqp1, isl_dim_param, 0,3866						isl_dim_in, 1, 1);3867 3868	str = "[j] -> { [i,k] -> 1 + 9 * [i/5] + 7 * [j/11] + 4 * [k/13] }";3869	pwqp2 = isl_pw_qpolynomial_read_from_str(ctx, str);3870 3871	pwqp1 = isl_pw_qpolynomial_sub(pwqp1, pwqp2);3872 3873	assert(isl_pw_qpolynomial_is_zero(pwqp1));3874 3875	isl_pw_qpolynomial_free(pwqp1);3876 3877	if (test_pwqp_gist(ctx) < 0)3878		return -1;3879 3880	str = "{ [i] -> ([([i/2] + [i/2])/5]) }";3881	pwqp1 = isl_pw_qpolynomial_read_from_str(ctx, str);3882	str = "{ [i] -> ([(2 * [i/2])/5]) }";3883	pwqp2 = isl_pw_qpolynomial_read_from_str(ctx, str);3884 3885	pwqp1 = isl_pw_qpolynomial_sub(pwqp1, pwqp2);3886 3887	assert(isl_pw_qpolynomial_is_zero(pwqp1));3888 3889	isl_pw_qpolynomial_free(pwqp1);3890 3891	str = "{ [x] -> ([x/2] + [(x+1)/2]) }";3892	pwqp1 = isl_pw_qpolynomial_read_from_str(ctx, str);3893	str = "{ [x] -> x }";3894	pwqp2 = isl_pw_qpolynomial_read_from_str(ctx, str);3895 3896	pwqp1 = isl_pw_qpolynomial_sub(pwqp1, pwqp2);3897 3898	assert(isl_pw_qpolynomial_is_zero(pwqp1));3899 3900	isl_pw_qpolynomial_free(pwqp1);3901 3902	str = "{ [i] -> ([i/2]) : i >= 0; [i] -> ([i/3]) : i < 0 }";3903	pwqp1 = isl_pw_qpolynomial_read_from_str(ctx, str);3904	pwqp2 = isl_pw_qpolynomial_read_from_str(ctx, str);3905	pwqp1 = isl_pw_qpolynomial_coalesce(pwqp1);3906	pwqp1 = isl_pw_qpolynomial_sub(pwqp1, pwqp2);3907	assert(isl_pw_qpolynomial_is_zero(pwqp1));3908	isl_pw_qpolynomial_free(pwqp1);3909 3910	str = "{ [a,b,a] -> (([(2*[a/3]+b)/5]) * ([(2*[a/3]+b)/5])) }";3911	pwqp2 = isl_pw_qpolynomial_read_from_str(ctx, str);3912	str = "{ [a,b,c] -> (([(2*[a/3]+b)/5]) * ([(2*[c/3]+b)/5])) }";3913	pwqp1 = isl_pw_qpolynomial_read_from_str(ctx, str);3914	set = isl_set_read_from_str(ctx, "{ [a,b,a] }");3915	pwqp1 = isl_pw_qpolynomial_intersect_domain(pwqp1, set);3916	equal = isl_pw_qpolynomial_plain_is_equal(pwqp1, pwqp2);3917	isl_pw_qpolynomial_free(pwqp1);3918	isl_pw_qpolynomial_free(pwqp2);3919	if (equal < 0)3920		return -1;3921	if (!equal)3922		isl_die(ctx, isl_error_unknown, "unexpected result", return -1);3923 3924	str = "{ [a,b,c] -> (([(2*[a/3]+1)/5]) * ([(2*[c/3]+1)/5])) : b = 1 }";3925	pwqp2 = isl_pw_qpolynomial_read_from_str(ctx, str);3926	str = "{ [a,b,c] -> (([(2*[a/3]+b)/5]) * ([(2*[c/3]+b)/5])) }";3927	pwqp1 = isl_pw_qpolynomial_read_from_str(ctx, str);3928	pwqp1 = isl_pw_qpolynomial_fix_val(pwqp1, isl_dim_set, 1,3929						isl_val_one(ctx));3930	equal = isl_pw_qpolynomial_plain_is_equal(pwqp1, pwqp2);3931	isl_pw_qpolynomial_free(pwqp1);3932	isl_pw_qpolynomial_free(pwqp2);3933	if (equal < 0)3934		return -1;3935	if (!equal)3936		isl_die(ctx, isl_error_unknown, "unexpected result", return -1);3937 3938	if (test_pwqp_max(ctx) < 0)3939		return -1;3940 3941	return 0;3942}3943 3944static int test_split_periods(isl_ctx *ctx)3945{3946	const char *str;3947	isl_pw_qpolynomial *pwqp;3948 3949	str = "{ [U,V] -> 1/3 * U + 2/3 * V - [(U + 2V)/3] + [U/2] : "3950		"U + 2V + 3 >= 0 and - U -2V  >= 0 and - U + 10 >= 0 and "3951		"U  >= 0; [U,V] -> U^2 : U >= 100 }";3952	pwqp = isl_pw_qpolynomial_read_from_str(ctx, str);3953 3954	pwqp = isl_pw_qpolynomial_split_periods(pwqp, 2);3955 3956	isl_pw_qpolynomial_free(pwqp);3957 3958	if (!pwqp)3959		return -1;3960 3961	return 0;3962}3963 3964static int test_union(isl_ctx *ctx)3965{3966	const char *str;3967	isl_union_set *uset1, *uset2;3968	isl_union_map *umap1, *umap2;3969	int equal;3970 3971	str = "{ [i] : 0 <= i <= 1 }";3972	uset1 = isl_union_set_read_from_str(ctx, str);3973	str = "{ [1] -> [0] }";3974	umap1 = isl_union_map_read_from_str(ctx, str);3975 3976	umap2 = isl_union_set_lex_gt_union_set(isl_union_set_copy(uset1), uset1);3977	equal = isl_union_map_is_equal(umap1, umap2);3978 3979	isl_union_map_free(umap1);3980	isl_union_map_free(umap2);3981 3982	if (equal < 0)3983		return -1;3984	if (!equal)3985		isl_die(ctx, isl_error_unknown, "union maps not equal",3986			return -1);3987 3988	str = "{ A[i] -> B[i]; B[i] -> C[i]; A[0] -> C[1] }";3989	umap1 = isl_union_map_read_from_str(ctx, str);3990	str = "{ A[i]; B[i] }";3991	uset1 = isl_union_set_read_from_str(ctx, str);3992 3993	uset2 = isl_union_map_domain(umap1);3994 3995	equal = isl_union_set_is_equal(uset1, uset2);3996 3997	isl_union_set_free(uset1);3998	isl_union_set_free(uset2);3999 4000	if (equal < 0)4001		return -1;4002	if (!equal)4003		isl_die(ctx, isl_error_unknown, "union sets not equal",4004			return -1);4005 4006	return 0;4007}4008 4009/* Inputs for basic isl_pw_qpolynomial_bound tests.4010 * "type" is the type of bound that should be computed.4011 * "poly" is a string representation of the input.4012 * "bound" is a string representation of the expected result.4013 * "tight" is set if the result is expected to be tight.4014 */4015static struct {4016	int tight;4017	enum isl_fold type;4018	const char *poly;4019	const char *bound;4020} bound_tests[] = {4021	/* Check that computing a bound of a non-zero polynomial4022	 * over an unbounded domain does not produce a rational value.4023	 * In particular, check that the upper bound is infinity.4024	 */4025	{ 0, isl_fold_max, "{ [m, n] -> -m * n }", "{ max(infty) }" },4026	{ 1, isl_fold_max, "{ [[a, b, c, d] -> [e]] -> 0 }",4027	  "{ [a, b, c, d] -> max(0) }" },4028	{ 1, isl_fold_max, "{ [[x] -> [x]] -> 1 : exists a : x = 2 a }",4029	  "{ [x] -> max(1) : x mod 2 = 0 }" },4030	{ 1, isl_fold_min, "{ [x=5:10] -> (x + 2)^2 }", "{ min(49) }" },4031	{ 1, isl_fold_max, "{ [0:10] -> 1 }", "{ max(1) }" },4032	{ 1, isl_fold_max, "{ [[m] -> [0:m]] -> m^2 }",4033	  "{ [m] -> max(m^2) : m >= 0 }" },4034};4035 4036/* Check that the bound computation can handle differences4037 * in domain dimension names of the input polynomial and its domain.4038 */4039static isl_stat test_bound_space(isl_ctx *ctx)4040{4041	const char *str;4042	isl_set *set;4043	isl_pw_qpolynomial *pwqp;4044	isl_pw_qpolynomial_fold *pwf;4045 4046	str = "{ [[c] -> [c]] }";4047	set = isl_set_read_from_str(ctx, str);4048	str = "{ [[a] -> [b]] -> 1 }";4049	pwqp = isl_pw_qpolynomial_read_from_str(ctx, str);4050	pwqp = isl_pw_qpolynomial_intersect_domain(pwqp, set);4051	pwf = isl_pw_qpolynomial_bound(pwqp, isl_fold_max, NULL);4052	isl_pw_qpolynomial_fold_free(pwf);4053 4054	return isl_stat_non_null(pwf);4055}4056 4057/* Perform basic isl_pw_qpolynomial_bound tests.4058 */4059static int test_bound(isl_ctx *ctx)4060{4061	int i;4062 4063	if (test_bound_space(ctx) < 0)4064		return -1;4065 4066	for (i = 0; i < ARRAY_SIZE(bound_tests); ++i) {4067		const char *str;4068		enum isl_fold type;4069		isl_bool equal, tight;4070		isl_pw_qpolynomial *pwqp;4071		isl_pw_qpolynomial_fold *pwf1, *pwf2;4072 4073		str = bound_tests[i].poly;4074		pwqp = isl_pw_qpolynomial_read_from_str(ctx, str);4075		type = bound_tests[i].type;4076		pwf1 = isl_pw_qpolynomial_bound(pwqp, type, &tight);4077		str = bound_tests[i].bound;4078		pwf2 = isl_pw_qpolynomial_fold_read_from_str(ctx, str);4079		equal = isl_pw_qpolynomial_fold_plain_is_equal(pwf1, pwf2);4080		isl_pw_qpolynomial_fold_free(pwf2);4081		isl_pw_qpolynomial_fold_free(pwf1);4082		if (equal < 0)4083			return -1;4084		if (!equal)4085			isl_die(ctx, isl_error_unknown,4086				"incorrect bound result", return -1);4087		if (bound_tests[i].tight && !tight)4088			isl_die(ctx, isl_error_unknown,4089				"bound unexpectedly not tight", return -1);4090	}4091 4092	return 0;4093}4094 4095/* isl_set is defined to isl_map internally, so the corresponding elements4096 * are isl_basic_map objects.4097 */4098#undef EL_BASE4099#undef SET_BASE4100#define EL_BASE		basic_map4101#define SET_BASE	set4102#include "isl_test_list_templ.c"4103 4104#undef EL_BASE4105#undef SET_BASE4106#define EL_BASE		basic_set4107#define SET_BASE	union_set4108#include "isl_test_list_templ.c"4109 4110#undef EL_BASE4111#undef SET_BASE4112#define EL_BASE		set4113#define SET_BASE	union_set4114#include "isl_test_list_templ.c"4115 4116#undef EL_BASE4117#undef SET_BASE4118#define EL_BASE		basic_map4119#define SET_BASE	map4120#include "isl_test_list_templ.c"4121 4122#undef EL_BASE4123#undef SET_BASE4124#define EL_BASE		map4125#define SET_BASE	union_map4126#include "isl_test_list_templ.c"4127 4128/* Check that the conversion from isl objects to lists works as expected.4129 */4130static int test_get_list(isl_ctx *ctx)4131{4132	if (test_get_list_basic_map_from_set(ctx, "{ [0]; [2]; [3] }"))4133		return -1;4134	if (test_get_list_basic_set_from_union_set(ctx, "{ A[0]; B[2]; B[3] }"))4135		return -1;4136	if (test_get_list_set_from_union_set(ctx, "{ A[0]; A[2]; B[3] }"))4137		return -1;4138	if (test_get_list_basic_map_from_map(ctx,4139				"{ [0] -> [0]; [2] -> [0]; [3] -> [0] }"))4140		return -1;4141	if (test_get_list_map_from_union_map(ctx,4142				"{ A[0] -> [0]; A[2] -> [0]; B[3] -> [0] }"))4143		return -1;4144 4145	return 0;4146}4147 4148static int test_lift(isl_ctx *ctx)4149{4150	const char *str;4151	isl_basic_map *bmap;4152	isl_basic_set *bset;4153 4154	str = "{ [i0] : exists e0 : i0 = 4e0 }";4155	bset = isl_basic_set_read_from_str(ctx, str);4156	bset = isl_basic_set_lift(bset);4157	bmap = isl_basic_map_from_range(bset);4158	bset = isl_basic_map_domain(bmap);4159	isl_basic_set_free(bset);4160 4161	return 0;4162}4163 4164/* Check that isl_set_is_subset is not confused by identical4165 * integer divisions.4166 * The call to isl_set_normalize ensures that the equality constraints4167 * a = b = 0 are discovered, turning e0 and e1 into identical4168 * integer divisions.  Any further simplification would remove4169 * the duplicate integer divisions.4170 */4171static isl_stat test_subset_duplicate_integer_divisions(isl_ctx *ctx)4172{4173	const char *str;4174	isl_bool is_subset;4175	isl_set *set1, *set2;4176 4177	str = "{ [a, b, c, d] : "4178	    "exists (e0 = floor((a + d)/4), e1 = floor((d)/4), "4179		    "e2 = floor((-a - d + 4 *floor((a + d)/4))/10), "4180		    "e3 = floor((-d + 4*floor((d)/4))/10): "4181		"10e2 = -a - 2c - d + 4e0 and 10e3 = -2c - d + 4e1 and "4182		"b >= 0 and a <= 0 and b <= a) }";4183	set1 = isl_set_read_from_str(ctx, str);4184	set2 = isl_set_read_from_str(ctx, str);4185	set2 = isl_set_normalize(set2);4186 4187	is_subset = isl_set_is_subset(set1, set2);4188 4189	isl_set_free(set1);4190	isl_set_free(set2);4191 4192	if (is_subset < 0)4193		return isl_stat_error;4194	if (!is_subset)4195		isl_die(ctx, isl_error_unknown,4196			"set is not considered to be a subset of itself",4197			return isl_stat_error);4198 4199	return isl_stat_ok;4200}4201 4202struct {4203	const char *set1;4204	const char *set2;4205	int subset;4206} subset_tests[] = {4207	{ "{ [112, 0] }",4208	  "{ [i0, i1] : exists (e0 = [(i0 - i1)/16], e1: "4209		"16e0 <= i0 - i1 and 16e0 >= -15 + i0 - i1 and "4210		"16e1 <= i1 and 16e0 >= -i1 and 16e1 >= -i0 + i1) }", 1 },4211	{ "{ [65] }",4212	  "{ [i] : exists (e0 = [(255i)/256], e1 = [(127i + 65e0)/191], "4213		"e2 = [(3i + 61e1)/65], e3 = [(52i + 12e2)/61], "4214		"e4 = [(2i + e3)/3], e5 = [(4i + e3)/4], e6 = [(8i + e3)/12]: "4215		    "3e4 = 2i + e3 and 4e5 = 4i + e3 and 12e6 = 8i + e3 and "4216		    "i <= 255 and 64e3 >= -45 + 67i and i >= 0 and "4217		    "256e0 <= 255i and 256e0 >= -255 + 255i and "4218		    "191e1 <= 127i + 65e0 and 191e1 >= -190 + 127i + 65e0 and "4219		    "65e2 <= 3i + 61e1 and 65e2 >= -64 + 3i + 61e1 and "4220		    "61e3 <= 52i + 12e2 and 61e3 >= -60 + 52i + 12e2) }", 1 },4221	{ "{ [i] : 0 <= i <= 10 }", "{ rat: [i] : 0 <= i <= 10 }", 1 },4222	{ "{ rat: [i] : 0 <= i <= 10 }", "{ [i] : 0 <= i <= 10 }", 0 },4223	{ "{ rat: [0] }", "{ [i] : 0 <= i <= 10 }", 1 },4224	{ "{ rat: [(1)/2] }", "{ [i] : 0 <= i <= 10 }", 0 },4225	{ "{ [t, i] : (exists (e0 = [(2 + t)/4]: 4e0 <= 2 + t and "4226			"4e0 >= -1 + t and i >= 57 and i <= 62 and "4227			"4e0 <= 62 + t - i and 4e0 >= -61 + t + i and "4228			"t >= 0 and t <= 511 and 4e0 <= -57 + t + i and "4229			"4e0 >= 58 + t - i and i >= 58 + t and i >= 62 - t)) }",4230	  "{ [i0, i1] : (exists (e0 = [(4 + i0)/4]: 4e0 <= 62 + i0 - i1 and "4231			"4e0 >= 1 + i0 and i0 >= 0 and i0 <= 511 and "4232			"4e0 <= -57 + i0 + i1)) or "4233		"(exists (e0 = [(2 + i0)/4]: 4e0 <= i0 and "4234			"4e0 >= 58 + i0 - i1 and i0 >= 2 and i0 <= 511 and "4235			"4e0 >= -61 + i0 + i1)) or "4236		"(i1 <= 66 - i0 and i0 >= 2 and i1 >= 59 + i0) }", 1 },4237	{ "[a, b] -> { : a = 0 and b = -1 }", "[b, a] -> { : b >= -10 }", 1 },4238};4239 4240static int test_subset(isl_ctx *ctx)4241{4242	int i;4243	isl_set *set1, *set2;4244	int subset;4245 4246	if (test_subset_duplicate_integer_divisions(ctx) < 0)4247		return -1;4248 4249	for (i = 0; i < ARRAY_SIZE(subset_tests); ++i) {4250		set1 = isl_set_read_from_str(ctx, subset_tests[i].set1);4251		set2 = isl_set_read_from_str(ctx, subset_tests[i].set2);4252		subset = isl_set_is_subset(set1, set2);4253		isl_set_free(set1);4254		isl_set_free(set2);4255		if (subset < 0)4256			return -1;4257		if (subset != subset_tests[i].subset)4258			isl_die(ctx, isl_error_unknown,4259				"incorrect subset result", return -1);4260	}4261 4262	return 0;4263}4264 4265/* Perform a set subtraction with a set that has a non-obviously empty disjunct.4266 * Older versions of isl would fail on such cases.4267 */4268static isl_stat test_subtract_empty(isl_ctx *ctx)4269{4270	const char *str;4271	isl_set *s1, *s2;4272 4273	s1 = isl_set_read_from_str(ctx, "{ [0] }");4274	str = "{ [a] : (exists (e0, e1, e2: 1056e1 <= 32 + a - 33e0 and "4275			"1089e1 >= a - 33e0 and 1089e1 <= 1 + a - 33e0 and "4276			"33e2 >= -a + 33e0 + 1056e1 and "4277			"33e2 < -2a + 66e0 + 2112e1)) or a = 0 }";4278	s2 = isl_set_read_from_str(ctx, str);4279	s1 = isl_set_subtract(s1, s2);4280	isl_set_free(s1);4281 4282	return isl_stat_non_null(s1);4283}4284 4285struct {4286	const char *minuend;4287	const char *subtrahend;4288	const char *difference;4289} subtract_domain_tests[] = {4290	{ "{ A[i] -> B[i] }", "{ A[i] }", "{ }" },4291	{ "{ A[i] -> B[i] }", "{ B[i] }", "{ A[i] -> B[i] }" },4292	{ "{ A[i] -> B[i] }", "{ A[i] : i > 0 }", "{ A[i] -> B[i] : i <= 0 }" },4293};4294 4295static int test_subtract(isl_ctx *ctx)4296{4297	int i;4298	isl_union_map *umap1, *umap2;4299	isl_union_pw_multi_aff *upma1, *upma2;4300	isl_union_set *uset;4301	int equal;4302 4303	if (test_subtract_empty(ctx) < 0)4304		return -1;4305 4306	for (i = 0; i < ARRAY_SIZE(subtract_domain_tests); ++i) {4307		umap1 = isl_union_map_read_from_str(ctx,4308				subtract_domain_tests[i].minuend);4309		uset = isl_union_set_read_from_str(ctx,4310				subtract_domain_tests[i].subtrahend);4311		umap2 = isl_union_map_read_from_str(ctx,4312				subtract_domain_tests[i].difference);4313		umap1 = isl_union_map_subtract_domain(umap1, uset);4314		equal = isl_union_map_is_equal(umap1, umap2);4315		isl_union_map_free(umap1);4316		isl_union_map_free(umap2);4317		if (equal < 0)4318			return -1;4319		if (!equal)4320			isl_die(ctx, isl_error_unknown,4321				"incorrect subtract domain result", return -1);4322	}4323 4324	for (i = 0; i < ARRAY_SIZE(subtract_domain_tests); ++i) {4325		upma1 = isl_union_pw_multi_aff_read_from_str(ctx,4326				subtract_domain_tests[i].minuend);4327		uset = isl_union_set_read_from_str(ctx,4328				subtract_domain_tests[i].subtrahend);4329		upma2 = isl_union_pw_multi_aff_read_from_str(ctx,4330				subtract_domain_tests[i].difference);4331		upma1 = isl_union_pw_multi_aff_subtract_domain(upma1, uset);4332		equal = isl_union_pw_multi_aff_plain_is_equal(upma1, upma2);4333		isl_union_pw_multi_aff_free(upma1);4334		isl_union_pw_multi_aff_free(upma2);4335		if (equal < 0)4336			return -1;4337		if (!equal)4338			isl_die(ctx, isl_error_unknown,4339				"incorrect subtract domain result", return -1);4340	}4341 4342	return 0;4343}4344 4345/* Check that intersecting the empty basic set with another basic set4346 * does not increase the number of constraints.  In particular,4347 * the empty basic set should maintain its canonical representation.4348 */4349static int test_intersect_1(isl_ctx *ctx)4350{4351	isl_size n1, n2;4352	isl_basic_set *bset1, *bset2;4353 4354	bset1 = isl_basic_set_read_from_str(ctx, "{ [a,b,c] : 1 = 0 }");4355	bset2 = isl_basic_set_read_from_str(ctx, "{ [1,2,3] }");4356	n1 = isl_basic_set_n_constraint(bset1);4357	bset1 = isl_basic_set_intersect(bset1, bset2);4358	n2 = isl_basic_set_n_constraint(bset1);4359	isl_basic_set_free(bset1);4360	if (n1 < 0 || n2 < 0)4361		return -1;4362	if (n1 != n2)4363		isl_die(ctx, isl_error_unknown,4364			"number of constraints of empty set changed",4365			return -1);4366 4367	return 0;4368}4369 4370/* Check that intersecting a set with itself does not cause4371 * an explosion in the number of disjuncts.4372 */4373static isl_stat test_intersect_2(isl_ctx *ctx)4374{4375	int i;4376	isl_set *set;4377 4378	set = isl_set_read_from_str(ctx, "{ [x,y] : x >= 0 or y >= 0 }");4379	for (i = 0; i < 100; ++i)4380		set = isl_set_intersect(set, isl_set_copy(set));4381	isl_set_free(set);4382	if (!set)4383		return isl_stat_error;4384	return isl_stat_ok;4385}4386 4387/* Perform some intersection tests.4388 */4389static int test_intersect(isl_ctx *ctx)4390{4391	if (test_intersect_1(ctx) < 0)4392		return -1;4393	if (test_intersect_2(ctx) < 0)4394		return -1;4395 4396	return 0;4397}4398 4399int test_factorize(isl_ctx *ctx)4400{4401	const char *str;4402	isl_basic_set *bset;4403	isl_factorizer *f;4404 4405	str = "{ [i0, i1, i2, i3, i4, i5, i6, i7] : 3i5 <= 2 - 2i0 and "4406	    "i0 >= -2 and i6 >= 1 + i3 and i7 >= 0 and 3i5 >= -2i0 and "4407	    "2i4 <= i2 and i6 >= 1 + 2i0 + 3i1 and i4 <= -1 and "4408	    "i6 >= 1 + 2i0 + 3i5 and i6 <= 2 + 2i0 + 3i5 and "4409	    "3i5 <= 2 - 2i0 - i2 + 3i4 and i6 <= 2 + 2i0 + 3i1 and "4410	    "i0 <= -1 and i7 <= i2 + i3 - 3i4 - i6 and "4411	    "3i5 >= -2i0 - i2 + 3i4 }";4412	bset = isl_basic_set_read_from_str(ctx, str);4413	f = isl_basic_set_factorizer(bset);4414	isl_basic_set_free(bset);4415	isl_factorizer_free(f);4416	if (!f)4417		isl_die(ctx, isl_error_unknown,4418			"failed to construct factorizer", return -1);4419 4420	str = "{ [i0, i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11, i12] : "4421	    "i12 <= 2 + i0 - i11 and 2i8 >= -i4 and i11 >= i1 and "4422	    "3i5 <= -i2 and 2i11 >= -i4 - 2i7 and i11 <= 3 + i0 + 3i9 and "4423	    "i11 <= -i4 - 2i7 and i12 >= -i10 and i2 >= -2 and "4424	    "i11 >= i1 + 3i10 and i11 >= 1 + i0 + 3i9 and "4425	    "i11 <= 1 - i4 - 2i8 and 6i6 <= 6 - i2 and 3i6 >= 1 - i2 and "4426	    "i11 <= 2 + i1 and i12 <= i4 + i11 and i12 >= i0 - i11 and "4427	    "3i5 >= -2 - i2 and i12 >= -1 + i4 + i11 and 3i3 <= 3 - i2 and "4428	    "9i6 <= 11 - i2 + 6i5 and 3i3 >= 1 - i2 and "4429	    "9i6 <= 5 - i2 + 6i3 and i12 <= -1 and i2 <= 0 }";4430	bset = isl_basic_set_read_from_str(ctx, str);4431	f = isl_basic_set_factorizer(bset);4432	isl_basic_set_free(bset);4433	isl_factorizer_free(f);4434	if (!f)4435		isl_die(ctx, isl_error_unknown,4436			"failed to construct factorizer", return -1);4437 4438	return 0;4439}4440 4441static isl_stat check_injective(__isl_take isl_map *map, void *user)4442{4443	int *injective = user;4444 4445	*injective = isl_map_is_injective(map);4446	isl_map_free(map);4447 4448	if (*injective < 0 || !*injective)4449		return isl_stat_error;4450 4451	return isl_stat_ok;4452}4453 4454int test_one_schedule(isl_ctx *ctx, const char *d, const char *w,4455	const char *r, const char *s, int tilable, int parallel)4456{4457	int i;4458	isl_union_set *D;4459	isl_union_map *W, *R, *S;4460	isl_union_map *empty;4461	isl_union_map *dep_raw, *dep_war, *dep_waw, *dep;4462	isl_union_map *validity, *proximity, *coincidence;4463	isl_union_map *schedule;4464	isl_union_map *test;4465	isl_union_set *delta;4466	isl_union_set *domain;4467	isl_set *delta_set;4468	isl_set *slice;4469	isl_set *origin;4470	isl_schedule_constraints *sc;4471	isl_schedule *sched;4472	int is_nonneg, is_parallel, is_tilable, is_injection, is_complete;4473	isl_size n;4474 4475	D = isl_union_set_read_from_str(ctx, d);4476	W = isl_union_map_read_from_str(ctx, w);4477	R = isl_union_map_read_from_str(ctx, r);4478	S = isl_union_map_read_from_str(ctx, s);4479 4480	W = isl_union_map_intersect_domain(W, isl_union_set_copy(D));4481	R = isl_union_map_intersect_domain(R, isl_union_set_copy(D));4482 4483	empty = isl_union_map_empty(isl_union_map_get_space(S));4484        isl_union_map_compute_flow(isl_union_map_copy(R),4485				   isl_union_map_copy(W), empty,4486				   isl_union_map_copy(S),4487				   &dep_raw, NULL, NULL, NULL);4488        isl_union_map_compute_flow(isl_union_map_copy(W),4489				   isl_union_map_copy(W),4490				   isl_union_map_copy(R),4491				   isl_union_map_copy(S),4492				   &dep_waw, &dep_war, NULL, NULL);4493 4494	dep = isl_union_map_union(dep_waw, dep_war);4495	dep = isl_union_map_union(dep, dep_raw);4496	validity = isl_union_map_copy(dep);4497	coincidence = isl_union_map_copy(dep);4498	proximity = isl_union_map_copy(dep);4499 4500	sc = isl_schedule_constraints_on_domain(isl_union_set_copy(D));4501	sc = isl_schedule_constraints_set_validity(sc, validity);4502	sc = isl_schedule_constraints_set_coincidence(sc, coincidence);4503	sc = isl_schedule_constraints_set_proximity(sc, proximity);4504	sched = isl_schedule_constraints_compute_schedule(sc);4505	schedule = isl_schedule_get_map(sched);4506	isl_schedule_free(sched);4507	isl_union_map_free(W);4508	isl_union_map_free(R);4509	isl_union_map_free(S);4510 4511	is_injection = 1;4512	isl_union_map_foreach_map(schedule, &check_injective, &is_injection);4513 4514	domain = isl_union_map_domain(isl_union_map_copy(schedule));4515	is_complete = isl_union_set_is_subset(D, domain);4516	isl_union_set_free(D);4517	isl_union_set_free(domain);4518 4519	test = isl_union_map_reverse(isl_union_map_copy(schedule));4520	test = isl_union_map_apply_range(test, dep);4521	test = isl_union_map_apply_range(test, schedule);4522 4523	delta = isl_union_map_deltas(test);4524	n = isl_union_set_n_set(delta);4525	if (n < 0) {4526		isl_union_set_free(delta);4527		return -1;4528	}4529	if (n == 0) {4530		is_tilable = 1;4531		is_parallel = 1;4532		is_nonneg = 1;4533		isl_union_set_free(delta);4534	} else {4535		isl_size dim;4536 4537		delta_set = isl_set_from_union_set(delta);4538 4539		slice = isl_set_universe(isl_set_get_space(delta_set));4540		for (i = 0; i < tilable; ++i)4541			slice = isl_set_lower_bound_si(slice, isl_dim_set, i, 0);4542		is_tilable = isl_set_is_subset(delta_set, slice);4543		isl_set_free(slice);4544 4545		slice = isl_set_universe(isl_set_get_space(delta_set));4546		for (i = 0; i < parallel; ++i)4547			slice = isl_set_fix_si(slice, isl_dim_set, i, 0);4548		is_parallel = isl_set_is_subset(delta_set, slice);4549		isl_set_free(slice);4550 4551		origin = isl_set_universe(isl_set_get_space(delta_set));4552		dim = isl_set_dim(origin, isl_dim_set);4553		if (dim < 0)4554			origin = isl_set_free(origin);4555		for (i = 0; i < dim; ++i)4556			origin = isl_set_fix_si(origin, isl_dim_set, i, 0);4557 4558		delta_set = isl_set_union(delta_set, isl_set_copy(origin));4559		delta_set = isl_set_lexmin(delta_set);4560 4561		is_nonneg = isl_set_is_equal(delta_set, origin);4562 4563		isl_set_free(origin);4564		isl_set_free(delta_set);4565	}4566 4567	if (is_nonneg < 0 || is_parallel < 0 || is_tilable < 0 ||4568	    is_injection < 0 || is_complete < 0)4569		return -1;4570	if (!is_complete)4571		isl_die(ctx, isl_error_unknown,4572			"generated schedule incomplete", return -1);4573	if (!is_injection)4574		isl_die(ctx, isl_error_unknown,4575			"generated schedule not injective on each statement",4576			return -1);4577	if (!is_nonneg)4578		isl_die(ctx, isl_error_unknown,4579			"negative dependences in generated schedule",4580			return -1);4581	if (!is_tilable)4582		isl_die(ctx, isl_error_unknown,4583			"generated schedule not as tilable as expected",4584			return -1);4585	if (!is_parallel)4586		isl_die(ctx, isl_error_unknown,4587			"generated schedule not as parallel as expected",4588			return -1);4589 4590	return 0;4591}4592 4593/* Compute a schedule for the given instance set, validity constraints,4594 * proximity constraints and context and return a corresponding union map4595 * representation.4596 */4597static __isl_give isl_union_map *compute_schedule_with_context(isl_ctx *ctx,4598	const char *domain, const char *validity, const char *proximity,4599	const char *context)4600{4601	isl_set *con;4602	isl_union_set *dom;4603	isl_union_map *dep;4604	isl_union_map *prox;4605	isl_schedule_constraints *sc;4606	isl_schedule *schedule;4607	isl_union_map *sched;4608 4609	con = isl_set_read_from_str(ctx, context);4610	dom = isl_union_set_read_from_str(ctx, domain);4611	dep = isl_union_map_read_from_str(ctx, validity);4612	prox = isl_union_map_read_from_str(ctx, proximity);4613	sc = isl_schedule_constraints_on_domain(dom);4614	sc = isl_schedule_constraints_set_context(sc, con);4615	sc = isl_schedule_constraints_set_validity(sc, dep);4616	sc = isl_schedule_constraints_set_proximity(sc, prox);4617	schedule = isl_schedule_constraints_compute_schedule(sc);4618	sched = isl_schedule_get_map(schedule);4619	isl_schedule_free(schedule);4620 4621	return sched;4622}4623 4624/* Compute a schedule for the given instance set, validity constraints and4625 * proximity constraints and return a corresponding union map representation.4626 */4627static __isl_give isl_union_map *compute_schedule(isl_ctx *ctx,4628	const char *domain, const char *validity, const char *proximity)4629{4630	return compute_schedule_with_context(ctx, domain, validity, proximity,4631						"{ : }");4632}4633 4634/* Check that a schedule can be constructed on the given domain4635 * with the given validity and proximity constraints.4636 */4637static int test_has_schedule(isl_ctx *ctx, const char *domain,4638	const char *validity, const char *proximity)4639{4640	isl_union_map *sched;4641 4642	sched = compute_schedule(ctx, domain, validity, proximity);4643	if (!sched)4644		return -1;4645 4646	isl_union_map_free(sched);4647	return 0;4648}4649 4650int test_special_schedule(isl_ctx *ctx, const char *domain,4651	const char *validity, const char *proximity, const char *expected_sched)4652{4653	isl_union_map *sched1, *sched2;4654	int equal;4655 4656	sched1 = compute_schedule(ctx, domain, validity, proximity);4657	sched2 = isl_union_map_read_from_str(ctx, expected_sched);4658 4659	equal = isl_union_map_is_equal(sched1, sched2);4660	isl_union_map_free(sched1);4661	isl_union_map_free(sched2);4662 4663	if (equal < 0)4664		return -1;4665	if (!equal)4666		isl_die(ctx, isl_error_unknown, "unexpected schedule",4667			return -1);4668 4669	return 0;4670}4671 4672/* Check that the schedule map is properly padded, i.e., that the range4673 * lives in a single space.4674 */4675static int test_padded_schedule(isl_ctx *ctx)4676{4677	const char *str;4678	isl_union_set *D;4679	isl_union_map *validity, *proximity;4680	isl_schedule_constraints *sc;4681	isl_schedule *sched;4682	isl_union_map *umap;4683	isl_union_set *range;4684	isl_set *set;4685 4686	str = "[N] -> { S0[i] : 0 <= i <= N; S1[i, j] : 0 <= i, j <= N }";4687	D = isl_union_set_read_from_str(ctx, str);4688	validity = isl_union_map_empty(isl_union_set_get_space(D));4689	proximity = isl_union_map_copy(validity);4690	sc = isl_schedule_constraints_on_domain(D);4691	sc = isl_schedule_constraints_set_validity(sc, validity);4692	sc = isl_schedule_constraints_set_proximity(sc, proximity);4693	sched = isl_schedule_constraints_compute_schedule(sc);4694	umap = isl_schedule_get_map(sched);4695	isl_schedule_free(sched);4696	range = isl_union_map_range(umap);4697	set = isl_set_from_union_set(range);4698	isl_set_free(set);4699 4700	if (!set)4701		return -1;4702 4703	return 0;4704}4705 4706/* Check that conditional validity constraints are also taken into4707 * account across bands.4708 * In particular, try to make sure that live ranges D[1,0]->C[2,1] and4709 * D[2,0]->C[3,0] are not local in the outer band of the generated schedule4710 * and then check that the adjacent order constraint C[2,1]->D[2,0]4711 * is enforced by the rest of the schedule.4712 */4713static int test_special_conditional_schedule_constraints(isl_ctx *ctx)4714{4715	const char *str;4716	isl_union_set *domain;4717	isl_union_map *validity, *proximity, *condition;4718	isl_union_map *sink, *source, *dep;4719	isl_schedule_constraints *sc;4720	isl_schedule *schedule;4721	isl_union_access_info *access;4722	isl_union_flow *flow;4723	int empty;4724 4725	str = "[n] -> { C[k, i] : k <= -1 + n and i >= 0 and i <= -1 + k; "4726	    "A[k] : k >= 1 and k <= -1 + n; "4727	    "B[k, i] : k <= -1 + n and i >= 0 and i <= -1 + k; "4728	    "D[k, i] : k <= -1 + n and i >= 0 and i <= -1 + k }";4729	domain = isl_union_set_read_from_str(ctx, str);4730	sc = isl_schedule_constraints_on_domain(domain);4731	str = "[n] -> { D[k, i] -> C[1 + k, k - i] : "4732		"k <= -2 + n and i >= 1 and i <= -1 + k; "4733		"D[k, i] -> C[1 + k, i] : "4734		"k <= -2 + n and i >= 1 and i <= -1 + k; "4735		"D[k, 0] -> C[1 + k, k] : k >= 1 and k <= -2 + n; "4736		"D[k, 0] -> C[1 + k, 0] : k >= 1 and k <= -2 + n }";4737	validity = isl_union_map_read_from_str(ctx, str);4738	sc = isl_schedule_constraints_set_validity(sc, validity);4739	str = "[n] -> { C[k, i] -> D[k, i] : "4740		"0 <= i <= -1 + k and k <= -1 + n }";4741	proximity = isl_union_map_read_from_str(ctx, str);4742	sc = isl_schedule_constraints_set_proximity(sc, proximity);4743	str = "[n] -> { [D[k, i] -> a[]] -> [C[1 + k, k - i] -> b[]] : "4744		"i <= -1 + k and i >= 1 and k <= -2 + n; "4745		"[B[k, i] -> c[]] -> [B[k, 1 + i] -> c[]] : "4746		"k <= -1 + n and i >= 0 and i <= -2 + k }";4747	condition = isl_union_map_read_from_str(ctx, str);4748	str = "[n] -> { [B[k, i] -> e[]] -> [D[k, i] -> a[]] : "4749		"i >= 0 and i <= -1 + k and k <= -1 + n; "4750		"[C[k, i] -> b[]] -> [D[k', -1 + k - i] -> a[]] : "4751		"i >= 0 and i <= -1 + k and k <= -1 + n and "4752		"k' <= -1 + n and k' >= k - i and k' >= 1 + k; "4753		"[C[k, i] -> b[]] -> [D[k, -1 + k - i] -> a[]] : "4754		"i >= 0 and i <= -1 + k and k <= -1 + n; "4755		"[B[k, i] -> c[]] -> [A[k'] -> d[]] : "4756		"k <= -1 + n and i >= 0 and i <= -1 + k and "4757		"k' >= 1 and k' <= -1 + n and k' >= 1 + k }";4758	validity = isl_union_map_read_from_str(ctx, str);4759	sc = isl_schedule_constraints_set_conditional_validity(sc, condition,4760								validity);4761	schedule = isl_schedule_constraints_compute_schedule(sc);4762	str = "{ D[2,0] -> [] }";4763	sink = isl_union_map_read_from_str(ctx, str);4764	access = isl_union_access_info_from_sink(sink);4765	str = "{ C[2,1] -> [] }";4766	source = isl_union_map_read_from_str(ctx, str);4767	access = isl_union_access_info_set_must_source(access, source);4768	access = isl_union_access_info_set_schedule(access, schedule);4769	flow = isl_union_access_info_compute_flow(access);4770	dep = isl_union_flow_get_must_dependence(flow);4771	isl_union_flow_free(flow);4772	empty = isl_union_map_is_empty(dep);4773	isl_union_map_free(dep);4774 4775	if (empty < 0)4776		return -1;4777	if (empty)4778		isl_die(ctx, isl_error_unknown,4779			"conditional validity not respected", return -1);4780 4781	return 0;4782}4783 4784/* Check that the test for violated conditional validity constraints4785 * is not confused by domain compression.4786 * In particular, earlier versions of isl would apply4787 * a schedule on the compressed domains to the original domains,4788 * resulting in a failure to detect that the default schedule4789 * violates the conditional validity constraints.4790 */4791static int test_special_conditional_schedule_constraints_2(isl_ctx *ctx)4792{4793	const char *str;4794	isl_bool empty;4795	isl_union_set *domain;4796	isl_union_map *validity, *condition;4797	isl_schedule_constraints *sc;4798	isl_schedule *schedule;4799	isl_union_map *umap;4800	isl_map *map, *ge;4801 4802	str = "{ A[0, i] : 0 <= i <= 10; B[1, i] : 0 <= i <= 10 }";4803	domain = isl_union_set_read_from_str(ctx, str);4804	sc = isl_schedule_constraints_on_domain(domain);4805	str = "{ B[1, i] -> A[0, i + 1] }";4806	condition = isl_union_map_read_from_str(ctx, str);4807	str = "{ A[0, i] -> B[1, i - 1] }";4808	validity = isl_union_map_read_from_str(ctx, str);4809	sc = isl_schedule_constraints_set_conditional_validity(sc, condition,4810						isl_union_map_copy(validity));4811	schedule = isl_schedule_constraints_compute_schedule(sc);4812	umap = isl_schedule_get_map(schedule);4813	isl_schedule_free(schedule);4814	validity = isl_union_map_apply_domain(validity,4815						isl_union_map_copy(umap));4816	validity = isl_union_map_apply_range(validity, umap);4817	map = isl_map_from_union_map(validity);4818	ge = isl_map_lex_ge(isl_space_domain(isl_map_get_space(map)));4819	map = isl_map_intersect(map, ge);4820	empty = isl_map_is_empty(map);4821	isl_map_free(map);4822 4823	if (empty < 0)4824		return -1;4825	if (!empty)4826		isl_die(ctx, isl_error_unknown,4827			"conditional validity constraints not satisfied",4828			return -1);4829 4830	return 0;4831}4832 4833/* Input for testing of schedule construction based on4834 * conditional constraints.4835 *4836 * domain is the iteration domain4837 * flow are the flow dependences, which determine the validity and4838 * 	proximity constraints4839 * condition are the conditions on the conditional validity constraints4840 * conditional_validity are the conditional validity constraints4841 * outer_band_n is the expected number of members in the outer band4842 */4843struct {4844	const char *domain;4845	const char *flow;4846	const char *condition;4847	const char *conditional_validity;4848	int outer_band_n;4849} live_range_tests[] = {4850	/* Contrived example that illustrates that we need to keep4851	 * track of tagged condition dependences and4852	 * tagged conditional validity dependences4853	 * in isl_sched_edge separately.4854	 * In particular, the conditional validity constraints on A4855	 * cannot be satisfied,4856	 * but they can be ignored because there are no corresponding4857	 * condition constraints.  However, we do have an additional4858	 * conditional validity constraint that maps to the same4859	 * dependence relation4860	 * as the condition constraint on B.  If we did not make a distinction4861	 * between tagged condition and tagged conditional validity4862	 * dependences, then we4863	 * could end up treating this shared dependence as an condition4864	 * constraint on A, forcing a localization of the conditions,4865	 * which is impossible.4866	 */4867	{ "{ S[i] : 0 <= 1 < 100; T[i] : 0 <= 1 < 100 }",4868	  "{ S[i] -> S[i+1] : 0 <= i < 99 }",4869	  "{ [S[i] -> B[]] -> [S[i+1] -> B[]] : 0 <= i < 99 }",4870	  "{ [S[i] -> A[]] -> [T[i'] -> A[]] : 0 <= i', i < 100 and i != i';"4871	    "[T[i] -> A[]] -> [S[i'] -> A[]] : 0 <= i', i < 100 and i != i';"4872	    "[S[i] -> A[]] -> [S[i+1] -> A[]] : 0 <= i < 99 }",4873	  14874	},4875	/* TACO 2013 Fig. 7 */4876	{ "[n] -> { S1[i,j] : 0 <= i,j < n; S2[i,j] : 0 <= i,j < n }",4877	  "[n] -> { S1[i,j] -> S2[i,j] : 0 <= i,j < n;"4878		   "S2[i,j] -> S2[i,j+1] : 0 <= i < n and 0 <= j < n - 1 }",4879	  "[n] -> { [S1[i,j] -> t[]] -> [S2[i,j] -> t[]] : 0 <= i,j < n;"4880		   "[S2[i,j] -> x1[]] -> [S2[i,j+1] -> x1[]] : "4881				"0 <= i < n and 0 <= j < n - 1 }",4882	  "[n] -> { [S2[i,j] -> t[]] -> [S1[i,j'] -> t[]] : "4883				"0 <= i < n and 0 <= j < j' < n;"4884		   "[S2[i,j] -> t[]] -> [S1[i',j'] -> t[]] : "4885				"0 <= i < i' < n and 0 <= j,j' < n;"4886		   "[S2[i,j] -> x1[]] -> [S2[i,j'] -> x1[]] : "4887				"0 <= i,j,j' < n and j < j' }",4888	    24889	},4890	/* TACO 2013 Fig. 7, without tags */4891	{ "[n] -> { S1[i,j] : 0 <= i,j < n; S2[i,j] : 0 <= i,j < n }",4892	  "[n] -> { S1[i,j] -> S2[i,j] : 0 <= i,j < n;"4893		   "S2[i,j] -> S2[i,j+1] : 0 <= i < n and 0 <= j < n - 1 }",4894	  "[n] -> { S1[i,j] -> S2[i,j] : 0 <= i,j < n;"4895		   "S2[i,j] -> S2[i,j+1] : 0 <= i < n and 0 <= j < n - 1 }",4896	  "[n] -> { S2[i,j] -> S1[i,j'] : 0 <= i < n and 0 <= j < j' < n;"4897		   "S2[i,j] -> S1[i',j'] : 0 <= i < i' < n and 0 <= j,j' < n;"4898		   "S2[i,j] -> S2[i,j'] : 0 <= i,j,j' < n and j < j' }",4899	   14900	},4901	/* TACO 2013 Fig. 12 */4902	{ "{ S1[i,0] : 0 <= i <= 1; S2[i,j] : 0 <= i <= 1 and 1 <= j <= 2;"4903	    "S3[i,3] : 0 <= i <= 1 }",4904	  "{ S1[i,0] -> S2[i,1] : 0 <= i <= 1;"4905	    "S2[i,1] -> S2[i,2] : 0 <= i <= 1;"4906	    "S2[i,2] -> S3[i,3] : 0 <= i <= 1 }",4907	  "{ [S1[i,0]->t[]] -> [S2[i,1]->t[]] : 0 <= i <= 1;"4908	    "[S2[i,1]->t[]] -> [S2[i,2]->t[]] : 0 <= i <= 1;"4909	    "[S2[i,2]->t[]] -> [S3[i,3]->t[]] : 0 <= i <= 1 }",4910	  "{ [S2[i,1]->t[]] -> [S2[i,2]->t[]] : 0 <= i <= 1;"4911	    "[S2[0,j]->t[]] -> [S2[1,j']->t[]] : 1 <= j,j' <= 2;"4912	    "[S2[0,j]->t[]] -> [S1[1,0]->t[]] : 1 <= j <= 2;"4913	    "[S3[0,3]->t[]] -> [S2[1,j]->t[]] : 1 <= j <= 2;"4914	    "[S3[0,3]->t[]] -> [S1[1,0]->t[]] }",4915	   14916	}4917};4918 4919/* Test schedule construction based on conditional constraints.4920 * In particular, check the number of members in the outer band node4921 * as an indication of whether tiling is possible or not.4922 */4923static int test_conditional_schedule_constraints(isl_ctx *ctx)4924{4925	int i;4926	isl_union_set *domain;4927	isl_union_map *condition;4928	isl_union_map *flow;4929	isl_union_map *validity;4930	isl_schedule_constraints *sc;4931	isl_schedule *schedule;4932	isl_schedule_node *node;4933	isl_size n_member;4934 4935	if (test_special_conditional_schedule_constraints(ctx) < 0)4936		return -1;4937	if (test_special_conditional_schedule_constraints_2(ctx) < 0)4938		return -1;4939 4940	for (i = 0; i < ARRAY_SIZE(live_range_tests); ++i) {4941		domain = isl_union_set_read_from_str(ctx,4942				live_range_tests[i].domain);4943		flow = isl_union_map_read_from_str(ctx,4944				live_range_tests[i].flow);4945		condition = isl_union_map_read_from_str(ctx,4946				live_range_tests[i].condition);4947		validity = isl_union_map_read_from_str(ctx,4948				live_range_tests[i].conditional_validity);4949		sc = isl_schedule_constraints_on_domain(domain);4950		sc = isl_schedule_constraints_set_validity(sc,4951				isl_union_map_copy(flow));4952		sc = isl_schedule_constraints_set_proximity(sc, flow);4953		sc = isl_schedule_constraints_set_conditional_validity(sc,4954				condition, validity);4955		schedule = isl_schedule_constraints_compute_schedule(sc);4956		node = isl_schedule_get_root(schedule);4957		while (node &&4958		    isl_schedule_node_get_type(node) != isl_schedule_node_band)4959			node = isl_schedule_node_first_child(node);4960		n_member = isl_schedule_node_band_n_member(node);4961		isl_schedule_node_free(node);4962		isl_schedule_free(schedule);4963 4964		if (!schedule || n_member < 0)4965			return -1;4966		if (n_member != live_range_tests[i].outer_band_n)4967			isl_die(ctx, isl_error_unknown,4968				"unexpected number of members in outer band",4969				return -1);4970	}4971	return 0;4972}4973 4974/* Check that the schedule computed for the given instance set and4975 * dependence relation strongly satisfies the dependences.4976 * In particular, check that no instance is scheduled before4977 * or together with an instance on which it depends.4978 * Earlier versions of isl would produce a schedule that4979 * only weakly satisfies the dependences.4980 */4981static int test_strongly_satisfying_schedule(isl_ctx *ctx)4982{4983	const char *domain, *dep;4984	isl_union_map *D, *schedule;4985	isl_map *map, *ge;4986	int empty;4987 4988	domain = "{ B[i0, i1] : 0 <= i0 <= 1 and 0 <= i1 <= 11; "4989		    "A[i0] : 0 <= i0 <= 1 }";4990	dep = "{ B[i0, i1] -> B[i0, 1 + i1] : 0 <= i0 <= 1 and 0 <= i1 <= 10; "4991		"B[0, 11] -> A[1]; A[i0] -> B[i0, 0] : 0 <= i0 <= 1 }";4992	schedule = compute_schedule(ctx, domain, dep, dep);4993	D = isl_union_map_read_from_str(ctx, dep);4994	D = isl_union_map_apply_domain(D, isl_union_map_copy(schedule));4995	D = isl_union_map_apply_range(D, schedule);4996	map = isl_map_from_union_map(D);4997	ge = isl_map_lex_ge(isl_space_domain(isl_map_get_space(map)));4998	map = isl_map_intersect(map, ge);4999	empty = isl_map_is_empty(map);5000	isl_map_free(map);5001 5002	if (empty < 0)5003		return -1;5004	if (!empty)5005		isl_die(ctx, isl_error_unknown,5006			"dependences not strongly satisfied", return -1);5007 5008	return 0;5009}5010 5011/* Compute a schedule for input where the instance set constraints5012 * conflict with the context constraints.5013 * Earlier versions of isl did not properly handle this situation.5014 */5015static int test_conflicting_context_schedule(isl_ctx *ctx)5016{5017	isl_union_map *schedule;5018	const char *domain, *context;5019 5020	domain = "[n] -> { A[] : n >= 0 }";5021	context = "[n] -> { : n < 0 }";5022	schedule = compute_schedule_with_context(ctx,5023						domain, "{}", "{}", context);5024	isl_union_map_free(schedule);5025 5026	if (!schedule)5027		return -1;5028 5029	return 0;5030}5031 5032/* Check that a set of schedule constraints that only allow for5033 * a coalescing schedule still produces a schedule even if the user5034 * request a non-coalescing schedule.  Earlier versions of isl5035 * would not handle this case correctly.5036 */5037static int test_coalescing_schedule(isl_ctx *ctx)5038{5039	const char *domain, *dep;5040	isl_union_set *I;5041	isl_union_map *D;5042	isl_schedule_constraints *sc;5043	isl_schedule *schedule;5044	int treat_coalescing;5045 5046	domain = "{ S[a, b] : 0 <= a <= 1 and 0 <= b <= 1 }";5047	dep = "{ S[a, b] -> S[a + b, 1 - b] }";5048	I = isl_union_set_read_from_str(ctx, domain);5049	D = isl_union_map_read_from_str(ctx, dep);5050	sc = isl_schedule_constraints_on_domain(I);5051	sc = isl_schedule_constraints_set_validity(sc, D);5052	treat_coalescing = isl_options_get_schedule_treat_coalescing(ctx);5053	isl_options_set_schedule_treat_coalescing(ctx, 1);5054	schedule = isl_schedule_constraints_compute_schedule(sc);5055	isl_options_set_schedule_treat_coalescing(ctx, treat_coalescing);5056	isl_schedule_free(schedule);5057	if (!schedule)5058		return -1;5059	return 0;5060}5061 5062/* Check that the scheduler does not perform any needless5063 * compound skewing.  Earlier versions of isl would compute5064 * schedules in terms of transformed schedule coefficients and5065 * would not accurately keep track of the sum of the original5066 * schedule coefficients.  It could then produce the schedule5067 * S[t,i,j,k] -> [t, 2t + i, 2t + i + j, 2t + i + j + k]5068 * for the input below instead of the schedule below.5069 */5070static int test_skewing_schedule(isl_ctx *ctx)5071{5072	const char *D, *V, *P, *S;5073 5074	D = "[n] -> { S[t,i,j,k] : 0 <= t,i,j,k < n }";5075	V = "[n] -> { S[t,i,j,k] -> S[t+1,a,b,c] : 0 <= t,i,j,k,a,b,c < n and "5076		"-2 <= a-i <= 2 and -1 <= a-i + b-j <= 1 and "5077		"-1 <= a-i + b-j + c-k <= 1 }";5078	P = "{ }";5079	S = "{ S[t,i,j,k] -> [t, 2t + i, t + i + j, 2t + k] }";5080 5081	return test_special_schedule(ctx, D, V, P, S);5082}5083 5084int test_schedule(isl_ctx *ctx)5085{5086	const char *D, *W, *R, *V, *P, *S;5087	int max_coincidence;5088	int treat_coalescing;5089 5090	/* Handle resulting schedule with zero bands. */5091	if (test_one_schedule(ctx, "{[]}", "{}", "{}", "{[] -> []}", 0, 0) < 0)5092		return -1;5093 5094	/* Jacobi */5095	D = "[T,N] -> { S1[t,i] : 1 <= t <= T and 2 <= i <= N - 1 }";5096	W = "{ S1[t,i] -> a[t,i] }";5097	R = "{ S1[t,i] -> a[t-1,i]; S1[t,i] -> a[t-1,i-1]; "5098	    	"S1[t,i] -> a[t-1,i+1] }";5099	S = "{ S1[t,i] -> [t,i] }";5100	if (test_one_schedule(ctx, D, W, R, S, 2, 0) < 0)5101		return -1;5102 5103	/* Fig. 5 of CC2008 */5104	D = "[N] -> { S_0[i, j] : i >= 0 and i <= -1 + N and j >= 2 and "5105				"j <= -1 + N }";5106	W = "[N] -> { S_0[i, j] -> a[i, j] : i >= 0 and i <= -1 + N and "5107				"j >= 2 and j <= -1 + N }";5108	R = "[N] -> { S_0[i, j] -> a[j, i] : i >= 0 and i <= -1 + N and "5109				"j >= 2 and j <= -1 + N; "5110		    "S_0[i, j] -> a[i, -1 + j] : i >= 0 and i <= -1 + N and "5111				"j >= 2 and j <= -1 + N }";5112	S = "[N] -> { S_0[i, j] -> [0, i, 0, j, 0] }";5113	if (test_one_schedule(ctx, D, W, R, S, 2, 0) < 0)5114		return -1;5115 5116	D = "{ S1[i] : 0 <= i <= 10; S2[i] : 0 <= i <= 9 }";5117	W = "{ S1[i] -> a[i] }";5118	R = "{ S2[i] -> a[i+1] }";5119	S = "{ S1[i] -> [0,i]; S2[i] -> [1,i] }";5120	if (test_one_schedule(ctx, D, W, R, S, 1, 1) < 0)5121		return -1;5122 5123	D = "{ S1[i] : 0 <= i < 10; S2[i] : 0 <= i < 10 }";5124	W = "{ S1[i] -> a[i] }";5125	R = "{ S2[i] -> a[9-i] }";5126	S = "{ S1[i] -> [0,i]; S2[i] -> [1,i] }";5127	if (test_one_schedule(ctx, D, W, R, S, 1, 1) < 0)5128		return -1;5129 5130	D = "[N] -> { S1[i] : 0 <= i < N; S2[i] : 0 <= i < N }";5131	W = "{ S1[i] -> a[i] }";5132	R = "[N] -> { S2[i] -> a[N-1-i] }";5133	S = "{ S1[i] -> [0,i]; S2[i] -> [1,i] }";5134	if (test_one_schedule(ctx, D, W, R, S, 1, 1) < 0)5135		return -1;5136	5137	D = "{ S1[i] : 0 < i < 10; S2[i] : 0 <= i < 10 }";5138	W = "{ S1[i] -> a[i]; S2[i] -> b[i] }";5139	R = "{ S2[i] -> a[i]; S1[i] -> b[i-1] }";5140	S = "{ S1[i] -> [i,0]; S2[i] -> [i,1] }";5141	if (test_one_schedule(ctx, D, W, R, S, 0, 0) < 0)5142		return -1;5143 5144	D = "[N] -> { S1[i] : 1 <= i <= N; S2[i,j] : 1 <= i,j <= N }";5145	W = "{ S1[i] -> a[0,i]; S2[i,j] -> a[i,j] }";5146	R = "{ S2[i,j] -> a[i-1,j] }";5147	S = "{ S1[i] -> [0,i,0]; S2[i,j] -> [1,i,j] }";5148	if (test_one_schedule(ctx, D, W, R, S, 2, 1) < 0)5149		return -1;5150 5151	D = "[N] -> { S1[i] : 1 <= i <= N; S2[i,j] : 1 <= i,j <= N }";5152	W = "{ S1[i] -> a[i,0]; S2[i,j] -> a[i,j] }";5153	R = "{ S2[i,j] -> a[i,j-1] }";5154	S = "{ S1[i] -> [0,i,0]; S2[i,j] -> [1,i,j] }";5155	if (test_one_schedule(ctx, D, W, R, S, 2, 1) < 0)5156		return -1;5157 5158	D = "[N] -> { S_0[]; S_1[i] : i >= 0 and i <= -1 + N; S_2[] }";5159	W = "[N] -> { S_0[] -> a[0]; S_2[] -> b[0]; "5160		    "S_1[i] -> a[1 + i] : i >= 0 and i <= -1 + N }";5161	R = "[N] -> { S_2[] -> a[N]; S_1[i] -> a[i] : i >= 0 and i <= -1 + N }";5162	S = "[N] -> { S_1[i] -> [1, i, 0]; S_2[] -> [2, 0, 1]; "5163		    "S_0[] -> [0, 0, 0] }";5164	if (test_one_schedule(ctx, D, W, R, S, 1, 0) < 0)5165		return -1;5166	ctx->opt->schedule_parametric = 0;5167	if (test_one_schedule(ctx, D, W, R, S, 0, 0) < 0)5168		return -1;5169	ctx->opt->schedule_parametric = 1;5170 5171	D = "[N] -> { S1[i] : 1 <= i <= N; S2[i] : 1 <= i <= N; "5172		    "S3[i,j] : 1 <= i,j <= N; S4[i] : 1 <= i <= N }";5173	W = "{ S1[i] -> a[i,0]; S2[i] -> a[0,i]; S3[i,j] -> a[i,j] }";5174	R = "[N] -> { S3[i,j] -> a[i-1,j]; S3[i,j] -> a[i,j-1]; "5175		    "S4[i] -> a[i,N] }";5176	S = "{ S1[i] -> [0,i,0]; S2[i] -> [1,i,0]; S3[i,j] -> [2,i,j]; "5177		"S4[i] -> [4,i,0] }";5178	max_coincidence = isl_options_get_schedule_maximize_coincidence(ctx);5179	isl_options_set_schedule_maximize_coincidence(ctx, 0);5180	if (test_one_schedule(ctx, D, W, R, S, 2, 0) < 0)5181		return -1;5182	isl_options_set_schedule_maximize_coincidence(ctx, max_coincidence);5183 5184	D = "[N] -> { S_0[i, j] : i >= 1 and i <= N and j >= 1 and j <= N }";5185	W = "[N] -> { S_0[i, j] -> s[0] : i >= 1 and i <= N and j >= 1 and "5186					"j <= N }";5187	R = "[N] -> { S_0[i, j] -> s[0] : i >= 1 and i <= N and j >= 1 and "5188					"j <= N; "5189		    "S_0[i, j] -> a[i, j] : i >= 1 and i <= N and j >= 1 and "5190					"j <= N }";5191	S = "[N] -> { S_0[i, j] -> [0, i, 0, j, 0] }";5192	if (test_one_schedule(ctx, D, W, R, S, 0, 0) < 0)5193		return -1;5194 5195	D = "[N] -> { S_0[t] : t >= 0 and t <= -1 + N; "5196		    " S_2[t] : t >= 0 and t <= -1 + N; "5197		    " S_1[t, i] : t >= 0 and t <= -1 + N and i >= 0 and "5198				"i <= -1 + N }";5199	W = "[N] -> { S_0[t] -> a[t, 0] : t >= 0 and t <= -1 + N; "5200		    " S_2[t] -> b[t] : t >= 0 and t <= -1 + N; "5201		    " S_1[t, i] -> a[t, 1 + i] : t >= 0 and t <= -1 + N and "5202						"i >= 0 and i <= -1 + N }";5203	R = "[N] -> { S_1[t, i] -> a[t, i] : t >= 0 and t <= -1 + N and "5204					    "i >= 0 and i <= -1 + N; "5205		    " S_2[t] -> a[t, N] : t >= 0 and t <= -1 + N }";5206	S = "[N] -> { S_2[t] -> [0, t, 2]; S_1[t, i] -> [0, t, 1, i, 0]; "5207		    " S_0[t] -> [0, t, 0] }";5208 5209	if (test_one_schedule(ctx, D, W, R, S, 2, 1) < 0)5210		return -1;5211	ctx->opt->schedule_parametric = 0;5212	if (test_one_schedule(ctx, D, W, R, S, 0, 0) < 0)5213		return -1;5214	ctx->opt->schedule_parametric = 1;5215 5216	D = "[N] -> { S1[i,j] : 0 <= i,j < N; S2[i,j] : 0 <= i,j < N }";5217	S = "{ S1[i,j] -> [0,i,j]; S2[i,j] -> [1,i,j] }";5218	if (test_one_schedule(ctx, D, "{}", "{}", S, 2, 2) < 0)5219		return -1;5220 5221	D = "[M, N] -> { S_1[i] : i >= 0 and i <= -1 + M; "5222	    "S_0[i, j] : i >= 0 and i <= -1 + M and j >= 0 and j <= -1 + N }";5223	W = "[M, N] -> { S_0[i, j] -> a[j] : i >= 0 and i <= -1 + M and "5224					    "j >= 0 and j <= -1 + N; "5225			"S_1[i] -> b[0] : i >= 0 and i <= -1 + M }";5226	R = "[M, N] -> { S_0[i, j] -> a[0] : i >= 0 and i <= -1 + M and "5227					    "j >= 0 and j <= -1 + N; "5228			"S_1[i] -> b[0] : i >= 0 and i <= -1 + M }";5229	S = "[M, N] -> { S_1[i] -> [1, i, 0]; S_0[i, j] -> [0, i, 0, j, 0] }";5230	if (test_one_schedule(ctx, D, W, R, S, 0, 0) < 0)5231		return -1;5232 5233	D = "{ S_0[i] : i >= 0 }";5234	W = "{ S_0[i] -> a[i] : i >= 0 }";5235	R = "{ S_0[i] -> a[0] : i >= 0 }";5236	S = "{ S_0[i] -> [0, i, 0] }";5237	if (test_one_schedule(ctx, D, W, R, S, 0, 0) < 0)5238		return -1;5239 5240	D = "{ S_0[i] : i >= 0; S_1[i] : i >= 0 }";5241	W = "{ S_0[i] -> a[i] : i >= 0; S_1[i] -> b[i] : i >= 0 }";5242	R = "{ S_0[i] -> b[0] : i >= 0; S_1[i] -> a[i] : i >= 0 }";5243	S = "{ S_1[i] -> [0, i, 1]; S_0[i] -> [0, i, 0] }";5244	if (test_one_schedule(ctx, D, W, R, S, 0, 0) < 0)5245		return -1;5246 5247	D = "[n] -> { S_0[j, k] : j <= -1 + n and j >= 0 and "5248				"k <= -1 + n and k >= 0 }";5249	W = "[n] -> { S_0[j, k] -> B[j] : j <= -1 + n and j >= 0 and "							"k <= -1 + n and k >= 0 }";5250	R = "[n] -> { S_0[j, k] -> B[j] : j <= -1 + n and j >= 0 and "5251					"k <= -1 + n and k >= 0; "5252		    "S_0[j, k] -> B[k] : j <= -1 + n and j >= 0 and "5253					"k <= -1 + n and k >= 0; "5254		    "S_0[j, k] -> A[k] : j <= -1 + n and j >= 0 and "5255					"k <= -1 + n and k >= 0 }";5256	S = "[n] -> { S_0[j, k] -> [2, j, k] }";5257	ctx->opt->schedule_outer_coincidence = 1;5258	if (test_one_schedule(ctx, D, W, R, S, 0, 0) < 0)5259		return -1;5260	ctx->opt->schedule_outer_coincidence = 0;5261 5262	D = "{Stmt_for_body24[i0, i1, i2, i3]:"5263		"i0 >= 0 and i0 <= 1 and i1 >= 0 and i1 <= 6 and i2 >= 2 and "5264		"i2 <= 6 - i1 and i3 >= 0 and i3 <= -1 + i2;"5265	     "Stmt_for_body24[i0, i1, 1, 0]:"5266		"i0 >= 0 and i0 <= 1 and i1 >= 0 and i1 <= 5;"5267	     "Stmt_for_body7[i0, i1, i2]:"5268		"i0 >= 0 and i0 <= 1 and i1 >= 0 and i1 <= 7 and i2 >= 0 and "5269		"i2 <= 7 }";5270 5271	V = "{Stmt_for_body24[0, i1, i2, i3] -> "5272		"Stmt_for_body24[1, i1, i2, i3]:"5273		"i3 >= 0 and i3 <= -1 + i2 and i1 >= 0 and i2 <= 6 - i1 and "5274		"i2 >= 1;"5275	     "Stmt_for_body24[0, i1, i2, i3] -> "5276		"Stmt_for_body7[1, 1 + i1 + i3, 1 + i1 + i2]:"5277		"i3 <= -1 + i2 and i2 <= 6 - i1 and i2 >= 1 and i1 >= 0 and "5278		"i3 >= 0;"5279	      "Stmt_for_body24[0, i1, i2, i3] ->"5280		"Stmt_for_body7[1, i1, 1 + i1 + i3]:"5281		"i3 >= 0 and i2 <= 6 - i1 and i1 >= 0 and i3 <= -1 + i2;"5282	      "Stmt_for_body7[0, i1, i2] -> Stmt_for_body7[1, i1, i2]:"5283		"(i2 >= 1 + i1 and i2 <= 6 and i1 >= 0 and i1 <= 4) or "5284		"(i2 >= 3 and i2 <= 7 and i1 >= 1 and i2 >= 1 + i1) or "5285		"(i2 >= 0 and i2 <= i1 and i2 >= -7 + i1 and i1 <= 7);"5286	      "Stmt_for_body7[0, i1, 1 + i1] -> Stmt_for_body7[1, i1, 1 + i1]:"5287		"i1 <= 6 and i1 >= 0;"5288	      "Stmt_for_body7[0, 0, 7] -> Stmt_for_body7[1, 0, 7];"5289	      "Stmt_for_body7[i0, i1, i2] -> "5290		"Stmt_for_body24[i0, o1, -1 + i2 - o1, -1 + i1 - o1]:"5291		"i0 >= 0 and i0 <= 1 and o1 >= 0 and i2 >= 1 + i1 and "5292		"o1 <= -2 + i2 and i2 <= 7 and o1 <= -1 + i1;"5293	      "Stmt_for_body7[i0, i1, i2] -> "5294		"Stmt_for_body24[i0, i1, o2, -1 - i1 + i2]:"5295		"i0 >= 0 and i0 <= 1 and i1 >= 0 and o2 >= -i1 + i2 and "5296		"o2 >= 1 and o2 <= 6 - i1 and i2 >= 1 + i1 }";5297	P = V;5298 5299	treat_coalescing = isl_options_get_schedule_treat_coalescing(ctx);5300	isl_options_set_schedule_treat_coalescing(ctx, 0);5301	if (test_has_schedule(ctx, D, V, P) < 0)5302		return -1;5303	isl_options_set_schedule_treat_coalescing(ctx, treat_coalescing);5304 5305	D = "{ S_0[i, j] : i >= 1 and i <= 10 and j >= 1 and j <= 8 }";5306	V = "{ S_0[i, j] -> S_0[i, 1 + j] : i >= 1 and i <= 10 and "5307					   "j >= 1 and j <= 7;"5308		"S_0[i, j] -> S_0[1 + i, j] : i >= 1 and i <= 9 and "5309					     "j >= 1 and j <= 8 }";5310	P = "{ }";5311	S = "{ S_0[i, j] -> [i + j, i] }";5312	ctx->opt->schedule_algorithm = ISL_SCHEDULE_ALGORITHM_FEAUTRIER;5313	if (test_special_schedule(ctx, D, V, P, S) < 0)5314		return -1;5315	ctx->opt->schedule_algorithm = ISL_SCHEDULE_ALGORITHM_ISL;5316 5317	/* Fig. 1 from Feautrier's "Some Efficient Solutions..." pt. 2, 1992 */5318	D = "[N] -> { S_0[i, j] : i >= 0 and i <= -1 + N and "5319				 "j >= 0 and j <= -1 + i }";5320	V = "[N] -> { S_0[i, j] -> S_0[i, 1 + j] : j <= -2 + i and "5321					"i <= -1 + N and j >= 0;"5322		     "S_0[i, -1 + i] -> S_0[1 + i, 0] : i >= 1 and "5323					"i <= -2 + N }";5324	P = "{ }";5325	S = "{ S_0[i, j] -> [i, j] }";5326	ctx->opt->schedule_algorithm = ISL_SCHEDULE_ALGORITHM_FEAUTRIER;5327	if (test_special_schedule(ctx, D, V, P, S) < 0)5328		return -1;5329	ctx->opt->schedule_algorithm = ISL_SCHEDULE_ALGORITHM_ISL;5330 5331	/* Test both algorithms on a case with only proximity dependences. */5332	D = "{ S[i,j] : 0 <= i <= 10 }";5333	V = "{ }";5334	P = "{ S[i,j] -> S[i+1,j] : 0 <= i,j <= 10 }";5335	S = "{ S[i, j] -> [j, i] }";5336	ctx->opt->schedule_algorithm = ISL_SCHEDULE_ALGORITHM_FEAUTRIER;5337	if (test_special_schedule(ctx, D, V, P, S) < 0)5338		return -1;5339	ctx->opt->schedule_algorithm = ISL_SCHEDULE_ALGORITHM_ISL;5340	if (test_special_schedule(ctx, D, V, P, S) < 0)5341		return -1;5342	5343	D = "{ A[a]; B[] }";5344	V = "{}";5345	P = "{ A[a] -> B[] }";5346	if (test_has_schedule(ctx, D, V, P) < 0)5347		return -1;5348 5349	if (test_padded_schedule(ctx) < 0)5350		return -1;5351 5352	/* Check that check for progress is not confused by rational5353	 * solution.5354	 */5355	D = "[N] -> { S0[i, j] : i >= 0 and i <= N and j >= 0 and j <= N }";5356	V = "[N] -> { S0[i0, -1 + N] -> S0[2 + i0, 0] : i0 >= 0 and "5357							"i0 <= -2 + N; "5358			"S0[i0, i1] -> S0[i0, 1 + i1] : i0 >= 0 and "5359				"i0 <= N and i1 >= 0 and i1 <= -1 + N }";5360	P = "{}";5361	ctx->opt->schedule_algorithm = ISL_SCHEDULE_ALGORITHM_FEAUTRIER;5362	if (test_has_schedule(ctx, D, V, P) < 0)5363		return -1;5364	ctx->opt->schedule_algorithm = ISL_SCHEDULE_ALGORITHM_ISL;5365 5366	/* Check that we allow schedule rows that are only non-trivial5367	 * on some full-dimensional domains.5368	 */5369	D = "{ S1[j] : 0 <= j <= 1; S0[]; S2[k] : 0 <= k <= 1 }";5370	V = "{ S0[] -> S1[j] : 0 <= j <= 1; S2[0] -> S0[];"5371		"S1[j] -> S2[1] : 0 <= j <= 1 }";5372	P = "{}";5373	ctx->opt->schedule_algorithm = ISL_SCHEDULE_ALGORITHM_FEAUTRIER;5374	if (test_has_schedule(ctx, D, V, P) < 0)5375		return -1;5376	ctx->opt->schedule_algorithm = ISL_SCHEDULE_ALGORITHM_ISL;5377 5378	if (test_conditional_schedule_constraints(ctx) < 0)5379		return -1;5380 5381	if (test_strongly_satisfying_schedule(ctx) < 0)5382		return -1;5383 5384	if (test_conflicting_context_schedule(ctx) < 0)5385		return -1;5386 5387	if (test_coalescing_schedule(ctx) < 0)5388		return -1;5389	if (test_skewing_schedule(ctx) < 0)5390		return -1;5391 5392	return 0;5393}5394 5395/* Perform scheduling tests using the whole component scheduler.5396 */5397static int test_schedule_whole(isl_ctx *ctx)5398{5399	int whole;5400	int r;5401 5402	whole = isl_options_get_schedule_whole_component(ctx);5403	isl_options_set_schedule_whole_component(ctx, 1);5404	r = test_schedule(ctx);5405	isl_options_set_schedule_whole_component(ctx, whole);5406 5407	return r;5408}5409 5410/* Perform scheduling tests using the incremental scheduler.5411 */5412static int test_schedule_incremental(isl_ctx *ctx)5413{5414	int whole;5415	int r;5416 5417	whole = isl_options_get_schedule_whole_component(ctx);5418	isl_options_set_schedule_whole_component(ctx, 0);5419	r = test_schedule(ctx);5420	isl_options_set_schedule_whole_component(ctx, whole);5421 5422	return r;5423}5424 5425int test_plain_injective(isl_ctx *ctx, const char *str, int injective)5426{5427	isl_union_map *umap;5428	int test;5429 5430	umap = isl_union_map_read_from_str(ctx, str);5431	test = isl_union_map_plain_is_injective(umap);5432	isl_union_map_free(umap);5433	if (test < 0)5434		return -1;5435	if (test == injective)5436		return 0;5437	if (injective)5438		isl_die(ctx, isl_error_unknown,5439			"map not detected as injective", return -1);5440	else5441		isl_die(ctx, isl_error_unknown,5442			"map detected as injective", return -1);5443}5444 5445int test_injective(isl_ctx *ctx)5446{5447	const char *str;5448 5449	if (test_plain_injective(ctx, "{S[i,j] -> A[0]; T[i,j] -> B[1]}", 0))5450		return -1;5451	if (test_plain_injective(ctx, "{S[] -> A[0]; T[] -> B[0]}", 1))5452		return -1;5453	if (test_plain_injective(ctx, "{S[] -> A[0]; T[] -> A[1]}", 1))5454		return -1;5455	if (test_plain_injective(ctx, "{S[] -> A[0]; T[] -> A[0]}", 0))5456		return -1;5457	if (test_plain_injective(ctx, "{S[i] -> A[i,0]; T[i] -> A[i,1]}", 1))5458		return -1;5459	if (test_plain_injective(ctx, "{S[i] -> A[i]; T[i] -> A[i]}", 0))5460		return -1;5461	if (test_plain_injective(ctx, "{S[] -> A[0,0]; T[] -> A[0,1]}", 1))5462		return -1;5463	if (test_plain_injective(ctx, "{S[] -> A[0,0]; T[] -> A[1,0]}", 1))5464		return -1;5465 5466	str = "{S[] -> A[0,0]; T[] -> A[0,1]; U[] -> A[1,0]}";5467	if (test_plain_injective(ctx, str, 1))5468		return -1;5469	str = "{S[] -> A[0,0]; T[] -> A[0,1]; U[] -> A[0,0]}";5470	if (test_plain_injective(ctx, str, 0))5471		return -1;5472 5473	return 0;5474}5475 5476#undef BASE5477#define BASE	aff5478#include "isl_test_plain_equal_templ.c"5479 5480#undef BASE5481#define BASE	pw_multi_aff5482#include "isl_test_plain_equal_templ.c"5483 5484#undef BASE5485#define BASE	union_pw_aff5486#include "isl_test_plain_equal_templ.c"5487 5488/* Basic tests on isl_union_pw_aff.5489 *5490 * In particular, check that isl_union_pw_aff_aff_on_domain5491 * aligns the parameters of the input objects and5492 * that isl_union_pw_aff_param_on_domain_id properly5493 * introduces the parameter.5494 */5495static int test_upa(isl_ctx *ctx)5496{5497	const char *str;5498	isl_id *id;5499	isl_aff *aff;5500	isl_union_set *domain;5501	isl_union_pw_aff *upa;5502	isl_stat ok;5503 5504	aff = isl_aff_read_from_str(ctx, "[N] -> { [N] }");5505	str = "[M] -> { A[i] : 0 <= i < M; B[] }";5506	domain = isl_union_set_read_from_str(ctx, str);5507	upa = isl_union_pw_aff_aff_on_domain(domain, aff);5508	str = "[N, M] -> { A[i] -> [N] : 0 <= i < M; B[] -> [N] }";5509	ok = union_pw_aff_check_plain_equal(upa, str);5510	isl_union_pw_aff_free(upa);5511	if (ok < 0)5512		return -1;5513 5514	id = isl_id_alloc(ctx, "N", NULL);5515	str = "[M] -> { A[i] : 0 <= i < M; B[] }";5516	domain = isl_union_set_read_from_str(ctx, str);5517	upa = isl_union_pw_aff_param_on_domain_id(domain, id);5518	str = "[N, M] -> { A[i] -> [N] : 0 <= i < M; B[] -> [N] }";5519	ok = union_pw_aff_check_plain_equal(upa, str);5520	isl_union_pw_aff_free(upa);5521	if (ok < 0)5522		return -1;5523 5524	return 0;5525}5526 5527struct {5528	__isl_give isl_aff *(*fn)(__isl_take isl_aff *aff1,5529				__isl_take isl_aff *aff2);5530} aff_bin_op[] = {5531	['+'] = { &isl_aff_add },5532	['-'] = { &isl_aff_sub },5533	['*'] = { &isl_aff_mul },5534	['/'] = { &isl_aff_div },5535};5536 5537struct {5538	const char *arg1;5539	unsigned char op;5540	const char *arg2;5541	const char *res;5542} aff_bin_tests[] = {5543	{ "{ [i] -> [i] }", '+', "{ [i] -> [i] }",5544	  "{ [i] -> [2i] }" },5545	{ "{ [i] -> [i] }", '-', "{ [i] -> [i] }",5546	  "{ [i] -> [0] }" },5547	{ "{ [i] -> [i] }", '*', "{ [i] -> [2] }",5548	  "{ [i] -> [2i] }" },5549	{ "{ [i] -> [2] }", '*', "{ [i] -> [i] }",5550	  "{ [i] -> [2i] }" },5551	{ "{ [i] -> [i] }", '/', "{ [i] -> [2] }",5552	  "{ [i] -> [i/2] }" },5553	{ "{ [i] -> [2i] }", '/', "{ [i] -> [2] }",5554	  "{ [i] -> [i] }" },5555	{ "{ [i] -> [i] }", '+', "{ [i] -> [NaN] }",5556	  "{ [i] -> [NaN] }" },5557	{ "{ [i] -> [i] }", '-', "{ [i] -> [NaN] }",5558	  "{ [i] -> [NaN] }" },5559	{ "{ [i] -> [i] }", '*', "{ [i] -> [NaN] }",5560	  "{ [i] -> [NaN] }" },5561	{ "{ [i] -> [2] }", '*', "{ [i] -> [NaN] }",5562	  "{ [i] -> [NaN] }" },5563	{ "{ [i] -> [i] }", '/', "{ [i] -> [NaN] }",5564	  "{ [i] -> [NaN] }" },5565	{ "{ [i] -> [2] }", '/', "{ [i] -> [NaN] }",5566	  "{ [i] -> [NaN] }" },5567	{ "{ [i] -> [NaN] }", '+', "{ [i] -> [i] }",5568	  "{ [i] -> [NaN] }" },5569	{ "{ [i] -> [NaN] }", '-', "{ [i] -> [i] }",5570	  "{ [i] -> [NaN] }" },5571	{ "{ [i] -> [NaN] }", '*', "{ [i] -> [2] }",5572	  "{ [i] -> [NaN] }" },5573	{ "{ [i] -> [NaN] }", '*', "{ [i] -> [i] }",5574	  "{ [i] -> [NaN] }" },5575	{ "{ [i] -> [NaN] }", '/', "{ [i] -> [2] }",5576	  "{ [i] -> [NaN] }" },5577	{ "{ [i] -> [NaN] }", '/', "{ [i] -> [i] }",5578	  "{ [i] -> [NaN] }" },5579	{ "{ [i] -> [i] }", '/', "{ [i] -> [0] }",5580	  "{ [i] -> [NaN] }" },5581};5582 5583/* Perform some basic tests of binary operations on isl_aff objects.5584 */5585static int test_bin_aff(isl_ctx *ctx)5586{5587	int i;5588	isl_aff *aff1, *aff2, *res;5589	__isl_give isl_aff *(*fn)(__isl_take isl_aff *aff1,5590				__isl_take isl_aff *aff2);5591	int ok;5592 5593	for (i = 0; i < ARRAY_SIZE(aff_bin_tests); ++i) {5594		aff1 = isl_aff_read_from_str(ctx, aff_bin_tests[i].arg1);5595		aff2 = isl_aff_read_from_str(ctx, aff_bin_tests[i].arg2);5596		res = isl_aff_read_from_str(ctx, aff_bin_tests[i].res);5597		fn = aff_bin_op[aff_bin_tests[i].op].fn;5598		aff1 = fn(aff1, aff2);5599		if (isl_aff_is_nan(res))5600			ok = isl_aff_is_nan(aff1);5601		else5602			ok = isl_aff_plain_is_equal(aff1, res);5603		isl_aff_free(aff1);5604		isl_aff_free(res);5605		if (ok < 0)5606			return -1;5607		if (!ok)5608			isl_die(ctx, isl_error_unknown,5609				"unexpected result", return -1);5610	}5611 5612	return 0;5613}5614 5615struct {5616	__isl_give isl_pw_aff *(*fn)(__isl_take isl_pw_aff *pa1,5617				     __isl_take isl_pw_aff *pa2);5618} pw_aff_bin_op[] = {5619	['m'] = { &isl_pw_aff_min },5620	['M'] = { &isl_pw_aff_max },5621};5622 5623/* Inputs for binary isl_pw_aff operation tests.5624 * "arg1" and "arg2" are the two arguments, "op" identifies the operation5625 * defined by pw_aff_bin_op, and "res" is the expected result.5626 */5627struct {5628	const char *arg1;5629	unsigned char op;5630	const char *arg2;5631	const char *res;5632} pw_aff_bin_tests[] = {5633	{ "{ [i] -> [i] }", 'm', "{ [i] -> [i] }",5634	  "{ [i] -> [i] }" },5635	{ "{ [i] -> [i] }", 'M', "{ [i] -> [i] }",5636	  "{ [i] -> [i] }" },5637	{ "{ [i] -> [i] }", 'm', "{ [i] -> [0] }",5638	  "{ [i] -> [i] : i <= 0; [i] -> [0] : i > 0 }" },5639	{ "{ [i] -> [i] }", 'M', "{ [i] -> [0] }",5640	  "{ [i] -> [i] : i >= 0; [i] -> [0] : i < 0 }" },5641	{ "{ [i] -> [i] }", 'm', "{ [i] -> [NaN] }",5642	  "{ [i] -> [NaN] }" },5643	{ "{ [i] -> [NaN] }", 'm', "{ [i] -> [i] }",5644	  "{ [i] -> [NaN] }" },5645};5646 5647/* Perform some basic tests of binary operations on isl_pw_aff objects.5648 */5649static int test_bin_pw_aff(isl_ctx *ctx)5650{5651	int i;5652	isl_bool ok;5653	isl_pw_aff *pa1, *pa2, *res;5654 5655	for (i = 0; i < ARRAY_SIZE(pw_aff_bin_tests); ++i) {5656		pa1 = isl_pw_aff_read_from_str(ctx, pw_aff_bin_tests[i].arg1);5657		pa2 = isl_pw_aff_read_from_str(ctx, pw_aff_bin_tests[i].arg2);5658		res = isl_pw_aff_read_from_str(ctx, pw_aff_bin_tests[i].res);5659		pa1 = pw_aff_bin_op[pw_aff_bin_tests[i].op].fn(pa1, pa2);5660		if (isl_pw_aff_involves_nan(res))5661			ok = isl_pw_aff_involves_nan(pa1);5662		else5663			ok = isl_pw_aff_plain_is_equal(pa1, res);5664		isl_pw_aff_free(pa1);5665		isl_pw_aff_free(res);5666		if (ok < 0)5667			return -1;5668		if (!ok)5669			isl_die(ctx, isl_error_unknown,5670				"unexpected result", return -1);5671	}5672 5673	return 0;5674}5675 5676/* Inputs for basic tests of test operations on5677 * isl_union_pw_multi_aff objects.5678 * "fn" is the function that is being tested.5679 * "arg" is a string description of the input.5680 * "res" is the expected result.5681 */5682static struct {5683	isl_bool (*fn)(__isl_keep isl_union_pw_multi_aff *upma1);5684	const char *arg;5685	isl_bool res;5686} upma_test_tests[] = {5687	{ &isl_union_pw_multi_aff_involves_nan, "{ A[] -> [0]; B[0] -> [1] }",5688	  isl_bool_false },5689	{ &isl_union_pw_multi_aff_involves_nan, "{ A[] -> [NaN]; B[0] -> [1] }",5690	  isl_bool_true },5691	{ &isl_union_pw_multi_aff_involves_nan, "{ A[] -> [0]; B[0] -> [NaN] }",5692	  isl_bool_true },5693	{ &isl_union_pw_multi_aff_involves_nan,5694	  "{ A[] -> [0]; B[0] -> [1, NaN, 5] }",5695	  isl_bool_true },5696	{ &isl_union_pw_multi_aff_involves_locals,5697	  "{ A[] -> [0]; B[0] -> [1] }",5698	  isl_bool_false },5699	{ &isl_union_pw_multi_aff_involves_locals,5700	  "{ A[] -> [0]; B[x] -> [1] : x mod 2 = 0 }",5701	  isl_bool_true },5702	{ &isl_union_pw_multi_aff_involves_locals,5703	  "{ A[] -> [0]; B[x] -> [x // 2] }",5704	  isl_bool_true },5705	{ &isl_union_pw_multi_aff_involves_locals,5706	  "{ A[i] -> [i // 2]; B[0] -> [1] }",5707	  isl_bool_true },5708};5709 5710/* Perform some basic tests of test operations on5711 * isl_union_pw_multi_aff objects.5712 */5713static isl_stat test_upma_test(isl_ctx *ctx)5714{5715	int i;5716	isl_union_pw_multi_aff *upma;5717	isl_bool res;5718 5719	for (i = 0; i < ARRAY_SIZE(upma_test_tests); ++i) {5720		const char *str;5721 5722		str = upma_test_tests[i].arg;5723		upma = isl_union_pw_multi_aff_read_from_str(ctx, str);5724		res = upma_test_tests[i].fn(upma);5725		isl_union_pw_multi_aff_free(upma);5726		if (res < 0)5727			return isl_stat_error;5728		if (res != upma_test_tests[i].res)5729			isl_die(ctx, isl_error_unknown,5730				"unexpected result", return isl_stat_error);5731	}5732 5733	return isl_stat_ok;5734}5735 5736struct {5737	__isl_give isl_union_pw_multi_aff *(*fn)(5738		__isl_take isl_union_pw_multi_aff *upma1,5739		__isl_take isl_union_pw_multi_aff *upma2);5740	const char *arg1;5741	const char *arg2;5742	const char *res;5743} upma_bin_tests[] = {5744	{ &isl_union_pw_multi_aff_add, "{ A[] -> [0]; B[0] -> [1] }",5745	  "{ B[x] -> [2] : x >= 0 }", "{ B[0] -> [3] }" },5746	{ &isl_union_pw_multi_aff_union_add, "{ A[] -> [0]; B[0] -> [1] }",5747	  "{ B[x] -> [2] : x >= 0 }",5748	  "{ A[] -> [0]; B[0] -> [3]; B[x] -> [2] : x >= 1 }" },5749	{ &isl_union_pw_multi_aff_pullback_union_pw_multi_aff,5750	  "{ A[] -> B[0]; C[x] -> B[1] : x < 10; C[y] -> B[2] : y >= 10 }",5751	  "{ D[i] -> A[] : i < 0; D[i] -> C[i + 5] : i >= 0 }",5752	  "{ D[i] -> B[0] : i < 0; D[i] -> B[1] : 0 <= i < 5; "5753	    "D[i] -> B[2] : i >= 5 }" },5754	{ &isl_union_pw_multi_aff_union_add, "{ B[x] -> A[1] : x <= 0 }",5755	  "{ B[x] -> C[2] : x > 0 }",5756	  "{ B[x] -> A[1] : x <= 0; B[x] -> C[2] : x > 0 }" },5757	{ &isl_union_pw_multi_aff_union_add, "{ B[x] -> A[1] : x <= 0 }",5758	  "{ B[x] -> A[2] : x >= 0 }",5759	  "{ B[x] -> A[1] : x < 0; B[x] -> A[2] : x > 0; B[0] -> A[3] }" },5760	{5761  &isl_union_pw_multi_aff_preimage_domain_wrapped_domain_union_pw_multi_aff,5762	  "{ B[x] -> C[x + 2] }",5763	  "{ D[y] -> B[2y] }",5764	  "{ }" },5765	{5766  &isl_union_pw_multi_aff_preimage_domain_wrapped_domain_union_pw_multi_aff,5767	  "{ [A[x] -> B[x + 1]] -> C[x + 2] }",5768	  "{ D[y] -> B[2y] }",5769	  "{ }" },5770	{5771  &isl_union_pw_multi_aff_preimage_domain_wrapped_domain_union_pw_multi_aff,5772	  "{ [A[x] -> B[x + 1]] -> C[x + 2]; B[x] -> C[x + 2] }",5773	  "{ D[y] -> A[2y] }",5774	  "{ [D[y] -> B[2y + 1]] -> C[2y + 2] }" },5775	{5776  &isl_union_pw_multi_aff_preimage_domain_wrapped_domain_union_pw_multi_aff,5777	  "{ T[A[x] -> B[x + 1]] -> C[x + 2]; B[x] -> C[x + 2] }",5778	  "{ D[y] -> A[2y] }",5779	  "{ T[D[y] -> B[2y + 1]] -> C[2y + 2] }" },5780};5781 5782/* Perform some basic tests of binary operations on5783 * isl_union_pw_multi_aff objects.5784 */5785static int test_bin_upma(isl_ctx *ctx)5786{5787	int i;5788	isl_union_pw_multi_aff *upma1, *upma2, *res;5789	int ok;5790 5791	for (i = 0; i < ARRAY_SIZE(upma_bin_tests); ++i) {5792		upma1 = isl_union_pw_multi_aff_read_from_str(ctx,5793							upma_bin_tests[i].arg1);5794		upma2 = isl_union_pw_multi_aff_read_from_str(ctx,5795							upma_bin_tests[i].arg2);5796		res = isl_union_pw_multi_aff_read_from_str(ctx,5797							upma_bin_tests[i].res);5798		upma1 = upma_bin_tests[i].fn(upma1, upma2);5799		ok = isl_union_pw_multi_aff_plain_is_equal(upma1, res);5800		isl_union_pw_multi_aff_free(upma1);5801		isl_union_pw_multi_aff_free(res);5802		if (ok < 0)5803			return -1;5804		if (!ok)5805			isl_die(ctx, isl_error_unknown,5806				"unexpected result", return -1);5807	}5808 5809	return 0;5810}5811 5812struct {5813	__isl_give isl_union_pw_multi_aff *(*fn)(5814		__isl_take isl_union_pw_multi_aff *upma1,5815		__isl_take isl_union_pw_multi_aff *upma2);5816	const char *arg1;5817	const char *arg2;5818} upma_bin_fail_tests[] = {5819	{ &isl_union_pw_multi_aff_union_add, "{ B[x] -> A[1] : x <= 0 }",5820	  "{ B[x] -> C[2] : x >= 0 }" },5821};5822 5823/* Perform some basic tests of binary operations on5824 * isl_union_pw_multi_aff objects that are expected to fail.5825 */5826static int test_bin_upma_fail(isl_ctx *ctx)5827{5828	int i, n;5829	isl_union_pw_multi_aff *upma1, *upma2;5830	int on_error;5831 5832	on_error = isl_options_get_on_error(ctx);5833	isl_options_set_on_error(ctx, ISL_ON_ERROR_CONTINUE);5834	n = ARRAY_SIZE(upma_bin_fail_tests);5835	for (i = 0; i < n; ++i) {5836		upma1 = isl_union_pw_multi_aff_read_from_str(ctx,5837						upma_bin_fail_tests[i].arg1);5838		upma2 = isl_union_pw_multi_aff_read_from_str(ctx,5839						upma_bin_fail_tests[i].arg2);5840		upma1 = upma_bin_fail_tests[i].fn(upma1, upma2);5841		isl_union_pw_multi_aff_free(upma1);5842		if (upma1)5843			break;5844	}5845	isl_options_set_on_error(ctx, on_error);5846	if (i < n)5847		isl_die(ctx, isl_error_unknown,5848			"operation not expected to succeed", return -1);5849 5850	return 0;5851}5852 5853/* Inputs for basic tests of binary operations on5854 * pairs of isl_union_pw_multi_aff and isl_union_set objects.5855 * "fn" is the function that is being tested.5856 * "arg1" and "arg2" are string descriptions of the inputs.5857 * "res" is a string description of the expected result.5858 */5859struct {5860	__isl_give isl_union_pw_multi_aff *(*fn)(5861		__isl_take isl_union_pw_multi_aff *upma,5862		__isl_take isl_union_set *uset);5863	const char *arg1;5864	const char *arg2;5865	const char *res;5866} upma_uset_tests[] = {5867	{ &isl_union_pw_multi_aff_intersect_domain_wrapped_range,5868	  "{ A[i] -> B[i] }", "{ B[0] }",5869	  "{ }" },5870	{ &isl_union_pw_multi_aff_intersect_domain_wrapped_domain,5871	  "{ [A[i] -> B[i]] -> C[i + 1] }", "{ A[1]; B[0] }",5872	  "{ [A[1] -> B[1]] -> C[2] }" },5873	{ &isl_union_pw_multi_aff_intersect_domain_wrapped_range,5874	  "{ [A[i] -> B[i]] -> C[i + 1] }", "{ A[1]; B[0] }",5875	  "{ [A[0] -> B[0]] -> C[1] }" },5876	{ &isl_union_pw_multi_aff_intersect_domain_wrapped_range,5877	  "{ [A[i] -> B[i]] -> C[i + 1] }", "[N] -> { B[N] }",5878	  "[N] -> { [A[N] -> B[N]] -> C[N + 1] }" },5879	{ &isl_union_pw_multi_aff_intersect_domain_wrapped_range,5880	  "[M] -> { [A[M] -> B[M]] -> C[M + 1] }", "[N] -> { B[N] }",5881	  "[N, M] -> { [A[N] -> B[N]] -> C[N + 1] : N = M }" },5882	{ &isl_union_pw_multi_aff_intersect_domain_wrapped_range,5883	  "{ [A[] -> B[]] -> C[]; N[A[] -> B[]] -> D[]; [B[] -> A[]] -> E[] }",5884	  "{ B[] }",5885	  "{ [A[] -> B[]] -> C[]; N[A[] -> B[]] -> D[] }" },5886};5887 5888/* Perform some basic tests of binary operations on5889 * pairs of isl_union_pw_multi_aff and isl_union_set objects.5890 */5891static isl_stat test_upma_uset(isl_ctx *ctx)5892{5893	int i;5894	isl_bool ok;5895	isl_union_pw_multi_aff *upma, *res;5896	isl_union_set *uset;5897 5898	for (i = 0; i < ARRAY_SIZE(upma_uset_tests); ++i) {5899		upma = isl_union_pw_multi_aff_read_from_str(ctx,5900						    upma_uset_tests[i].arg1);5901		uset = isl_union_set_read_from_str(ctx,5902						    upma_uset_tests[i].arg2);5903		res = isl_union_pw_multi_aff_read_from_str(ctx,5904						    upma_uset_tests[i].res);5905		upma = upma_uset_tests[i].fn(upma, uset);5906		ok = isl_union_pw_multi_aff_plain_is_equal(upma, res);5907		isl_union_pw_multi_aff_free(upma);5908		isl_union_pw_multi_aff_free(res);5909		if (ok < 0)5910			return isl_stat_error;5911		if (!ok)5912			isl_die(ctx, isl_error_unknown,5913				"unexpected result", return isl_stat_error);5914	}5915 5916	return isl_stat_ok;5917}5918 5919/* Inputs for basic tests of unary operations on isl_multi_pw_aff objects.5920 * "fn" is the function that is tested.5921 * "arg" is a string description of the input.5922 * "res" is a string description of the expected result.5923 */5924struct {5925	__isl_give isl_multi_pw_aff *(*fn)(__isl_take isl_multi_pw_aff *mpa);5926	const char *arg;5927	const char *res;5928} mpa_un_tests[] = {5929	{ &isl_multi_pw_aff_range_factor_domain,5930	  "{ A[x] -> [B[(1 : x >= 5)] -> C[(2 : x <= 10)]] }",5931	  "{ A[x] -> B[(1 : x >= 5)] }" },5932	{ &isl_multi_pw_aff_range_factor_range,5933	  "{ A[x] -> [B[(1 : x >= 5)] -> C[(2 : x <= 10)]] }",5934	  "{ A[y] -> C[(2 : y <= 10)] }" },5935	{ &isl_multi_pw_aff_range_factor_domain,5936	  "{ A[x] -> [B[(1 : x >= 5)] -> C[]] }",5937	  "{ A[x] -> B[(1 : x >= 5)] }" },5938	{ &isl_multi_pw_aff_range_factor_range,5939	  "{ A[x] -> [B[(1 : x >= 5)] -> C[]] }",5940	  "{ A[y] -> C[] }" },5941	{ &isl_multi_pw_aff_range_factor_domain,5942	  "{ A[x] -> [B[] -> C[(2 : x <= 10)]] }",5943	  "{ A[x] -> B[] }" },5944	{ &isl_multi_pw_aff_range_factor_range,5945	  "{ A[x] -> [B[] -> C[(2 : x <= 10)]] }",5946	  "{ A[y] -> C[(2 : y <= 10)] }" },5947	{ &isl_multi_pw_aff_range_factor_domain,5948	  "{ A[x] -> [B[] -> C[]] }",5949	  "{ A[x] -> B[] }" },5950	{ &isl_multi_pw_aff_range_factor_range,5951	  "{ A[x] -> [B[] -> C[]] }",5952	  "{ A[y] -> C[] }" },5953	{ &isl_multi_pw_aff_factor_range,5954	  "{ [B[] -> C[]] }",5955	  "{ C[] }" },5956	{ &isl_multi_pw_aff_range_factor_domain,5957	  "{ A[x] -> [B[] -> C[]] : x >= 0 }",5958	  "{ A[x] -> B[] : x >= 0 }" },5959	{ &isl_multi_pw_aff_range_factor_range,5960	  "{ A[x] -> [B[] -> C[]] : x >= 0 }",5961	  "{ A[y] -> C[] : y >= 0 }" },5962	{ &isl_multi_pw_aff_factor_range,5963	  "[N] -> { [B[] -> C[]] : N >= 0 }",5964	  "[N] -> { C[] : N >= 0 }" },5965};5966 5967/* Perform some basic tests of unary operations on isl_multi_pw_aff objects.5968 */5969static int test_un_mpa(isl_ctx *ctx)5970{5971	int i;5972	isl_bool ok;5973	isl_multi_pw_aff *mpa, *res;5974 5975	for (i = 0; i < ARRAY_SIZE(mpa_un_tests); ++i) {5976		mpa = isl_multi_pw_aff_read_from_str(ctx, mpa_un_tests[i].arg);5977		res = isl_multi_pw_aff_read_from_str(ctx, mpa_un_tests[i].res);5978		mpa = mpa_un_tests[i].fn(mpa);5979		ok = isl_multi_pw_aff_plain_is_equal(mpa, res);5980		isl_multi_pw_aff_free(mpa);5981		isl_multi_pw_aff_free(res);5982		if (ok < 0)5983			return -1;5984		if (!ok)5985			isl_die(ctx, isl_error_unknown,5986				"unexpected result", return -1);5987	}5988 5989	return 0;5990}5991 5992/* Inputs for basic tests of binary operations on isl_multi_pw_aff objects.5993 * "fn" is the function that is tested.5994 * "arg1" and "arg2" are string descriptions of the inputs.5995 * "res" is a string description of the expected result.5996 */5997struct {5998	__isl_give isl_multi_pw_aff *(*fn)(5999		__isl_take isl_multi_pw_aff *mpa1,6000		__isl_take isl_multi_pw_aff *mpa2);6001	const char *arg1;6002	const char *arg2;6003	const char *res;6004} mpa_bin_tests[] = {6005	{ &isl_multi_pw_aff_add, "{ A[] -> [1] }", "{ A[] -> [2] }",6006	  "{ A[] -> [3] }" },6007	{ &isl_multi_pw_aff_add, "{ A[x] -> [(1 : x >= 5)] }",6008	  "{ A[x] -> [(x : x <= 10)] }",6009	  "{ A[x] -> [(1 + x : 5 <= x <= 10)] }" },6010	{ &isl_multi_pw_aff_add, "{ A[x] -> [] : x >= 5 }",6011	  "{ A[x] -> [] : x <= 10 }",6012	  "{ A[x] -> [] : 5 <= x <= 10 }" },6013	{ &isl_multi_pw_aff_add, "{ A[x] -> [] : x >= 5 }",6014	  "[N] -> { A[x] -> [] : x <= N }",6015	  "[N] -> { A[x] -> [] : 5 <= x <= N }" },6016	{ &isl_multi_pw_aff_add,6017	  "[N] -> { A[x] -> [] : x <= N }",6018	  "{ A[x] -> [] : x >= 5 }",6019	  "[N] -> { A[x] -> [] : 5 <= x <= N }" },6020	{ &isl_multi_pw_aff_range_product, "{ A[x] -> B[(1 : x >= 5)] }",6021	  "{ A[y] -> C[(2 : y <= 10)] }",6022	  "{ A[x] -> [B[(1 : x >= 5)] -> C[(2 : x <= 10)]] }" },6023	{ &isl_multi_pw_aff_range_product, "{ A[x] -> B[1] : x >= 5 }",6024	  "{ A[y] -> C[2] : y <= 10 }",6025	  "{ A[x] -> [B[(1 : x >= 5)] -> C[(2 : x <= 10)]] }" },6026	{ &isl_multi_pw_aff_range_product, "{ A[x] -> B[1] : x >= 5 }",6027	  "[N] -> { A[y] -> C[2] : y <= N }",6028	  "[N] -> { A[x] -> [B[(1 : x >= 5)] -> C[(2 : x <= N)]] }" },6029	{ &isl_multi_pw_aff_range_product, "[N] -> { A[x] -> B[1] : x >= N }",6030	  "{ A[y] -> C[2] : y <= 10 }",6031	  "[N] -> { A[x] -> [B[(1 : x >= N)] -> C[(2 : x <= 10)]] }" },6032	{ &isl_multi_pw_aff_range_product, "{ A[] -> B[1] }", "{ A[] -> C[2] }",6033	  "{ A[] -> [B[1] -> C[2]] }" },6034	{ &isl_multi_pw_aff_range_product, "{ A[] -> B[] }", "{ A[] -> C[] }",6035	  "{ A[] -> [B[] -> C[]] }" },6036	{ &isl_multi_pw_aff_range_product, "{ A[x] -> B[(1 : x >= 5)] }",6037	  "{ A[y] -> C[] : y <= 10 }",6038	  "{ A[x] -> [B[(1 : x >= 5)] -> C[]] : x <= 10 }" },6039	{ &isl_multi_pw_aff_range_product, "{ A[y] -> C[] : y <= 10 }",6040	  "{ A[x] -> B[(1 : x >= 5)] }",6041	  "{ A[x] -> [C[] -> B[(1 : x >= 5)]] : x <= 10 }" },6042	{ &isl_multi_pw_aff_product, "{ A[x] -> B[(1 : x >= 5)] }",6043	  "{ A[y] -> C[(2 : y <= 10)] }",6044	  "{ [A[x] -> A[y]] -> [B[(1 : x >= 5)] -> C[(2 : y <= 10)]] }" },6045	{ &isl_multi_pw_aff_product, "{ A[x] -> B[(1 : x >= 5)] }",6046	  "{ A[y] -> C[] : y <= 10 }",6047	  "{ [A[x] -> A[y]] -> [B[(1 : x >= 5)] -> C[]] : y <= 10 }" },6048	{ &isl_multi_pw_aff_product, "{ A[y] -> C[] : y <= 10 }",6049	  "{ A[x] -> B[(1 : x >= 5)] }",6050	  "{ [A[y] -> A[x]] -> [C[] -> B[(1 : x >= 5)]] : y <= 10 }" },6051	{ &isl_multi_pw_aff_product, "{ A[x] -> B[(1 : x >= 5)] }",6052	  "[N] -> { A[y] -> C[] : y <= N }",6053	  "[N] -> { [A[x] -> A[y]] -> [B[(1 : x >= 5)] -> C[]] : y <= N }" },6054	{ &isl_multi_pw_aff_product, "[N] -> { A[y] -> C[] : y <= N }",6055	  "{ A[x] -> B[(1 : x >= 5)] }",6056	  "[N] -> { [A[y] -> A[x]] -> [C[] -> B[(1 : x >= 5)]] : y <= N }" },6057	{ &isl_multi_pw_aff_product, "{ A[x] -> B[] : x >= 5 }",6058	  "{ A[y] -> C[] : y <= 10 }",6059	  "{ [A[x] -> A[y]] -> [B[] -> C[]] : x >= 5 and y <= 10 }" },6060	{ &isl_multi_pw_aff_product, "{ A[] -> B[1] }", "{ A[] -> C[2] }",6061	  "{ [A[] -> A[]] -> [B[1] -> C[2]] }" },6062	{ &isl_multi_pw_aff_product, "{ A[] -> B[] }", "{ A[] -> C[] }",6063	  "{ [A[] -> A[]] -> [B[] -> C[]] }" },6064	{ &isl_multi_pw_aff_pullback_multi_pw_aff,6065	  "{ B[i,j] -> C[i + 2j] }", "{ A[a,b] -> B[b,a] }",6066	  "{ A[a,b] -> C[b + 2a] }" },6067	{ &isl_multi_pw_aff_pullback_multi_pw_aff,6068	  "{ B[i,j] -> C[i + 2j] }",6069	  "{ A[a,b] -> B[(b : b > a),(a : b > a)] }",6070	  "{ A[a,b] -> C[(b + 2a : b > a)] }" },6071	{ &isl_multi_pw_aff_pullback_multi_pw_aff,6072	  "{ B[i,j] -> C[(i + 2j : j > 4)] }",6073	  "{ A[a,b] -> B[(b : b > a),(a : b > a)] }",6074	  "{ A[a,b] -> C[(b + 2a : b > a > 4)] }" },6075	{ &isl_multi_pw_aff_pullback_multi_pw_aff,6076	  "{ B[i,j] -> C[] }",6077	  "{ A[a,b] -> B[(b : b > a),(a : b > a)] }",6078	  "{ A[a,b] -> C[] }" },6079	{ &isl_multi_pw_aff_pullback_multi_pw_aff,6080	  "{ B[i,j] -> C[] : i > j }",6081	  "{ A[a,b] -> B[b,a] }",6082	  "{ A[a,b] -> C[] : b > a }" },6083	{ &isl_multi_pw_aff_pullback_multi_pw_aff,6084	  "{ B[i,j] -> C[] : j > 5 }",6085	  "{ A[a,b] -> B[(b : b > a),(a : b > a)] }",6086	  "{ A[a,b] -> C[] : b > a > 5 }" },6087	{ &isl_multi_pw_aff_pullback_multi_pw_aff,6088	  "[N] -> { B[i,j] -> C[] : j > N }",6089	  "{ A[a,b] -> B[(b : b > a),(a : b > a)] }",6090	  "[N] -> { A[a,b] -> C[] : b > a > N }" },6091	{ &isl_multi_pw_aff_pullback_multi_pw_aff,6092	  "[M,N] -> { B[] -> C[] : N > 5 }",6093	  "[M,N] -> { A[] -> B[] : M > N }",6094	  "[M,N] -> { A[] -> C[] : M > N > 5 }" },6095};6096 6097/* Perform some basic tests of binary operations on isl_multi_pw_aff objects.6098 */6099static int test_bin_mpa(isl_ctx *ctx)6100{6101	int i;6102	isl_bool ok;6103	isl_multi_pw_aff *mpa1, *mpa2, *res;6104 6105	for (i = 0; i < ARRAY_SIZE(mpa_bin_tests); ++i) {6106		mpa1 = isl_multi_pw_aff_read_from_str(ctx,6107							mpa_bin_tests[i].arg1);6108		mpa2 = isl_multi_pw_aff_read_from_str(ctx,6109							mpa_bin_tests[i].arg2);6110		res = isl_multi_pw_aff_read_from_str(ctx,6111							mpa_bin_tests[i].res);6112		mpa1 = mpa_bin_tests[i].fn(mpa1, mpa2);6113		ok = isl_multi_pw_aff_plain_is_equal(mpa1, res);6114		isl_multi_pw_aff_free(mpa1);6115		isl_multi_pw_aff_free(res);6116		if (ok < 0)6117			return -1;6118		if (!ok)6119			isl_die(ctx, isl_error_unknown,6120				"unexpected result", return -1);6121	}6122 6123	return 0;6124}6125 6126/* Inputs for basic tests of unary operations on6127 * isl_multi_union_pw_aff objects.6128 * "fn" is the function that is tested.6129 * "arg" is a string description of the input.6130 * "res" is a string description of the expected result.6131 */6132struct {6133	__isl_give isl_multi_union_pw_aff *(*fn)(6134		__isl_take isl_multi_union_pw_aff *mupa);6135	const char *arg;6136	const char *res;6137} mupa_un_tests[] = {6138	{ &isl_multi_union_pw_aff_factor_range,6139	  "[B[{ A[] -> [1] }] -> C[{ A[] -> [2] }]]",6140	  "C[{ A[] -> [2] }]" },6141	{ &isl_multi_union_pw_aff_factor_range,6142	  "[B[] -> C[{ A[] -> [2] }]]",6143	  "C[{ A[] -> [2] }]" },6144	{ &isl_multi_union_pw_aff_factor_range,6145	  "[B[{ A[] -> [1] }] -> C[]]",6146	  "C[]" },6147	{ &isl_multi_union_pw_aff_factor_range,6148	  "[B[] -> C[]]",6149	  "C[]" },6150	{ &isl_multi_union_pw_aff_factor_range,6151	  "([B[] -> C[]] : { A[x] : x >= 0 })",6152	  "(C[] : { A[x] : x >= 0 })" },6153	{ &isl_multi_union_pw_aff_factor_range,6154	  "[N] -> ([B[] -> C[]] : { A[x] : x <= N })",6155	  "[N] -> (C[] : { A[x] : x <= N })" },6156	{ &isl_multi_union_pw_aff_factor_range,6157	  "[N] -> ([B[] -> C[]] : { : N >= 0 })",6158	  "[N] -> (C[] : { : N >= 0 })" },6159};6160 6161/* Perform some basic tests of unary operations on6162 * isl_multi_union_pw_aff objects.6163 */6164static int test_un_mupa(isl_ctx *ctx)6165{6166	int i;6167	isl_bool ok;6168	isl_multi_union_pw_aff *mupa, *res;6169 6170	for (i = 0; i < ARRAY_SIZE(mupa_un_tests); ++i) {6171		mupa = isl_multi_union_pw_aff_read_from_str(ctx,6172							mupa_un_tests[i].arg);6173		res = isl_multi_union_pw_aff_read_from_str(ctx,6174							mupa_un_tests[i].res);6175		mupa = mupa_un_tests[i].fn(mupa);6176		ok = isl_multi_union_pw_aff_plain_is_equal(mupa, res);6177		isl_multi_union_pw_aff_free(mupa);6178		isl_multi_union_pw_aff_free(res);6179		if (ok < 0)6180			return -1;6181		if (!ok)6182			isl_die(ctx, isl_error_unknown,6183				"unexpected result", return -1);6184	}6185 6186	return 0;6187}6188 6189/* Inputs for basic tests of binary operations on6190 * isl_multi_union_pw_aff objects.6191 * "fn" is the function that is tested.6192 * "arg1" and "arg2" are string descriptions of the inputs.6193 * "res" is a string description of the expected result.6194 */6195struct {6196	__isl_give isl_multi_union_pw_aff *(*fn)(6197		__isl_take isl_multi_union_pw_aff *mupa1,6198		__isl_take isl_multi_union_pw_aff *mupa2);6199	const char *arg1;6200	const char *arg2;6201	const char *res;6202} mupa_bin_tests[] = {6203	{ &isl_multi_union_pw_aff_add, "[{ A[] -> [1] }]", "[{ A[] -> [2] }]",6204	  "[{ A[] -> [3] }]" },6205	{ &isl_multi_union_pw_aff_sub, "[{ A[] -> [1] }]", "[{ A[] -> [2] }]",6206	  "[{ A[] -> [-1] }]" },6207	{ &isl_multi_union_pw_aff_add,6208	  "[{ A[] -> [1]; B[] -> [4] }]",6209	  "[{ A[] -> [2]; C[] -> [5] }]",6210	  "[{ A[] -> [3] }]" },6211	{ &isl_multi_union_pw_aff_union_add,6212	  "[{ A[] -> [1]; B[] -> [4] }]",6213	  "[{ A[] -> [2]; C[] -> [5] }]",6214	  "[{ A[] -> [3]; B[] -> [4]; C[] -> [5] }]" },6215	{ &isl_multi_union_pw_aff_add, "[{ A[x] -> [(1)] : x >= 5 }]",6216	  "[{ A[x] -> [(x)] : x <= 10 }]",6217	  "[{ A[x] -> [(1 + x)] : 5 <= x <= 10 }]" },6218	{ &isl_multi_union_pw_aff_add, "([] : { A[x] : x >= 5 })",6219	  "([] : { A[x] : x <= 10 })",6220	  "([] : { A[x] : 5 <= x <= 10 })" },6221	{ &isl_multi_union_pw_aff_add, "([] : { A[x] : x >= 5 })",6222	  "[N] -> ([] : { A[x] : x <= N })",6223	  "[N] -> ([] : { A[x] : 5 <= x <= N })" },6224	{ &isl_multi_union_pw_aff_add, "[N] -> ([] : { A[x] : x >= N })",6225	  "([] : { A[x] : x <= 10 })",6226	  "[N] -> ([] : { A[x] : N <= x <= 10 })" },6227	{ &isl_multi_union_pw_aff_union_add, "[{ A[x] -> [(1)] : x >= 5 }]",6228	  "[{ A[x] -> [(x)] : x <= 10 }]",6229	  "[{ A[x] -> [(1 + x)] : 5 <= x <= 10; "6230	     "A[x] -> [(1)] : x > 10; A[x] -> [(x)] : x < 5 }]" },6231	{ &isl_multi_union_pw_aff_union_add, "([] : { A[x] : x >= 5 })",6232	  "([] : { A[x] : x <= 10 })",6233	  "([] : { A[x] })" },6234	{ &isl_multi_union_pw_aff_union_add, "([] : { A[x] : x >= 0 })",6235	  "[N] -> ([] : { A[x] : x >= N })",6236	  "[N] -> ([] : { A[x] : x >= 0 or x >= N })" },6237	{ &isl_multi_union_pw_aff_union_add,6238	  "[N] -> ([] : { A[] : N >= 0})",6239	  "[N] -> ([] : { A[] : N <= 0})",6240	  "[N] -> ([] : { A[] })" },6241	{ &isl_multi_union_pw_aff_union_add,6242	  "[N] -> ([] : { A[] })",6243	  "[N] -> ([] : { : })",6244	  "[N] -> ([] : { : })" },6245	{ &isl_multi_union_pw_aff_union_add,6246	  "[N] -> ([] : { : })",6247	  "[N] -> ([] : { A[] })",6248	  "[N] -> ([] : { : })" },6249	{ &isl_multi_union_pw_aff_union_add,6250	  "[N] -> ([] : { : N >= 0})",6251	  "[N] -> ([] : { : N <= 0})",6252	  "[N] -> ([] : { : })" },6253	{ &isl_multi_union_pw_aff_range_product,6254	  "B[{ A[] -> [1] }]",6255	  "C[{ A[] -> [2] }]",6256	  "[B[{ A[] -> [1] }] -> C[{ A[] -> [2] }]]" },6257	{ &isl_multi_union_pw_aff_range_product,6258	  "(B[] : { A[x] : x >= 5 })",6259	  "(C[] : { A[x] : x <= 10 })",6260	  "([B[] -> C[]] : { A[x] : 5 <= x <= 10 })" },6261	{ &isl_multi_union_pw_aff_range_product,6262	  "B[{ A[x] -> [x + 1] : x >= 5 }]",6263	  "(C[] : { A[x] : x <= 10 })",6264	  "[B[{ A[x] -> [x + 1] : 5 <= x <= 10 }] -> C[]]" },6265	{ &isl_multi_union_pw_aff_range_product,6266	  "(C[] : { A[x] : x <= 10 })",6267	  "B[{ A[x] -> [x + 1] : x >= 5 }]",6268	  "[C[] -> B[{ A[x] -> [x + 1] : 5 <= x <= 10 }]]" },6269	{ &isl_multi_union_pw_aff_range_product,6270	  "B[{ A[x] -> [x + 1] : x >= 5 }]",6271	  "[N] -> (C[] : { A[x] : x <= N })",6272	  "[N] -> [B[{ A[x] -> [x + 1] : 5 <= x <= N }] -> C[]]" },6273	{ &isl_multi_union_pw_aff_range_product,6274	  "[N] -> (C[] : { A[x] : x <= N })",6275	  "B[{ A[x] -> [x + 1] : x >= 5 }]",6276	  "[N] -> [C[] -> B[{ A[x] -> [x + 1] : 5 <= x <= N }]]" },6277	{ &isl_multi_union_pw_aff_range_product,6278	  "B[{ A[] -> [1]; D[] -> [3] }]",6279	  "C[{ A[] -> [2] }]",6280	  "[B[{ A[] -> [1]; D[] -> [3] }] -> C[{ A[] -> [2] }]]" },6281	{ &isl_multi_union_pw_aff_range_product,6282	  "B[] }]",6283	  "(C[] : { A[x] })",6284	  "([B[] -> C[]] : { A[x] })" },6285	{ &isl_multi_union_pw_aff_range_product,6286	  "(B[] : { A[x] })",6287	  "C[] }]",6288	  "([B[] -> C[]] : { A[x] })" },6289};6290 6291/* Perform some basic tests of binary operations on6292 * isl_multi_union_pw_aff objects.6293 */6294static int test_bin_mupa(isl_ctx *ctx)6295{6296	int i;6297	isl_bool ok;6298	isl_multi_union_pw_aff *mupa1, *mupa2, *res;6299 6300	for (i = 0; i < ARRAY_SIZE(mupa_bin_tests); ++i) {6301		mupa1 = isl_multi_union_pw_aff_read_from_str(ctx,6302							mupa_bin_tests[i].arg1);6303		mupa2 = isl_multi_union_pw_aff_read_from_str(ctx,6304							mupa_bin_tests[i].arg2);6305		res = isl_multi_union_pw_aff_read_from_str(ctx,6306							mupa_bin_tests[i].res);6307		mupa1 = mupa_bin_tests[i].fn(mupa1, mupa2);6308		ok = isl_multi_union_pw_aff_plain_is_equal(mupa1, res);6309		isl_multi_union_pw_aff_free(mupa1);6310		isl_multi_union_pw_aff_free(res);6311		if (ok < 0)6312			return -1;6313		if (!ok)6314			isl_die(ctx, isl_error_unknown,6315				"unexpected result", return -1);6316	}6317 6318	return 0;6319}6320 6321/* Inputs for basic tests of binary operations on6322 * pairs of isl_multi_union_pw_aff and isl_set objects.6323 * "fn" is the function that is tested.6324 * "arg1" and "arg2" are string descriptions of the inputs.6325 * "res" is a string description of the expected result.6326 */6327struct {6328	__isl_give isl_multi_union_pw_aff *(*fn)(6329		__isl_take isl_multi_union_pw_aff *mupa,6330		__isl_take isl_set *set);6331	const char *arg1;6332	const char *arg2;6333	const char *res;6334} mupa_set_tests[] = {6335	{ &isl_multi_union_pw_aff_intersect_range,6336	  "C[{ B[i,j] -> [i + 2j] }]", "{ C[1] }",6337	  "C[{ B[i,j] -> [i + 2j] : i + 2j = 1 }]" },6338	{ &isl_multi_union_pw_aff_intersect_range,6339	  "C[{ B[i,j] -> [i + 2j] }]", "[N] -> { C[N] }",6340	  "[N] -> C[{ B[i,j] -> [i + 2j] : i + 2j = N }]" },6341	{ &isl_multi_union_pw_aff_intersect_range,6342	  "[N] -> C[{ B[i,j] -> [i + 2j + N] }]", "{ C[1] }",6343	  "[N] -> C[{ B[i,j] -> [i + 2j + N] : i + 2j + N = 1 }]" },6344	{ &isl_multi_union_pw_aff_intersect_range,6345	  "C[{ B[i,j] -> [i + 2j] }]", "[N] -> { C[x] : N >= 0 }",6346	  "[N] -> C[{ B[i,j] -> [i + 2j] : N >= 0 }]" },6347	{ &isl_multi_union_pw_aff_intersect_range,6348	  "C[]", "{ C[] }", "C[]" },6349	{ &isl_multi_union_pw_aff_intersect_range,6350	  "[N] -> (C[] : { : N >= 0 })",6351	  "{ C[] }",6352	  "[N] -> (C[] : { : N >= 0 })" },6353	{ &isl_multi_union_pw_aff_intersect_range,6354	  "(C[] : { A[a,b] })",6355	  "{ C[] }",6356	  "(C[] : { A[a,b] })" },6357	{ &isl_multi_union_pw_aff_intersect_range,6358	  "[N] -> (C[] : { A[a,b] : a,b <= N })",6359	  "{ C[] }",6360	  "[N] -> (C[] : { A[a,b] : a,b <= N })" },6361	{ &isl_multi_union_pw_aff_intersect_range,6362	  "C[]",6363	  "[N] -> { C[] : N >= 0 }",6364	  "[N] -> (C[] : { : N >= 0 })" },6365	{ &isl_multi_union_pw_aff_intersect_range,6366	  "(C[] : { A[a,b] })",6367	  "[N] -> { C[] : N >= 0 }",6368	  "[N] -> (C[] : { A[a,b] : N >= 0 })" },6369	{ &isl_multi_union_pw_aff_intersect_range,6370	  "[N] -> (C[] : { : N >= 0 })",6371	  "[N] -> { C[] : N < 1024 }",6372	  "[N] -> (C[] : { : 0 <= N < 1024 })" },6373	{ &isl_multi_union_pw_aff_intersect_params,6374	  "C[{ B[i,j] -> [i + 2j] }]", "[N] -> { : N >= 0 }",6375	  "[N] -> C[{ B[i,j] -> [i + 2j] : N >= 0}]" },6376	{ &isl_multi_union_pw_aff_intersect_params,6377	  "[N] -> C[{ B[i,j] -> [i + 2j] : N <= 256 }]", "[N] -> { : N >= 0 }",6378	  "[N] -> C[{ B[i,j] -> [i + 2j] : 0 <= N <= 256 }]" },6379	{ &isl_multi_union_pw_aff_intersect_params,6380	  "[N] -> C[{ B[i,j] -> [i + 2j] : N <= 256 }]", "{ : }",6381	  "[N] -> C[{ B[i,j] -> [i + 2j] : N <= 256 }]" },6382	{ &isl_multi_union_pw_aff_intersect_params,6383	  "C[]", "[N] -> { : N >= 0 }",6384	  "[N] -> (C[] : { : N >= 0 })" },6385	{ &isl_multi_union_pw_aff_intersect_params,6386	  "(C[] : { A[a,b] })", "[N] -> { : N >= 0 }",6387	  "[N] -> (C[] : { A[a,b] : N >= 0 })" },6388	{ &isl_multi_union_pw_aff_intersect_params,6389	  "[N] -> (C[] : { A[a,N] })", "{ : }",6390	  "[N] -> (C[] : { A[a,N] })" },6391	{ &isl_multi_union_pw_aff_intersect_params,6392	  "[N] -> (C[] : { A[a,b] : N <= 256 })", "[N] -> { : N >= 0 }",6393	  "[N] -> (C[] : { A[a,b] : 0 <= N <= 256 })" },6394};6395 6396/* Perform some basic tests of binary operations on6397 * pairs of isl_multi_union_pw_aff and isl_set objects.6398 */6399static int test_mupa_set(isl_ctx *ctx)6400{6401	int i;6402	isl_bool ok;6403	isl_multi_union_pw_aff *mupa, *res;6404	isl_set *set;6405 6406	for (i = 0; i < ARRAY_SIZE(mupa_set_tests); ++i) {6407		mupa = isl_multi_union_pw_aff_read_from_str(ctx,6408						    mupa_set_tests[i].arg1);6409		set = isl_set_read_from_str(ctx, mupa_set_tests[i].arg2);6410		res = isl_multi_union_pw_aff_read_from_str(ctx,6411						    mupa_set_tests[i].res);6412		mupa = mupa_set_tests[i].fn(mupa, set);6413		ok = isl_multi_union_pw_aff_plain_is_equal(mupa, res);6414		isl_multi_union_pw_aff_free(mupa);6415		isl_multi_union_pw_aff_free(res);6416		if (ok < 0)6417			return -1;6418		if (!ok)6419			isl_die(ctx, isl_error_unknown,6420				"unexpected result", return -1);6421	}6422 6423	return 0;6424}6425 6426/* Inputs for basic tests of binary operations on6427 * pairs of isl_multi_union_pw_aff and isl_union_set objects.6428 * "fn" is the function that is tested.6429 * "arg1" and "arg2" are string descriptions of the inputs.6430 * "res" is a string description of the expected result.6431 */6432struct {6433	__isl_give isl_multi_union_pw_aff *(*fn)(6434		__isl_take isl_multi_union_pw_aff *mupa,6435		__isl_take isl_union_set *uset);6436	const char *arg1;6437	const char *arg2;6438	const char *res;6439} mupa_uset_tests[] = {6440	{ &isl_multi_union_pw_aff_intersect_domain,6441	  "C[{ B[i,j] -> [i + 2j] }]", "{ B[i,i] }",6442	  "C[{ B[i,i] -> [3i] }]" },6443	{ &isl_multi_union_pw_aff_intersect_domain,6444	  "(C[] : { B[i,j] })", "{ B[i,i] }",6445	  "(C[] : { B[i,i] })" },6446	{ &isl_multi_union_pw_aff_intersect_domain,6447	  "(C[] : { B[i,j] })", "[N] -> { B[N,N] }",6448	  "[N] -> (C[] : { B[N,N] })" },6449	{ &isl_multi_union_pw_aff_intersect_domain,6450	  "C[]", "{ B[i,i] }",6451	  "(C[] : { B[i,i] })" },6452	{ &isl_multi_union_pw_aff_intersect_domain,6453	  "[N] -> (C[] : { : N >= 0 })", "{ B[i,i] }",6454	  "[N] -> (C[] : { B[i,i] : N >= 0 })" },6455};6456 6457/* Perform some basic tests of binary operations on6458 * pairs of isl_multi_union_pw_aff and isl_union_set objects.6459 */6460static int test_mupa_uset(isl_ctx *ctx)6461{6462	int i;6463	isl_bool ok;6464	isl_multi_union_pw_aff *mupa, *res;6465	isl_union_set *uset;6466 6467	for (i = 0; i < ARRAY_SIZE(mupa_uset_tests); ++i) {6468		mupa = isl_multi_union_pw_aff_read_from_str(ctx,6469						    mupa_uset_tests[i].arg1);6470		uset = isl_union_set_read_from_str(ctx,6471						    mupa_uset_tests[i].arg2);6472		res = isl_multi_union_pw_aff_read_from_str(ctx,6473						    mupa_uset_tests[i].res);6474		mupa = mupa_uset_tests[i].fn(mupa, uset);6475		ok = isl_multi_union_pw_aff_plain_is_equal(mupa, res);6476		isl_multi_union_pw_aff_free(mupa);6477		isl_multi_union_pw_aff_free(res);6478		if (ok < 0)6479			return -1;6480		if (!ok)6481			isl_die(ctx, isl_error_unknown,6482				"unexpected result", return -1);6483	}6484 6485	return 0;6486}6487 6488/* Inputs for basic tests of binary operations on6489 * pairs of isl_multi_union_pw_aff and isl_multi_aff objects.6490 * "fn" is the function that is tested.6491 * "arg1" and "arg2" are string descriptions of the inputs.6492 * "res" is a string description of the expected result.6493 */6494struct {6495	__isl_give isl_multi_union_pw_aff *(*fn)(6496		__isl_take isl_multi_union_pw_aff *mupa,6497		__isl_take isl_multi_aff *ma);6498	const char *arg1;6499	const char *arg2;6500	const char *res;6501} mupa_ma_tests[] = {6502	{ &isl_multi_union_pw_aff_apply_multi_aff,6503	  "C[{ A[i,j] -> [i]; B[i,j] -> [j] }, "6504	    "{ A[i,j] -> [j]; B[i,j] -> [i] }]",6505	  "{ C[a,b] -> D[b,a] }",6506	  "D[{ A[i,j] -> [j]; B[i,j] -> [i] }, "6507	    "{ A[i,j] -> [i]; B[i,j] -> [j] }]" },6508	{ &isl_multi_union_pw_aff_apply_multi_aff,6509	  "C[{ A[i,j] -> [i] : i >= 0; B[i,j] -> [j] }, "6510	    "{ A[i,j] -> [j]; B[i,j] -> [i] }]",6511	  "{ C[a,b] -> D[b,a] }",6512	  "D[{ A[i,j] -> [j] : i >= 0; B[i,j] -> [i] }, "6513	    "{ A[i,j] -> [i] : i >= 0; B[i,j] -> [j] }]" },6514	{ &isl_multi_union_pw_aff_apply_multi_aff,6515	  "C[{ A[i,j] -> [i]; B[i,j] -> [j] }]",6516	  "[N] -> { C[a] -> D[a + N] }",6517	  "[N] -> D[{ A[i,j] -> [i + N]; B[i,j] -> [j + N] }] " },6518	{ &isl_multi_union_pw_aff_apply_multi_aff,6519	  "C[]",6520	  "{ C[] -> D[] }",6521	  "D[]" },6522	{ &isl_multi_union_pw_aff_apply_multi_aff,6523	  "[N] -> (C[] : { : N >= 0 })",6524	  "{ C[] -> D[] }",6525	  "[N] -> (D[] : { : N >= 0 })" },6526	{ &isl_multi_union_pw_aff_apply_multi_aff,6527	  "C[]",6528	  "[N] -> { C[] -> D[N] }",6529	  "[N] -> D[{ [N] }]" },6530	{ &isl_multi_union_pw_aff_apply_multi_aff,6531	  "(C[] : { A[i,j] : i >= j })",6532	  "{ C[] -> D[] }",6533	  "(D[] : { A[i,j] : i >= j })" },6534	{ &isl_multi_union_pw_aff_apply_multi_aff,6535	  "[N] -> (C[] : { A[i,j] : N >= 0 })",6536	  "{ C[] -> D[] }",6537	  "[N] -> (D[] : { A[i,j] : N >= 0 })" },6538	{ &isl_multi_union_pw_aff_apply_multi_aff,6539	  "(C[] : { A[i,j] : i >= j })",6540	  "[N] -> { C[] -> D[N] }",6541	  "[N] -> (D[{ A[i,j] -> [N] : i >= j }])" },6542};6543 6544/* Perform some basic tests of binary operations on6545 * pairs of isl_multi_union_pw_aff and isl_multi_aff objects.6546 */6547static int test_mupa_ma(isl_ctx *ctx)6548{6549	int i;6550	isl_bool ok;6551	isl_multi_union_pw_aff *mupa, *res;6552	isl_multi_aff *ma;6553 6554	for (i = 0; i < ARRAY_SIZE(mupa_ma_tests); ++i) {6555		mupa = isl_multi_union_pw_aff_read_from_str(ctx,6556						    mupa_ma_tests[i].arg1);6557		ma = isl_multi_aff_read_from_str(ctx, mupa_ma_tests[i].arg2);6558		res = isl_multi_union_pw_aff_read_from_str(ctx,6559						    mupa_ma_tests[i].res);6560		mupa = mupa_ma_tests[i].fn(mupa, ma);6561		ok = isl_multi_union_pw_aff_plain_is_equal(mupa, res);6562		isl_multi_union_pw_aff_free(mupa);6563		isl_multi_union_pw_aff_free(res);6564		if (ok < 0)6565			return -1;6566		if (!ok)6567			isl_die(ctx, isl_error_unknown,6568				"unexpected result", return -1);6569	}6570 6571	return 0;6572}6573 6574/* Inputs for basic tests of binary operations on6575 * pairs of isl_multi_union_pw_aff and isl_pw_aff objects.6576 * "fn" is the function that is tested.6577 * "arg1" and "arg2" are string descriptions of the inputs.6578 * "res" is a string description of the expected result.6579 */6580struct {6581	__isl_give isl_union_pw_aff *(*fn)(6582		__isl_take isl_multi_union_pw_aff *mupa,6583		__isl_take isl_pw_aff *pa);6584	const char *arg1;6585	const char *arg2;6586	const char *res;6587} mupa_pa_tests[] = {6588	{ &isl_multi_union_pw_aff_apply_pw_aff,6589	  "C[{ A[i,j] -> [i]; B[i,j] -> [j] }]",6590	  "[N] -> { C[a] -> [a + N] }",6591	  "[N] -> { A[i,j] -> [i + N]; B[i,j] -> [j + N] }" },6592	{ &isl_multi_union_pw_aff_apply_pw_aff,6593	  "C[{ A[i,j] -> [i]; B[i,j] -> [j] }]",6594	  "{ C[a] -> [a] : a >= 0; C[a] -> [-a] : a < 0 }",6595	  "{ A[i,j] -> [i] : i >= 0; A[i,j] -> [-i] : i < 0; "6596	    "B[i,j] -> [j] : j >= 0; B[i,j] -> [-j] : j < 0 }" },6597	{ &isl_multi_union_pw_aff_apply_pw_aff,6598	  "C[]",6599	  "[N] -> { C[] -> [N] }",6600	  "[N] -> { [N] }" },6601	{ &isl_multi_union_pw_aff_apply_pw_aff,6602	  "C[]",6603	  "[N] -> { C[] -> [N] : N >= 0; C[] -> [-N] : N < 0 }",6604	  "[N] -> { [N] : N >= 0; [-N] : N < 0 }" },6605	{ &isl_multi_union_pw_aff_apply_pw_aff,6606	  "[N] -> (C[] : { : N >= 0 })",6607	  "[N] -> { C[] -> [N] }",6608	  "[N] -> { [N] : N >= 0 }" },6609	{ &isl_multi_union_pw_aff_apply_pw_aff,6610	  "[N] -> (C[] : { : N >= 0 })",6611	  "[N] -> { C[] -> [N] : N >= 0; C[] -> [-N] : N < 0 }",6612	  "[N] -> { [N] : N >= 0 }" },6613	{ &isl_multi_union_pw_aff_apply_pw_aff,6614	  "[N] -> (C[] : { : N >= 0 })",6615	  "{ C[] -> [0] }",6616	  "[N] -> { [0] : N >= 0 }" },6617	{ &isl_multi_union_pw_aff_apply_pw_aff,6618	  "(C[] : { A[i,j] : i >= j })",6619	  "[N] -> { C[] -> [N] }",6620	  "[N] -> { A[i,j] -> [N] : i >= j }" },6621	{ &isl_multi_union_pw_aff_apply_pw_aff,6622	  "(C[] : { A[i,j] : i >= j })",6623	  "[N] -> { C[] -> [N] : N >= 0 }",6624	  "[N] -> { A[i,j] -> [N] : i >= j and N >= 0 }" },6625};6626 6627/* Perform some basic tests of binary operations on6628 * pairs of isl_multi_union_pw_aff and isl_pw_aff objects.6629 */6630static int test_mupa_pa(isl_ctx *ctx)6631{6632	int i;6633	isl_bool ok;6634	isl_multi_union_pw_aff *mupa;6635	isl_union_pw_aff *upa, *res;6636	isl_pw_aff *pa;6637 6638	for (i = 0; i < ARRAY_SIZE(mupa_pa_tests); ++i) {6639		mupa = isl_multi_union_pw_aff_read_from_str(ctx,6640						    mupa_pa_tests[i].arg1);6641		pa = isl_pw_aff_read_from_str(ctx, mupa_pa_tests[i].arg2);6642		res = isl_union_pw_aff_read_from_str(ctx,6643						    mupa_pa_tests[i].res);6644		upa = mupa_pa_tests[i].fn(mupa, pa);6645		ok = isl_union_pw_aff_plain_is_equal(upa, res);6646		isl_union_pw_aff_free(upa);6647		isl_union_pw_aff_free(res);6648		if (ok < 0)6649			return -1;6650		if (!ok)6651			isl_die(ctx, isl_error_unknown,6652				"unexpected result", return -1);6653	}6654 6655	return 0;6656}6657 6658/* Inputs for basic tests of binary operations on6659 * pairs of isl_multi_union_pw_aff and isl_pw_multi_aff objects.6660 * "fn" is the function that is tested.6661 * "arg1" and "arg2" are string descriptions of the inputs.6662 * "res" is a string description of the expected result.6663 */6664struct {6665	__isl_give isl_multi_union_pw_aff *(*fn)(6666		__isl_take isl_multi_union_pw_aff *mupa,6667		__isl_take isl_pw_multi_aff *pma);6668	const char *arg1;6669	const char *arg2;6670	const char *res;6671} mupa_pma_tests[] = {6672	{ &isl_multi_union_pw_aff_apply_pw_multi_aff,6673	  "C[{ A[i,j] -> [i]; B[i,j] -> [j] }, "6674	    "{ A[i,j] -> [j]; B[i,j] -> [i] }]",6675	  "{ C[a,b] -> D[b,a] }",6676	  "D[{ A[i,j] -> [j]; B[i,j] -> [i] }, "6677	    "{ A[i,j] -> [i]; B[i,j] -> [j] }]" },6678	{ &isl_multi_union_pw_aff_apply_pw_multi_aff,6679	  "C[{ A[i,j] -> [i] : i >= 0; B[i,j] -> [j] }, "6680	    "{ A[i,j] -> [j]; B[i,j] -> [i] }]",6681	  "{ C[a,b] -> D[b,a] }",6682	  "D[{ A[i,j] -> [j] : i >= 0; B[i,j] -> [i] }, "6683	    "{ A[i,j] -> [i] : i >= 0; B[i,j] -> [j] }]" },6684	{ &isl_multi_union_pw_aff_apply_pw_multi_aff,6685	  "C[{ A[i,j] -> [i]; B[i,j] -> [j] }]",6686	  "[N] -> { C[a] -> D[a + N] }",6687	  "[N] -> D[{ A[i,j] -> [i + N]; B[i,j] -> [j + N] }]" },6688	{ &isl_multi_union_pw_aff_apply_pw_multi_aff,6689	  "C[{ A[i,j] -> [i]; B[i,j] -> [j] }]",6690	  "{ C[a] -> D[a] : a >= 0; C[a] -> D[-a] : a < 0 }",6691	  "D[{ A[i,j] -> [i] : i >= 0; A[i,j] -> [-i] : i < 0; "6692	      "B[i,j] -> [j] : j >= 0; B[i,j] -> [-j] : j < 0 }]" },6693	{ &isl_multi_union_pw_aff_apply_pw_multi_aff,6694	  "C[{ A[i,j] -> [i]; B[i,j] -> [j] }, "6695	    "{ A[i,j] -> [j]; B[i,j] -> [i] }]",6696	  "{ C[a,b] -> D[a,b] : a >= b; C[a,b] -> D[b,a] : a < b }",6697	  "D[{ A[i,j] -> [i] : i >= j; A[i,j] -> [j] : i < j; "6698	      "B[i,j] -> [j] : i <= j; B[i,j] -> [i] : i > j }, "6699	    "{ A[i,j] -> [j] : i >= j; A[i,j] -> [i] : i < j; "6700	      "B[i,j] -> [i] : i <= j; B[i,j] -> [j] : i > j }]" },6701	{ &isl_multi_union_pw_aff_apply_pw_multi_aff,6702	  "C[]",6703	  "{ C[] -> D[] }",6704	  "D[]" },6705	{ &isl_multi_union_pw_aff_apply_pw_multi_aff,6706	  "[N] -> (C[] : { : N >= 0 })",6707	  "{ C[] -> D[] }",6708	  "[N] -> (D[] : { : N >= 0 })" },6709	{ &isl_multi_union_pw_aff_apply_pw_multi_aff,6710	  "C[]",6711	  "[N] -> { C[] -> D[N] }",6712	  "[N] -> D[{ [N] }]" },6713	{ &isl_multi_union_pw_aff_apply_pw_multi_aff,6714	  "(C[] : { A[i,j] : i >= j })",6715	  "{ C[] -> D[] }",6716	  "(D[] : { A[i,j] : i >= j })" },6717	{ &isl_multi_union_pw_aff_apply_pw_multi_aff,6718	  "[N] -> (C[] : { A[i,j] : N >= 0 })",6719	  "{ C[] -> D[] }",6720	  "[N] -> (D[] : { A[i,j] : N >= 0 })" },6721	{ &isl_multi_union_pw_aff_apply_pw_multi_aff,6722	  "(C[] : { A[i,j] : i >= j })",6723	  "[N] -> { C[] -> D[N] }",6724	  "[N] -> (D[{ A[i,j] -> [N] : i >= j }])" },6725	{ &isl_multi_union_pw_aff_apply_pw_multi_aff,6726	  "C[]",6727	  "[N] -> { C[] -> D[N] : N >= 0; C[] -> D[-N] : N < 0 }",6728	  "[N] -> D[{ [N] : N >= 0; [-N] : N < 0 }]" },6729	{ &isl_multi_union_pw_aff_apply_pw_multi_aff,6730	  "[N] -> (C[] : { : N >= 0 })",6731	  "[N] -> { C[] -> D[N] }",6732	  "[N] -> D[{ [N] : N >= 0 }]" },6733	{ &isl_multi_union_pw_aff_apply_pw_multi_aff,6734	  "[N] -> (C[] : { : N >= 0 })",6735	  "[N] -> { C[] -> D[N] : N >= 0; C[] -> D[-N] : N < 0 }",6736	  "[N] -> D[{ [N] : N >= 0 }]" },6737	{ &isl_multi_union_pw_aff_apply_pw_multi_aff,6738	  "[N] -> (C[] : { : N >= 0 })",6739	  "{ C[] -> D[0] }",6740	  "[N] -> D[{ [0] : N >= 0 }]" },6741	{ &isl_multi_union_pw_aff_apply_pw_multi_aff,6742	  "(C[] : { A[i,j] : i >= j })",6743	  "[N] -> { C[] -> D[N] : N >= 0 }",6744	  "[N] -> D[{ A[i,j] -> [N] : i >= j and N >= 0 }]" },6745};6746 6747/* Perform some basic tests of binary operations on6748 * pairs of isl_multi_union_pw_aff and isl_pw_multi_aff objects.6749 */6750static int test_mupa_pma(isl_ctx *ctx)6751{6752	int i;6753	isl_bool ok;6754	isl_multi_union_pw_aff *mupa, *res;6755	isl_pw_multi_aff *pma;6756 6757	for (i = 0; i < ARRAY_SIZE(mupa_pma_tests); ++i) {6758		mupa = isl_multi_union_pw_aff_read_from_str(ctx,6759						    mupa_pma_tests[i].arg1);6760		pma = isl_pw_multi_aff_read_from_str(ctx,6761						    mupa_pma_tests[i].arg2);6762		res = isl_multi_union_pw_aff_read_from_str(ctx,6763						    mupa_pma_tests[i].res);6764		mupa = mupa_pma_tests[i].fn(mupa, pma);6765		ok = isl_multi_union_pw_aff_plain_is_equal(mupa, res);6766		isl_multi_union_pw_aff_free(mupa);6767		isl_multi_union_pw_aff_free(res);6768		if (ok < 0)6769			return -1;6770		if (!ok)6771			isl_die(ctx, isl_error_unknown,6772				"unexpected result", return -1);6773	}6774 6775	return 0;6776}6777 6778/* Inputs for basic tests of binary operations on6779 * pairs of isl_multi_union_pw_aff and isl_union_pw_multi_aff objects.6780 * "fn" is the function that is tested.6781 * "arg1" and "arg2" are string descriptions of the inputs.6782 * "res" is a string description of the expected result.6783 */6784struct {6785	__isl_give isl_multi_union_pw_aff *(*fn)(6786		__isl_take isl_multi_union_pw_aff *mupa,6787		__isl_take isl_union_pw_multi_aff *upma);6788	const char *arg1;6789	const char *arg2;6790	const char *res;6791} mupa_upma_tests[] = {6792	{ &isl_multi_union_pw_aff_pullback_union_pw_multi_aff,6793	  "C[{ B[i,j] -> [i + 2j] }]", "{ A[a,b] -> B[b,a] }",6794	  "C[{ A[a,b] -> [b + 2a] }]" },6795	{ &isl_multi_union_pw_aff_pullback_union_pw_multi_aff,6796	  "C[{ B[i,j] -> [i + 2j] }]",6797	  "{ A[a,b] -> B[b,a] : b > a }",6798	  "C[{ A[a,b] -> [b + 2a] : b > a }]" },6799	{ &isl_multi_union_pw_aff_pullback_union_pw_multi_aff,6800	  "C[{ B[i,j] -> [i + 2j] : j > 4 }]",6801	  "{ A[a,b] -> B[b,a] : b > a }",6802	  "C[{ A[a,b] -> [b + 2a] : b > a > 4 }]" },6803	{ &isl_multi_union_pw_aff_pullback_union_pw_multi_aff,6804	  "C[{ B[i,j] -> [i + 2j] }]",6805	  "{ A[a,b] -> B[b,a] : a > b; A[a,b] -> B[a,b] : a <= b }",6806	  "C[{ A[a,b] -> [b + 2a] : a > b; A[a,b] -> [a + 2b] : a <= b }]" },6807	{ &isl_multi_union_pw_aff_pullback_union_pw_multi_aff,6808	  "(C[] : { B[a,b] })",6809	  "{ A[a,b] -> B[b,a] }",6810	  "(C[] : { A[a,b] })" },6811	{ &isl_multi_union_pw_aff_pullback_union_pw_multi_aff,6812	  "(C[] : { B[a,b] })",6813	  "{ B[a,b] -> A[b,a] }",6814	  "(C[] : { })" },6815	{ &isl_multi_union_pw_aff_pullback_union_pw_multi_aff,6816	  "(C[] : { B[a,b] })",6817	  "{ A[a,b] -> B[b,a] : a > b }",6818	  "(C[] : { A[a,b] : a > b })" },6819	{ &isl_multi_union_pw_aff_pullback_union_pw_multi_aff,6820	  "(C[] : { B[a,b] : a > b })",6821	  "{ A[a,b] -> B[b,a] }",6822	  "(C[] : { A[a,b] : b > a })" },6823	{ &isl_multi_union_pw_aff_pullback_union_pw_multi_aff,6824	  "[N] -> (C[] : { B[a,b] : a > N })",6825	  "{ A[a,b] -> B[b,a] : a > b }",6826	  "[N] -> (C[] : { A[a,b] : a > b > N })" },6827	{ &isl_multi_union_pw_aff_pullback_union_pw_multi_aff,6828	  "(C[] : { B[a,b] : a > b })",6829	  "[N] -> { A[a,b] -> B[b,a] : a > N }",6830	  "[N] -> (C[] : { A[a,b] : b > a > N })" },6831	{ &isl_multi_union_pw_aff_pullback_union_pw_multi_aff,6832	  "C[]",6833	  "{ A[a,b] -> B[b,a] }",6834	  "C[]" },6835	{ &isl_multi_union_pw_aff_pullback_union_pw_multi_aff,6836	  "[N] -> (C[] : { : N >= 0 })",6837	  "{ A[a,b] -> B[b,a] }",6838	  "[N] -> (C[] : { : N >= 0 })" },6839	{ &isl_multi_union_pw_aff_pullback_union_pw_multi_aff,6840	  "C[]",6841	  "[N] -> { A[a,b] -> B[b,a] : N >= 0 }",6842	  "[N] -> (C[] : { : N >= 0 })" },6843};6844 6845/* Perform some basic tests of binary operations on6846 * pairs of isl_multi_union_pw_aff and isl_union_pw_multi_aff objects.6847 */6848static int test_mupa_upma(isl_ctx *ctx)6849{6850	int i;6851	isl_bool ok;6852	isl_multi_union_pw_aff *mupa, *res;6853	isl_union_pw_multi_aff *upma;6854 6855	for (i = 0; i < ARRAY_SIZE(mupa_upma_tests); ++i) {6856		mupa = isl_multi_union_pw_aff_read_from_str(ctx,6857						    mupa_upma_tests[i].arg1);6858		upma = isl_union_pw_multi_aff_read_from_str(ctx,6859						    mupa_upma_tests[i].arg2);6860		res = isl_multi_union_pw_aff_read_from_str(ctx,6861						    mupa_upma_tests[i].res);6862		mupa = mupa_upma_tests[i].fn(mupa, upma);6863		ok = isl_multi_union_pw_aff_plain_is_equal(mupa, res);6864		isl_multi_union_pw_aff_free(mupa);6865		isl_multi_union_pw_aff_free(res);6866		if (ok < 0)6867			return -1;6868		if (!ok)6869			isl_die(ctx, isl_error_unknown,6870				"unexpected result", return -1);6871	}6872 6873	return 0;6874}6875 6876/* Check that the input tuple of an isl_aff can be set properly.6877 */6878static isl_stat test_aff_set_tuple_id(isl_ctx *ctx)6879{6880	isl_id *id;6881	isl_aff *aff;6882	isl_stat equal;6883 6884	aff = isl_aff_read_from_str(ctx, "{ [x] -> [x + 1] }");6885	id = isl_id_alloc(ctx, "A", NULL);6886	aff = isl_aff_set_tuple_id(aff, isl_dim_in, id);6887	equal = aff_check_plain_equal(aff, "{ A[x] -> [x + 1] }");6888	isl_aff_free(aff);6889	if (equal < 0)6890		return isl_stat_error;6891 6892	return isl_stat_ok;6893}6894 6895/* Check that affine expressions get normalized on addition/subtraction.6896 * In particular, check that (final) unused integer divisions get removed6897 * such that an expression derived from expressions with integer divisions6898 * is found to be obviously equal to one that is created directly.6899 */6900static isl_stat test_aff_normalize(isl_ctx *ctx)6901{6902	isl_aff *aff, *aff2;6903	isl_stat ok;6904 6905	aff = isl_aff_read_from_str(ctx, "{ [x] -> [x//2] }");6906	aff2 = isl_aff_read_from_str(ctx, "{ [x] -> [1 + x//2] }");6907	aff = isl_aff_sub(aff2, aff);6908	ok = aff_check_plain_equal(aff, "{ [x] -> [1] }");6909	isl_aff_free(aff);6910 6911	return ok;6912}6913 6914int test_aff(isl_ctx *ctx)6915{6916	const char *str;6917	isl_set *set;6918	isl_space *space;6919	isl_local_space *ls;6920	isl_aff *aff;6921	int zero;6922	isl_stat equal;6923 6924	if (test_upa(ctx) < 0)6925		return -1;6926	if (test_bin_aff(ctx) < 0)6927		return -1;6928	if (test_bin_pw_aff(ctx) < 0)6929		return -1;6930	if (test_upma_test(ctx) < 0)6931		return -1;6932	if (test_bin_upma(ctx) < 0)6933		return -1;6934	if (test_bin_upma_fail(ctx) < 0)6935		return -1;6936	if (test_upma_uset(ctx) < 0)6937		return -1;6938	if (test_un_mpa(ctx) < 0)6939		return -1;6940	if (test_bin_mpa(ctx) < 0)6941		return -1;6942	if (test_un_mupa(ctx) < 0)6943		return -1;6944	if (test_bin_mupa(ctx) < 0)6945		return -1;6946	if (test_mupa_set(ctx) < 0)6947		return -1;6948	if (test_mupa_uset(ctx) < 0)6949		return -1;6950	if (test_mupa_ma(ctx) < 0)6951		return -1;6952	if (test_mupa_pa(ctx) < 0)6953		return -1;6954	if (test_mupa_pma(ctx) < 0)6955		return -1;6956	if (test_mupa_upma(ctx) < 0)6957		return -1;6958 6959	space = isl_space_set_alloc(ctx, 0, 1);6960	ls = isl_local_space_from_space(space);6961	aff = isl_aff_zero_on_domain(ls);6962 6963	aff = isl_aff_add_coefficient_si(aff, isl_dim_in, 0, 1);6964	aff = isl_aff_scale_down_ui(aff, 3);6965	aff = isl_aff_floor(aff);6966	aff = isl_aff_add_coefficient_si(aff, isl_dim_in, 0, 1);6967	aff = isl_aff_scale_down_ui(aff, 2);6968	aff = isl_aff_floor(aff);6969	aff = isl_aff_add_coefficient_si(aff, isl_dim_in, 0, 1);6970 6971	str = "{ [10] }";6972	set = isl_set_read_from_str(ctx, str);6973	aff = isl_aff_gist(aff, set);6974 6975	aff = isl_aff_add_constant_si(aff, -16);6976	zero = isl_aff_plain_is_zero(aff);6977	isl_aff_free(aff);6978 6979	if (zero < 0)6980		return -1;6981	if (!zero)6982		isl_die(ctx, isl_error_unknown, "unexpected result", return -1);6983 6984	aff = isl_aff_read_from_str(ctx, "{ [-1] }");6985	aff = isl_aff_scale_down_ui(aff, 64);6986	aff = isl_aff_floor(aff);6987	equal = aff_check_plain_equal(aff, "{ [-1] }");6988	isl_aff_free(aff);6989	if (equal < 0)6990		return -1;6991 6992	if (test_aff_set_tuple_id(ctx) < 0)6993		return -1;6994	if (test_aff_normalize(ctx) < 0)6995		return -1;6996 6997	return 0;6998}6999 7000/* Inputs for isl_set_bind tests.7001 * "set" is the input set.7002 * "tuple" is the binding tuple.7003 * "res" is the expected result.7004 */7005static7006struct {7007	const char *set;7008	const char *tuple;7009	const char *res;7010} bind_set_tests[] = {7011	{ "{ A[M, N] : M mod 2 = 0 and N mod 8 = 3 }",7012	  "{ A[M, N] }",7013	  "[M, N] -> { : M mod 2 = 0 and N mod 8 = 3 }" },7014	{ "{ B[N, M] : M mod 2 = 0 and N mod 8 = 3 }",7015	  "{ B[N, M] }",7016	  "[M, N] -> { : M mod 2 = 0 and N mod 8 = 3 }" },7017	{ "[M] -> { C[N] : M mod 2 = 0 and N mod 8 = 3 }",7018	  "{ C[N] }",7019	  "[M, N] -> { : M mod 2 = 0 and N mod 8 = 3 }" },7020	{ "[M] -> { D[x, N] : x mod 2 = 0 and N mod 8 = 3 and M >= 0 }",7021	  "{ D[M, N] }",7022	  "[M, N] -> { : M mod 2 = 0 and N mod 8 = 3 and M >= 0 }" },7023};7024 7025/* Perform basic isl_set_bind tests.7026 */7027static isl_stat test_bind_set(isl_ctx *ctx)7028{7029	int i;7030 7031	for (i = 0; i < ARRAY_SIZE(bind_set_tests); ++i) {7032		const char *str;7033		isl_set *set;7034		isl_multi_id *tuple;7035		isl_stat r;7036 7037		set = isl_set_read_from_str(ctx, bind_set_tests[i].set);7038		str = bind_set_tests[i].tuple;7039		tuple = isl_multi_id_read_from_str(ctx, str);7040		set = isl_set_bind(set, tuple);7041		r = set_check_equal(set, bind_set_tests[i].res);7042		isl_set_free(set);7043		if (r < 0)7044			return isl_stat_error;7045	}7046 7047	return isl_stat_ok;7048}7049 7050/* Inputs for isl_map_bind_domain tests.7051 * "map" is the input map.7052 * "tuple" is the binding tuple.7053 * "res" is the expected result.7054 */7055struct {7056	const char *map;7057	const char *tuple;7058	const char *res;7059} bind_map_domain_tests[] = {7060	{ "{ A[M, N] -> [M + floor(N/2)] }",7061	  "{ A[M, N] }",7062	  "[M, N] -> { [M + floor(N/2)] }" },7063	{ "{ B[N, M] -> [M + floor(N/2)] }",7064	  "{ B[N, M] }",7065	  "[N, M] -> { [M + floor(N/2)] }" },7066	{ "[M] -> { C[N] -> [M + floor(N/2)] }",7067	  "{ C[N] }",7068	  "[M, N] -> { [M + floor(N/2)] }" },7069	{ "[M] -> { C[x, N] -> [x + floor(N/2)] }",7070	  "{ C[M, N] }",7071	  "[M, N] -> { [M + floor(N/2)] }" },7072	{ "[M] -> { C[x, N] -> [M + floor(N/2)] }",7073	  "{ C[M, N] }",7074	  "[M, N] -> { [M + floor(N/2)] }" },7075	{ "[A, M] -> { C[N, x] -> [x + floor(N/2)] }",7076	  "{ C[N, M] }",7077	  "[A, N, M] -> { [M + floor(N/2)] }" },7078};7079 7080/* Perform basic isl_map_bind_domain tests.7081 */7082static isl_stat test_bind_map_domain(isl_ctx *ctx)7083{7084	int i;7085 7086	for (i = 0; i < ARRAY_SIZE(bind_map_domain_tests); ++i) {7087		const char *str;7088		isl_map *map;7089		isl_set *set;7090		isl_multi_id *tuple;7091		isl_stat r;7092 7093		str = bind_map_domain_tests[i].map;7094		map = isl_map_read_from_str(ctx, str);7095		str = bind_map_domain_tests[i].tuple;7096		tuple = isl_multi_id_read_from_str(ctx, str);7097		set = isl_map_bind_domain(map, tuple);7098		str = bind_map_domain_tests[i].res;7099		r = set_check_equal(set, str);7100		isl_set_free(set);7101		if (r < 0)7102			return isl_stat_error;7103	}7104 7105	return isl_stat_ok;7106}7107 7108/* Inputs for isl_union_map_bind_range tests.7109 * "map" is the input union map.7110 * "tuple" is the binding tuple.7111 * "res" is the expected result.7112 */7113struct {7114	const char *map;7115	const char *tuple;7116	const char *res;7117} bind_umap_range_tests[] = {7118	{ "{ B[N, M] -> A[M, N] : M mod 2 = 0 and N mod 8 = 3 }",7119	  "{ A[M, N] }",7120	  "[M, N] -> { B[N, M] : M mod 2 = 0 and N mod 8 = 3 }" },7121	{ "{ B[N, M] -> A[M, N] : M mod 2 = 0 and N mod 8 = 3 }",7122	  "{ B[M, N] }",7123	  "{ }" },7124	{ "{ A[] -> B[]; C[] -> D[]; E[] -> B[] }",7125	  "{ B[] }",7126	  "{ A[]; E[] }" },7127};7128 7129/* Perform basic isl_union_map_bind_range tests.7130 */7131static isl_stat test_bind_umap_range(isl_ctx *ctx)7132{7133	int i;7134 7135	for (i = 0; i < ARRAY_SIZE(bind_umap_range_tests); ++i) {7136		const char *str;7137		isl_union_map *umap;7138		isl_union_set *uset;7139		isl_multi_id *tuple;7140		isl_stat r;7141 7142		str = bind_umap_range_tests[i].map;7143		umap = isl_union_map_read_from_str(ctx, str);7144		str = bind_umap_range_tests[i].tuple;7145		tuple = isl_multi_id_read_from_str(ctx, str);7146		uset = isl_union_map_bind_range(umap, tuple);7147		str = bind_umap_range_tests[i].res;7148		r = uset_check_equal(uset, str);7149		isl_union_set_free(uset);7150		if (r < 0)7151			return isl_stat_error;7152	}7153 7154	return isl_stat_ok;7155}7156 7157/* Inputs for isl_pw_multi_aff_bind_domain tests.7158 * "pma" is the input expression.7159 * "tuple" is the binding tuple.7160 * "res" is the expected result.7161 */7162struct {7163	const char *pma;7164	const char *tuple;7165	const char *res;7166} bind_pma_domain_tests[] = {7167	{ "{ A[M, N] -> [M + floor(N/2)] }",7168	  "{ A[M, N] }",7169	  "[M, N] -> { [M + floor(N/2)] }" },7170	{ "{ B[N, M] -> [M + floor(N/2)] }",7171	  "{ B[N, M] }",7172	  "[N, M] -> { [M + floor(N/2)] }" },7173	{ "[M] -> { C[N] -> [M + floor(N/2)] }",7174	  "{ C[N] }",7175	  "[M, N] -> { [M + floor(N/2)] }" },7176	{ "[M] -> { C[x, N] -> [x + floor(N/2)] }",7177	  "{ C[M, N] }",7178	  "[M, N] -> { [M + floor(N/2)] }" },7179	{ "[M] -> { C[x, N] -> [M + floor(N/2)] }",7180	  "{ C[M, N] }",7181	  "[M, N] -> { [M + floor(N/2)] }" },7182	{ "[A, M] -> { C[N, x] -> [x + floor(N/2)] }",7183	  "{ C[N, M] }",7184	  "[A, N, M] -> { [M + floor(N/2)] }" },7185};7186 7187/* Perform basic isl_pw_multi_aff_bind_domain tests.7188 */7189static isl_stat test_bind_pma_domain(isl_ctx *ctx)7190{7191	int i;7192 7193	for (i = 0; i < ARRAY_SIZE(bind_pma_domain_tests); ++i) {7194		const char *str;7195		isl_pw_multi_aff *pma;7196		isl_multi_id *tuple;7197		isl_stat r;7198 7199		str = bind_pma_domain_tests[i].pma;7200		pma = isl_pw_multi_aff_read_from_str(ctx, str);7201		str = bind_pma_domain_tests[i].tuple;7202		tuple = isl_multi_id_read_from_str(ctx, str);7203		pma = isl_pw_multi_aff_bind_domain(pma, tuple);7204		str = bind_pma_domain_tests[i].res;7205		r = pw_multi_aff_check_plain_equal(pma, str);7206		isl_pw_multi_aff_free(pma);7207		if (r < 0)7208			return isl_stat_error;7209	}7210 7211	return isl_stat_ok;7212}7213 7214/* Inputs for isl_pw_multi_aff_bind_domain_wrapped_domain tests.7215 * "pma" is the input expression.7216 * "tuple" is the binding tuple.7217 * "res" is the expected result.7218 */7219struct {7220	const char *pma;7221	const char *tuple;7222	const char *res;7223} bind_pma_domain_wrapped_tests[] = {7224	{ "{ [A[M, N] -> B[]] -> [M + floor(N/2)] }",7225	  "{ A[M, N] }",7226	  "[M, N] -> { B[] -> [M + floor(N/2)] }" },7227	{ "{ [B[N, M] -> D[]] -> [M + floor(N/2)] }",7228	  "{ B[N, M] }",7229	  "[N, M] -> { D[] -> [M + floor(N/2)] }" },7230	{ "[M] -> { [C[N] -> B[x]] -> [x + M + floor(N/2)] }",7231	  "{ C[N] }",7232	  "[M, N] -> { B[x] -> [x + M + floor(N/2)] }" },7233	{ "[M] -> { [C[x, N] -> B[]] -> [x + floor(N/2)] }",7234	  "{ C[M, N] }",7235	  "[M, N] -> { B[] -> [M + floor(N/2)] }" },7236	{ "[M] -> { [C[x, N] -> B[]] -> [M + floor(N/2)] }",7237	  "{ C[M, N] }",7238	  "[M, N] -> { B[] -> [M + floor(N/2)] }" },7239	{ "[A, M] -> { [C[N, x] -> B[]] -> [x + floor(N/2)] }",7240	  "{ C[N, M] }",7241	  "[A, N, M] -> { B[] -> [M + floor(N/2)] }" },7242};7243 7244/* Perform basic isl_pw_multi_aff_bind_domain_wrapped_domain tests.7245 */7246static isl_stat test_bind_pma_domain_wrapped(isl_ctx *ctx)7247{7248	int i;7249 7250	for (i = 0; i < ARRAY_SIZE(bind_pma_domain_wrapped_tests); ++i) {7251		const char *str;7252		isl_pw_multi_aff *pma;7253		isl_multi_id *tuple;7254		isl_stat r;7255 7256		str = bind_pma_domain_wrapped_tests[i].pma;7257		pma = isl_pw_multi_aff_read_from_str(ctx, str);7258		str = bind_pma_domain_wrapped_tests[i].tuple;7259		tuple = isl_multi_id_read_from_str(ctx, str);7260		pma = isl_pw_multi_aff_bind_domain_wrapped_domain(pma, tuple);7261		str = bind_pma_domain_wrapped_tests[i].res;7262		r = pw_multi_aff_check_plain_equal(pma, str);7263		isl_pw_multi_aff_free(pma);7264		if (r < 0)7265			return isl_stat_error;7266	}7267 7268	return isl_stat_ok;7269}7270 7271/* Inputs for isl_aff_bind_id tests.7272 * "aff" is the input expression.7273 * "id" is the binding id.7274 * "res" is the expected result.7275 */7276static7277struct {7278	const char *aff;7279	const char *id;7280	const char *res;7281} bind_aff_tests[] = {7282	{ "{ [4] }", "M", "[M = 4] -> { : }" },7283	{ "{ B[x] -> [floor(x/2)] }", "M", "[M] -> { B[x] : M = floor(x/2) }" },7284	{ "[M] -> { [4] }", "M", "[M = 4] -> { : }" },7285	{ "[M] -> { [floor(M/2)] }", "M", "[M] -> { : floor(M/2) = M }" },7286	{ "{ [NaN] }", "M", "{ : false }" },7287	{ "{ A[x] -> [NaN] }", "M", "{ A[x] : false }" },7288};7289 7290/* Perform basic isl_aff_bind_id tests.7291 */7292static isl_stat test_bind_aff(isl_ctx *ctx)7293{7294	int i;7295 7296	for (i = 0; i < ARRAY_SIZE(bind_aff_tests); ++i) {7297		isl_aff *aff;7298		isl_set *res;7299		isl_id *id;7300		isl_stat r;7301 7302		aff = isl_aff_read_from_str(ctx, bind_aff_tests[i].aff);7303		id = isl_id_read_from_str(ctx, bind_aff_tests[i].id);7304		res = isl_set_from_basic_set(isl_aff_bind_id(aff, id));7305		r = set_check_equal(res, bind_aff_tests[i].res);7306		isl_set_free(res);7307		if (r < 0)7308			return isl_stat_error;7309	}7310 7311	return isl_stat_ok;7312}7313 7314/* Inputs for isl_pw_aff_bind_id tests.7315 * "pa" is the input expression.7316 * "id" is the binding id.7317 * "res" is the expected result.7318 */7319static7320struct {7321	const char *pa;7322	const char *id;7323	const char *res;7324} bind_pa_tests[] = {7325	{ "{ [4] }", "M", "[M = 4] -> { : }" },7326	{ "{ B[x] -> [floor(x/2)] }", "M", "[M] -> { B[x] : M = floor(x/2) }" },7327	{ "[M] -> { [4] }", "M", "[M = 4] -> { : }" },7328	{ "[M] -> { [floor(M/2)] }", "M", "[M] -> { : floor(M/2) = M }" },7329	{ "[M] -> { [M] : M >= 0; [-M] : M < 0 }", "M", "[M] -> { : M >= 0 }" },7330	{ "{ [NaN] }", "M", "{ : false }" },7331	{ "{ A[x] -> [NaN] }", "M", "{ A[x] : false }" },7332};7333 7334/* Perform basic isl_pw_aff_bind_id tests.7335 */7336static isl_stat test_bind_pa(isl_ctx *ctx)7337{7338	int i;7339 7340	for (i = 0; i < ARRAY_SIZE(bind_pa_tests); ++i) {7341		isl_pw_aff *pa;7342		isl_set *res;7343		isl_id *id;7344		isl_stat r;7345 7346		pa = isl_pw_aff_read_from_str(ctx, bind_pa_tests[i].pa);7347		id = isl_id_read_from_str(ctx, bind_pa_tests[i].id);7348		res = isl_pw_aff_bind_id(pa, id);7349		r = set_check_equal(res, bind_pa_tests[i].res);7350		isl_set_free(res);7351		if (r < 0)7352			return isl_stat_error;7353	}7354 7355	return isl_stat_ok;7356}7357 7358/* Inputs for isl_multi_union_pw_aff_bind tests.7359 * "mupa" is the input expression.7360 * "tuple" is the binding tuple.7361 * "res" is the expected result.7362 */7363static7364struct {7365	const char *mupa;7366	const char *tuple;7367	const char *res;7368} bind_mupa_tests[] = {7369	{ "A[{ [4] }, { [5] }]",7370	  "{ A[M, N] }",7371	  "[M = 4, N = 5] -> { : }" },7372	{ "A[{ B[x] -> [floor(x/2)] }, { B[y] -> [y + 5] }]",7373	  "{ A[M, N] }",7374	  "[M, N] -> { B[x] : M = floor(x/2) and N = x + 5 }" },7375	{ "[M] -> A[{ [4] }, { [M + 1] }]",7376	  "{ A[M, N] }",7377	  "[M = 4, N = 5] -> { : }" },7378};7379 7380/* Perform basic isl_multi_union_pw_aff_bind tests.7381 */7382static isl_stat test_bind_mupa(isl_ctx *ctx)7383{7384	int i;7385 7386	for (i = 0; i < ARRAY_SIZE(bind_mupa_tests); ++i) {7387		const char *str;7388		isl_multi_union_pw_aff *mupa;7389		isl_union_set *res;7390		isl_multi_id *tuple;7391		isl_stat r;7392 7393		str = bind_mupa_tests[i].mupa;7394		mupa = isl_multi_union_pw_aff_read_from_str(ctx, str);7395		str = bind_mupa_tests[i].tuple;7396		tuple = isl_multi_id_read_from_str(ctx, str);7397		res = isl_multi_union_pw_aff_bind(mupa, tuple);7398		r = uset_check_equal(res, bind_mupa_tests[i].res);7399		isl_union_set_free(res);7400		if (r < 0)7401			return isl_stat_error;7402	}7403 7404	return isl_stat_ok;7405}7406 7407/* Perform tests that reinterpret dimensions as parameters.7408 */7409static int test_bind(isl_ctx *ctx)7410{7411	if (test_bind_set(ctx) < 0)7412		return -1;7413	if (test_bind_map_domain(ctx) < 0)7414		return -1;7415	if (test_bind_umap_range(ctx) < 0)7416		return -1;7417	if (test_bind_pma_domain(ctx) < 0)7418		return -1;7419	if (test_bind_pma_domain_wrapped(ctx) < 0)7420		return -1;7421	if (test_bind_aff(ctx) < 0)7422		return -1;7423	if (test_bind_pa(ctx) < 0)7424		return -1;7425	if (test_bind_mupa(ctx) < 0)7426		return -1;7427 7428	return 0;7429}7430 7431/* Inputs for isl_set_unbind_params tests.7432 * "set" is the input parameter domain.7433 * "tuple" is the tuple of the constructed set.7434 * "res" is the expected result.7435 */7436struct {7437	const char *set;7438	const char *tuple;7439	const char *res;7440} unbind_set_tests[] = {7441	{ "[M, N] -> { : M mod 2 = 0 and N mod 8 = 3 }",7442	  "{ A[M, N] }",7443	  "{ A[M, N] : M mod 2 = 0 and N mod 8 = 3 }" },7444	{ "[M, N] -> { : M mod 2 = 0 and N mod 8 = 3 }",7445	  "{ B[N, M] }",7446	  "{ B[N, M] : M mod 2 = 0 and N mod 8 = 3 }" },7447	{ "[M, N] -> { : M mod 2 = 0 and N mod 8 = 3 }",7448	  "{ C[N] }",7449	  "[M] -> { C[N] : M mod 2 = 0 and N mod 8 = 3 }" },7450	{ "[M, N] -> { : M mod 2 = 0 and N mod 8 = 3 }",7451	  "{ D[T, N] }",7452	  "[M] -> { D[x, N] : M mod 2 = 0 and N mod 8 = 3 }" },7453};7454 7455/* Perform basic isl_set_unbind_params tests.7456 */7457static isl_stat test_unbind_set(isl_ctx *ctx)7458{7459	int i;7460 7461	for (i = 0; i < ARRAY_SIZE(unbind_set_tests); ++i) {7462		const char *str;7463		isl_set *set;7464		isl_multi_id *tuple;7465		isl_stat r;7466 7467		set = isl_set_read_from_str(ctx, unbind_set_tests[i].set);7468		str = unbind_set_tests[i].tuple;7469		tuple = isl_multi_id_read_from_str(ctx, str);7470		set = isl_set_unbind_params(set, tuple);7471		r = set_check_equal(set, unbind_set_tests[i].res);7472		isl_set_free(set);7473		if (r < 0)7474			return isl_stat_error;7475	}7476 7477	return isl_stat_ok;7478}7479 7480/* Inputs for isl_aff_unbind_params_insert_domain tests.7481 * "aff" is the input affine expression defined over a parameter domain.7482 * "tuple" is the tuple of the domain that gets introduced.7483 * "res" is the expected result.7484 */7485struct {7486	const char *aff;7487	const char *tuple;7488	const char *res;7489} unbind_aff_tests[] = {7490	{ "[M, N] -> { [M + floor(N/2)] }",7491	  "{ A[M, N] }",7492	  "{ A[M, N] -> [M + floor(N/2)] }" },7493	{ "[M, N] -> { [M + floor(N/2)] }",7494	  "{ B[N, M] }",7495	  "{ B[N, M] -> [M + floor(N/2)] }" },7496	{ "[M, N] -> { [M + floor(N/2)] }",7497	  "{ C[N] }",7498	  "[M] -> { C[N] -> [M + floor(N/2)] }" },7499	{ "[M, N] -> { [M + floor(N/2)] }",7500	  "{ D[A, B, C, N, Z] }",7501	  "[M] -> { D[A, B, C, N, Z] -> [M + floor(N/2)] }" },7502};7503 7504/* Perform basic isl_aff_unbind_params_insert_domain tests.7505 */7506static isl_stat test_unbind_aff(isl_ctx *ctx)7507{7508	int i;7509 7510	for (i = 0; i < ARRAY_SIZE(unbind_aff_tests); ++i) {7511		const char *str;7512		isl_aff *aff;7513		isl_multi_id *tuple;7514		isl_stat r;7515 7516		aff = isl_aff_read_from_str(ctx, unbind_aff_tests[i].aff);7517		str = unbind_aff_tests[i].tuple;7518		tuple = isl_multi_id_read_from_str(ctx, str);7519		aff = isl_aff_unbind_params_insert_domain(aff, tuple);7520		r = aff_check_plain_equal(aff, unbind_aff_tests[i].res);7521		isl_aff_free(aff);7522		if (r < 0)7523			return isl_stat_error;7524	}7525 7526	return isl_stat_ok;7527}7528 7529/* Inputs for isl_multi_aff_unbind_params_insert_domain tests.7530 * "ma" is the input multi affine expression defined over a parameter domain.7531 * "tuple" is the tuple of the domain that gets introduced.7532 * "res" is the expected result.7533 */7534static struct {7535	const char *ma;7536	const char *tuple;7537	const char *res;7538} unbind_multi_aff_tests[] = {7539	{ "[M, N] -> { T[M + floor(N/2)] }",7540	  "{ A[M, N] }",7541	  "{ A[M, N] -> T[M + floor(N/2)] }" },7542	{ "[M, N] -> { [M + floor(N/2)] }",7543	  "{ B[N, M] }",7544	  "{ B[N, M] -> [M + floor(N/2)] }" },7545	{ "[M, N] -> { [M + floor(N/2)] }",7546	  "{ C[N] }",7547	  "[M] -> { C[N] -> [M + floor(N/2)] }" },7548	{ "[M, N] -> { [M + floor(N/2)] }",7549	  "{ D[A, B, C, N, Z] }",7550	  "[M] -> { D[A, B, C, N, Z] -> [M + floor(N/2)] }" },7551	{ "[M, N] -> { T[M + floor(N/2), N + floor(M/3)] }",7552	  "{ A[M, N] }",7553	  "{ A[M, N] -> T[M + floor(N/2), N + floor(M/3)] }" },7554};7555 7556/* Perform basic isl_multi_aff_unbind_params_insert_domain tests.7557 */7558static isl_stat test_unbind_multi_aff(isl_ctx *ctx)7559{7560	int i;7561 7562	for (i = 0; i < ARRAY_SIZE(unbind_multi_aff_tests); ++i) {7563		const char *str;7564		isl_multi_aff *ma;7565		isl_multi_id *tuple;7566		isl_stat r;7567 7568		str = unbind_multi_aff_tests[i].ma;7569		ma = isl_multi_aff_read_from_str(ctx, str);7570		str = unbind_multi_aff_tests[i].tuple;7571		tuple = isl_multi_id_read_from_str(ctx, str);7572		ma = isl_multi_aff_unbind_params_insert_domain(ma, tuple);7573		str = unbind_multi_aff_tests[i].res;7574		r = multi_aff_check_plain_equal(ma, str);7575		isl_multi_aff_free(ma);7576		if (r < 0)7577			return isl_stat_error;7578	}7579 7580	return isl_stat_ok;7581}7582 7583/* Perform tests that reinterpret parameters.7584 */7585static int test_unbind(isl_ctx *ctx)7586{7587	if (test_unbind_set(ctx) < 0)7588		return -1;7589	if (test_unbind_aff(ctx) < 0)7590		return -1;7591	if (test_unbind_multi_aff(ctx) < 0)7592		return -1;7593 7594	return 0;7595}7596 7597/* Check that "pa" consists of a single expression.7598 */7599static int check_single_piece(isl_ctx *ctx, __isl_take isl_pw_aff *pa)7600{7601	isl_size n;7602 7603	n = isl_pw_aff_n_piece(pa);7604	isl_pw_aff_free(pa);7605 7606	if (n < 0)7607		return -1;7608	if (n != 1)7609		isl_die(ctx, isl_error_unknown, "expecting single expression",7610			return -1);7611 7612	return 0;7613}7614 7615/* Check that the computation below results in a single expression.7616 * One or two expressions may result depending on which constraint7617 * ends up being considered as redundant with respect to the other7618 * constraints after the projection that is performed internally7619 * by isl_set_dim_min.7620 */7621static int test_dim_max_1(isl_ctx *ctx)7622{7623	const char *str;7624	isl_set *set;7625	isl_pw_aff *pa;7626 7627	str = "[n] -> { [a, b] : n >= 0 and 4a >= -4 + n and b >= 0 and "7628				"-4a <= b <= 3 and b < n - 4a }";7629	set = isl_set_read_from_str(ctx, str);7630	pa = isl_set_dim_min(set, 0);7631	return check_single_piece(ctx, pa);7632}7633 7634/* Check that the computation below results in a single expression.7635 * The PIP problem corresponding to these constraints has a row7636 * that causes a split of the solution domain.  The solver should7637 * first pick rows that split off empty parts such that the actual7638 * solution domain does not get split.7639 * Note that the description contains some redundant constraints.7640 * If these constraints get removed first, then the row mentioned7641 * above does not appear in the PIP problem.7642 */7643static int test_dim_max_2(isl_ctx *ctx)7644{7645	const char *str;7646	isl_set *set;7647	isl_pw_aff *pa;7648 7649	str = "[P, N] -> { [a] : a < N and a >= 0 and N > P and a <= P and "7650				"N > 0 and P >= 0 }";7651	set = isl_set_read_from_str(ctx, str);7652	pa = isl_set_dim_max(set, 0);7653	return check_single_piece(ctx, pa);7654}7655 7656int test_dim_max(isl_ctx *ctx)7657{7658	int equal;7659	const char *str;7660	isl_set *set1, *set2;7661	isl_set *set;7662	isl_map *map;7663	isl_pw_aff *pwaff;7664 7665	if (test_dim_max_1(ctx) < 0)7666		return -1;7667	if (test_dim_max_2(ctx) < 0)7668		return -1;7669 7670	str = "[N] -> { [i] : 0 <= i <= min(N,10) }";7671	set = isl_set_read_from_str(ctx, str);7672	pwaff = isl_set_dim_max(set, 0);7673	set1 = isl_set_from_pw_aff(pwaff);7674	str = "[N] -> { [10] : N >= 10; [N] : N <= 9 and N >= 0 }";7675	set2 = isl_set_read_from_str(ctx, str);7676	equal = isl_set_is_equal(set1, set2);7677	isl_set_free(set1);7678	isl_set_free(set2);7679	if (equal < 0)7680		return -1;7681	if (!equal)7682		isl_die(ctx, isl_error_unknown, "unexpected result", return -1);7683 7684	str = "[N] -> { [i] : 0 <= i <= max(2N,N+6) }";7685	set = isl_set_read_from_str(ctx, str);7686	pwaff = isl_set_dim_max(set, 0);7687	set1 = isl_set_from_pw_aff(pwaff);7688	str = "[N] -> { [6 + N] : -6 <= N <= 5; [2N] : N >= 6 }";7689	set2 = isl_set_read_from_str(ctx, str);7690	equal = isl_set_is_equal(set1, set2);7691	isl_set_free(set1);7692	isl_set_free(set2);7693	if (equal < 0)7694		return -1;7695	if (!equal)7696		isl_die(ctx, isl_error_unknown, "unexpected result", return -1);7697 7698	str = "[N] -> { [i] : 0 <= i <= 2N or 0 <= i <= N+6 }";7699	set = isl_set_read_from_str(ctx, str);7700	pwaff = isl_set_dim_max(set, 0);7701	set1 = isl_set_from_pw_aff(pwaff);7702	str = "[N] -> { [6 + N] : -6 <= N <= 5; [2N] : N >= 6 }";7703	set2 = isl_set_read_from_str(ctx, str);7704	equal = isl_set_is_equal(set1, set2);7705	isl_set_free(set1);7706	isl_set_free(set2);7707	if (equal < 0)7708		return -1;7709	if (!equal)7710		isl_die(ctx, isl_error_unknown, "unexpected result", return -1);7711 7712	str = "[N,M] -> { [i,j] -> [([i/16]), i%16, ([j/16]), j%16] : "7713			"0 <= i < N and 0 <= j < M }";7714	map = isl_map_read_from_str(ctx, str);7715	set = isl_map_range(map);7716 7717	pwaff = isl_set_dim_max(isl_set_copy(set), 0);7718	set1 = isl_set_from_pw_aff(pwaff);7719	str = "[N,M] -> { [([(N-1)/16])] : M,N > 0 }";7720	set2 = isl_set_read_from_str(ctx, str);7721	equal = isl_set_is_equal(set1, set2);7722	isl_set_free(set1);7723	isl_set_free(set2);7724 7725	pwaff = isl_set_dim_max(isl_set_copy(set), 3);7726	set1 = isl_set_from_pw_aff(pwaff);7727	str = "[N,M] -> { [t] : t = min(M-1,15) and M,N > 0 }";7728	set2 = isl_set_read_from_str(ctx, str);7729	if (equal >= 0 && equal)7730		equal = isl_set_is_equal(set1, set2);7731	isl_set_free(set1);7732	isl_set_free(set2);7733 7734	isl_set_free(set);7735 7736	if (equal < 0)7737		return -1;7738	if (!equal)7739		isl_die(ctx, isl_error_unknown, "unexpected result", return -1);7740 7741	/* Check that solutions are properly merged. */7742	str = "[n] -> { [a, b, c] : c >= -4a - 2b and "7743				"c <= -1 + n - 4a - 2b and c >= -2b and "7744				"4a >= -4 + n and c >= 0 }";7745	set = isl_set_read_from_str(ctx, str);7746	pwaff = isl_set_dim_min(set, 2);7747	set1 = isl_set_from_pw_aff(pwaff);7748	str = "[n] -> { [(0)] : n >= 1 }";7749	set2 = isl_set_read_from_str(ctx, str);7750	equal = isl_set_is_equal(set1, set2);7751	isl_set_free(set1);7752	isl_set_free(set2);7753 7754	if (equal < 0)7755		return -1;7756	if (!equal)7757		isl_die(ctx, isl_error_unknown, "unexpected result", return -1);7758 7759	/* Check that empty solution lie in the right space. */7760	str = "[n] -> { [t,a] : 1 = 0 }";7761	set = isl_set_read_from_str(ctx, str);7762	pwaff = isl_set_dim_max(set, 0);7763	set1 = isl_set_from_pw_aff(pwaff);7764	str = "[n] -> { [t] : 1 = 0 }";7765	set2 = isl_set_read_from_str(ctx, str);7766	equal = isl_set_is_equal(set1, set2);7767	isl_set_free(set1);7768	isl_set_free(set2);7769 7770	if (equal < 0)7771		return -1;7772	if (!equal)7773		isl_die(ctx, isl_error_unknown, "unexpected result", return -1);7774 7775	return 0;7776}7777 7778/* Basic test for isl_pw_multi_aff_product.7779 *7780 * Check that multiple pieces are properly handled.7781 */7782static int test_product_pma(isl_ctx *ctx)7783{7784	isl_stat equal;7785	const char *str;7786	isl_pw_multi_aff *pma1, *pma2;7787 7788	str = "{ A[i] -> B[1] : i < 0; A[i] -> B[2] : i >= 0 }";7789	pma1 = isl_pw_multi_aff_read_from_str(ctx, str);7790	str = "{ C[] -> D[] }";7791	pma2 = isl_pw_multi_aff_read_from_str(ctx, str);7792	pma1 = isl_pw_multi_aff_product(pma1, pma2);7793	str = "{ [A[i] -> C[]] -> [B[(1)] -> D[]] : i < 0;"7794		"[A[i] -> C[]] -> [B[(2)] -> D[]] : i >= 0 }";7795	equal = pw_multi_aff_check_plain_equal(pma1, str);7796	isl_pw_multi_aff_free(pma1);7797	if (equal < 0)7798		return -1;7799 7800	return 0;7801}7802 7803int test_product(isl_ctx *ctx)7804{7805	const char *str;7806	isl_set *set;7807	isl_union_set *uset1, *uset2;7808	int ok;7809 7810	str = "{ A[i] }";7811	set = isl_set_read_from_str(ctx, str);7812	set = isl_set_product(set, isl_set_copy(set));7813	ok = isl_set_is_wrapping(set);7814	isl_set_free(set);7815	if (ok < 0)7816		return -1;7817	if (!ok)7818		isl_die(ctx, isl_error_unknown, "unexpected result", return -1);7819 7820	str = "{ [] }";7821	uset1 = isl_union_set_read_from_str(ctx, str);7822	uset1 = isl_union_set_product(uset1, isl_union_set_copy(uset1));7823	str = "{ [[] -> []] }";7824	uset2 = isl_union_set_read_from_str(ctx, str);7825	ok = isl_union_set_is_equal(uset1, uset2);7826	isl_union_set_free(uset1);7827	isl_union_set_free(uset2);7828	if (ok < 0)7829		return -1;7830	if (!ok)7831		isl_die(ctx, isl_error_unknown, "unexpected result", return -1);7832 7833	if (test_product_pma(ctx) < 0)7834		return -1;7835 7836	return 0;7837}7838 7839/* Check that two sets are not considered disjoint just because7840 * they have a different set of (named) parameters.7841 */7842static int test_disjoint(isl_ctx *ctx)7843{7844	const char *str;7845	isl_set *set, *set2;7846	int disjoint;7847 7848	str = "[n] -> { [[]->[]] }";7849	set = isl_set_read_from_str(ctx, str);7850	str = "{ [[]->[]] }";7851	set2 = isl_set_read_from_str(ctx, str);7852	disjoint = isl_set_is_disjoint(set, set2);7853	isl_set_free(set);7854	isl_set_free(set2);7855	if (disjoint < 0)7856		return -1;7857	if (disjoint)7858		isl_die(ctx, isl_error_unknown, "unexpected result", return -1);7859 7860	return 0;7861}7862 7863/* Inputs for isl_pw_multi_aff_is_equal tests.7864 * "f1" and "f2" are the two function that need to be compared.7865 * "equal" is the expected result.7866 */7867struct {7868	int equal;7869	const char *f1;7870	const char *f2;7871} pma_equal_tests[] = {7872	{ 1, "[N] -> { [floor(N/2)] : 0 <= N <= 1 }",7873	     "[N] -> { [0] : 0 <= N <= 1 }" },7874	{ 1, "[N] -> { [floor(N/2)] : 0 <= N <= 2 }",7875	     "[N] -> { [0] : 0 <= N <= 1; [1] : N = 2 }" },7876	{ 0, "[N] -> { [floor(N/2)] : 0 <= N <= 2 }",7877	     "[N] -> { [0] : 0 <= N <= 1 }" },7878	{ 0, "{ [NaN] }", "{ [NaN] }" },7879};7880 7881int test_equal(isl_ctx *ctx)7882{7883	int i;7884	const char *str;7885	isl_set *set, *set2;7886	int equal;7887 7888	str = "{ S_6[i] }";7889	set = isl_set_read_from_str(ctx, str);7890	str = "{ S_7[i] }";7891	set2 = isl_set_read_from_str(ctx, str);7892	equal = isl_set_is_equal(set, set2);7893	isl_set_free(set);7894	isl_set_free(set2);7895	if (equal < 0)7896		return -1;7897	if (equal)7898		isl_die(ctx, isl_error_unknown, "unexpected result", return -1);7899 7900	for (i = 0; i < ARRAY_SIZE(pma_equal_tests); ++i) {7901		int expected = pma_equal_tests[i].equal;7902		isl_pw_multi_aff *f1, *f2;7903 7904		f1 = isl_pw_multi_aff_read_from_str(ctx, pma_equal_tests[i].f1);7905		f2 = isl_pw_multi_aff_read_from_str(ctx, pma_equal_tests[i].f2);7906		equal = isl_pw_multi_aff_is_equal(f1, f2);7907		isl_pw_multi_aff_free(f1);7908		isl_pw_multi_aff_free(f2);7909		if (equal < 0)7910			return -1;7911		if (equal != expected)7912			isl_die(ctx, isl_error_unknown,7913				"unexpected equality result", return -1);7914	}7915 7916	return 0;7917}7918 7919static int test_plain_fixed(isl_ctx *ctx, __isl_take isl_map *map,7920	enum isl_dim_type type, unsigned pos, int fixed)7921{7922	isl_bool test;7923 7924	test = isl_map_plain_is_fixed(map, type, pos, NULL);7925	isl_map_free(map);7926	if (test < 0)7927		return -1;7928	if (test == fixed)7929		return 0;7930	if (fixed)7931		isl_die(ctx, isl_error_unknown,7932			"map not detected as fixed", return -1);7933	else7934		isl_die(ctx, isl_error_unknown,7935			"map detected as fixed", return -1);7936}7937 7938int test_fixed(isl_ctx *ctx)7939{7940	const char *str;7941	isl_map *map;7942 7943	str = "{ [i] -> [i] }";7944	map = isl_map_read_from_str(ctx, str);7945	if (test_plain_fixed(ctx, map, isl_dim_out, 0, 0))7946		return -1;7947	str = "{ [i] -> [1] }";7948	map = isl_map_read_from_str(ctx, str);7949	if (test_plain_fixed(ctx, map, isl_dim_out, 0, 1))7950		return -1;7951	str = "{ S_1[p1] -> [o0] : o0 = -2 and p1 >= 1 and p1 <= 7 }";7952	map = isl_map_read_from_str(ctx, str);7953	if (test_plain_fixed(ctx, map, isl_dim_out, 0, 1))7954		return -1;7955	map = isl_map_read_from_str(ctx, str);7956	map = isl_map_neg(map);7957	if (test_plain_fixed(ctx, map, isl_dim_out, 0, 1))7958		return -1;7959 7960	return 0;7961}7962 7963struct isl_vertices_test_data {7964	const char *set;7965	int n;7966	const char *vertex[6];7967} vertices_tests[] = {7968	{ "{ A[t, i] : t = 12 and i >= 4 and i <= 12 }",7969	  2, { "{ A[12, 4] }", "{ A[12, 12] }" } },7970	{ "{ A[t, i] : t = 14 and i = 1 }",7971	  1, { "{ A[14, 1] }" } },7972	{ "[n, m] -> { [a, b, c] : b <= a and a <= n and b > 0 and c >= b and "7973				"c <= m and m <= n and m > 0 }",7974	  6, {7975		"[n, m] -> { [n, m, m] : 0 < m <= n }",7976		"[n, m] -> { [n, 1, m] : 0 < m <= n }",7977		"[n, m] -> { [n, 1, 1] : 0 < m <= n }",7978		"[n, m] -> { [m, m, m] : 0 < m <= n }",7979		"[n, m] -> { [1, 1, m] : 0 < m <= n }",7980		"[n, m] -> { [1, 1, 1] : 0 < m <= n }"7981	    } },7982	/* An input with implicit equality constraints among the parameters. */7983	{ "[N, M] -> { [a, b] : M >= 3 and 9 + 3M <= a <= 29 + 2N + 11M and "7984			    "2b >= M + a and 5 - 2N - M + a <= 2b <= 3 + a and "7985			    "3b >= 15 + a }",7986	  2, {7987		"[N, M] -> { [(21), (12)] : M = 3 and N >= 0 }",7988		"[N, M] -> { [(61 + 2N), (32 + N)] : M = 3 and N >= 0 }",7989	     }7990	},7991};7992 7993/* Check that "vertex" corresponds to one of the vertices in data->vertex.7994 */7995static isl_stat find_vertex(__isl_take isl_vertex *vertex, void *user)7996{7997	struct isl_vertices_test_data *data = user;7998	isl_ctx *ctx;7999	isl_multi_aff *ma;8000	isl_basic_set *bset;8001	isl_pw_multi_aff *pma;8002	int i;8003	isl_bool equal;8004 8005	ctx = isl_vertex_get_ctx(vertex);8006	bset = isl_vertex_get_domain(vertex);8007	ma = isl_vertex_get_expr(vertex);8008	pma = isl_pw_multi_aff_alloc(isl_set_from_basic_set(bset), ma);8009 8010	for (i = 0; i < data->n; ++i) {8011		isl_pw_multi_aff *pma_i;8012 8013		pma_i = isl_pw_multi_aff_read_from_str(ctx, data->vertex[i]);8014		equal = isl_pw_multi_aff_plain_is_equal(pma, pma_i);8015		isl_pw_multi_aff_free(pma_i);8016 8017		if (equal < 0 || equal)8018			break;8019	}8020 8021	isl_pw_multi_aff_free(pma);8022	isl_vertex_free(vertex);8023 8024	if (equal < 0)8025		return isl_stat_error;8026 8027	return equal ? isl_stat_ok : isl_stat_error;8028}8029 8030int test_vertices(isl_ctx *ctx)8031{8032	int i;8033 8034	for (i = 0; i < ARRAY_SIZE(vertices_tests); ++i) {8035		isl_basic_set *bset;8036		isl_vertices *vertices;8037		int ok = 1;8038		isl_size n;8039 8040		bset = isl_basic_set_read_from_str(ctx, vertices_tests[i].set);8041		vertices = isl_basic_set_compute_vertices(bset);8042		n = isl_vertices_get_n_vertices(vertices);8043		if (vertices_tests[i].n != n)8044			ok = 0;8045		if (isl_vertices_foreach_vertex(vertices, &find_vertex,8046						&vertices_tests[i]) < 0)8047			ok = 0;8048		isl_vertices_free(vertices);8049		isl_basic_set_free(bset);8050 8051		if (n < 0)8052			return -1;8053		if (!ok)8054			isl_die(ctx, isl_error_unknown, "unexpected vertices",8055				return -1);8056	}8057 8058	return 0;8059}8060 8061/* Inputs for basic tests of unary operations on isl_union_map.8062 * "fn" is the function that is being tested.8063 * "arg" is a string description of the input.8064 * "res" is a string description of the expected result.8065 */8066static struct {8067	__isl_give isl_union_map *(*fn)(__isl_take isl_union_map *umap);8068	const char *arg;8069	const char *res;8070} umap_un_tests[] = {8071	{ &isl_union_map_range_reverse,8072	  "{ A[] -> [B[] -> C[]]; A[] -> B[]; A[0] -> N[B[1] -> B[2]] }",8073	  "{ A[] -> [C[] -> B[]]; A[0] -> N[B[2] -> B[1]] }" },8074	{ &isl_union_map_range_reverse,8075	  "{ A[] -> N[B[] -> C[]] }",8076	  "{ A[] -> [C[] -> B[]] }" },8077	{ &isl_union_map_range_reverse,8078	  "{ A[] -> N[B[x] -> B[y]] }",8079	  "{ A[] -> N[B[*] -> B[*]] }" },8080};8081 8082/* Perform basic tests of unary operations on isl_union_map.8083 */8084static isl_stat test_un_union_map(isl_ctx *ctx)8085{8086	int i;8087 8088	for (i = 0; i < ARRAY_SIZE(umap_un_tests); ++i) {8089		const char *str;8090		isl_union_map *umap, *res;8091		isl_bool equal;8092 8093		str = umap_un_tests[i].arg;8094		umap = isl_union_map_read_from_str(ctx, str);8095		str = umap_un_tests[i].res;8096		res = isl_union_map_read_from_str(ctx, str);8097		umap = umap_un_tests[i].fn(umap);8098		equal = isl_union_map_is_equal(umap, res);8099		isl_union_map_free(umap);8100		isl_union_map_free(res);8101		if (equal < 0)8102			return isl_stat_error;8103		if (!equal)8104			isl_die(ctx, isl_error_unknown,8105				"unexpected result", return isl_stat_error);8106	}8107 8108	return isl_stat_ok;8109}8110 8111/* Inputs for basic tests of binary operations on isl_union_map.8112 * "fn" is the function that is being tested.8113 * "arg1" and "arg2" are string descriptions of the inputs.8114 * "res" is a string description of the expected result.8115 */8116static struct {8117	__isl_give isl_union_map *(*fn)(__isl_take isl_union_map *umap1,8118				__isl_take isl_union_map *umap2);8119	const char *arg1;8120	const char *arg2;8121	const char *res;8122} umap_bin_tests[] = {8123	{ &isl_union_map_intersect,8124	  "[n] -> { A[i] -> [] : 0 <= i <= n; B[] -> [] }",8125	  "[m] -> { A[i] -> [] : 0 <= i <= m; C[] -> [] }",8126	  "[m, n] -> { A[i] -> [] : 0 <= i <= n and i <= m }" },8127	{ &isl_union_map_intersect_domain_factor_domain,8128	  "{ [A[i] -> B[i + 1]] -> C[i + 2] }",8129	  "[N] -> { B[i] -> C[N] }",8130	  "{ }" },8131	{ &isl_union_map_intersect_domain_factor_domain,8132	  "{ [A[i] -> B[i + 1]] -> C[i + 2] }",8133	  "[N] -> { A[i] -> C[N] }",8134	  "[N] -> { [A[N - 2] -> B[N - 1]] -> C[N] }" },8135	{ &isl_union_map_intersect_domain_factor_domain,8136	  "{ T[A[i] -> B[i + 1]] -> C[i + 2] }",8137	  "[N] -> { A[i] -> C[N] }",8138	  "[N] -> { T[A[N - 2] -> B[N - 1]] -> C[N] }" },8139	{ &isl_union_map_intersect_domain_factor_range,8140	  "{ [A[i] -> B[i + 1]] -> C[i + 2] }",8141	  "[N] -> { B[i] -> C[N] }",8142	  "[N] -> { [A[N - 2] -> B[N - 1]] -> C[N] }" },8143	{ &isl_union_map_intersect_domain_factor_range,8144	  "{ T[A[i] -> B[i + 1]] -> C[i + 2] }",8145	  "[N] -> { B[i] -> C[N] }",8146	  "[N] -> { T[A[N - 2] -> B[N - 1]] -> C[N] }" },8147	{ &isl_union_map_intersect_domain_factor_range,8148	  "{ [A[i] -> B[i + 1]] -> C[i + 2] }",8149	  "[N] -> { A[i] -> C[N] }",8150	  "{ }" },8151	{ &isl_union_map_intersect_range_factor_domain,8152	  "{ A[i] -> [B[i + 1] -> C[i + 2]] }",8153	  "[N] -> { A[i] -> B[N] }",8154	  "[N] -> { A[N - 1] -> [B[N] -> C[N + 1]] }" },8155	{ &isl_union_map_intersect_range_factor_domain,8156	  "{ A[i] -> T[B[i + 1] -> C[i + 2]] }",8157	  "[N] -> { A[i] -> B[N] }",8158	  "[N] -> { A[N - 1] -> T[B[N] -> C[N + 1]] }" },8159	{ &isl_union_map_intersect_range_factor_domain,8160	  "{ A[i] -> [B[i + 1] -> C[i + 2]] }",8161	  "[N] -> { A[i] -> C[N] }",8162	  "{ }" },8163	{ &isl_union_map_intersect_range_factor_range,8164	  "{ A[i] -> [B[i + 1] -> C[i + 2]] }",8165	  "[N] -> { A[i] -> C[N] }",8166	  "[N] -> { A[N - 2] -> [B[N - 1] -> C[N]] }" },8167	{ &isl_union_map_intersect_range_factor_range,8168	  "{ A[i] -> T[B[i + 1] -> C[i + 2]] }",8169	  "[N] -> { A[i] -> C[N] }",8170	  "[N] -> { A[N - 2] -> T[B[N - 1] -> C[N]] }" },8171	{ &isl_union_map_intersect_range_factor_range,8172	  "{ A[i] -> [B[i + 1] -> C[i + 2]] }",8173	  "[N] -> { A[i] -> B[N] }",8174	  "{ }" },8175};8176 8177/* Perform basic tests of binary operations on isl_union_map.8178 */8179static isl_stat test_bin_union_map(isl_ctx *ctx)8180{8181	int i;8182 8183	for (i = 0; i < ARRAY_SIZE(umap_bin_tests); ++i) {8184		const char *str;8185		isl_union_map *umap1, *umap2, *res;8186		isl_bool equal;8187 8188		str = umap_bin_tests[i].arg1;8189		umap1 = isl_union_map_read_from_str(ctx, str);8190		str = umap_bin_tests[i].arg2;8191		umap2 = isl_union_map_read_from_str(ctx, str);8192		str = umap_bin_tests[i].res;8193		res = isl_union_map_read_from_str(ctx, str);8194		umap1 = umap_bin_tests[i].fn(umap1, umap2);8195		equal = isl_union_map_is_equal(umap1, res);8196		isl_union_map_free(umap1);8197		isl_union_map_free(res);8198		if (equal < 0)8199			return isl_stat_error;8200		if (!equal)8201			isl_die(ctx, isl_error_unknown,8202				"unexpected result", return isl_stat_error);8203	}8204 8205	return isl_stat_ok;8206}8207 8208/* Check that isl_union_set_contains finds space independently8209 * of the parameters.8210 */8211static isl_stat test_union_set_contains(isl_ctx *ctx)8212{8213	const char *str;8214	isl_bool ok;8215	isl_space *space;8216	isl_id *id;8217	isl_union_set *uset;8218 8219	str = "[N] -> { A[0:N]; B[*,*] }";8220	uset = isl_union_set_read_from_str(ctx, str);8221	space = isl_space_unit(ctx);8222	id = isl_id_alloc(ctx, "A", NULL);8223	space = isl_space_add_named_tuple_id_ui(space, id, 1);8224	ok = isl_union_set_contains(uset, space);8225	isl_space_free(space);8226	isl_union_set_free(uset);8227 8228	if (ok < 0)8229		return isl_stat_error;8230	if (!ok)8231		isl_die(ctx, isl_error_unknown,8232			"unexpected result", return isl_stat_error);8233 8234	return isl_stat_ok;8235}8236 8237/* Perform basic tests of operations on isl_union_map or isl_union_set.8238 */8239static int test_union_map(isl_ctx *ctx)8240{8241	if (test_un_union_map(ctx) < 0)8242		return -1;8243	if (test_bin_union_map(ctx) < 0)8244		return -1;8245	if (test_union_set_contains(ctx) < 0)8246		return -1;8247	return 0;8248}8249 8250#undef BASE8251#define BASE	union_pw_qpolynomial8252#include "isl_test_plain_equal_templ.c"8253 8254/* Check that the result of applying "fn" to "a" and "b"8255 * in (obviously) equal to "res".8256 */8257static isl_stat test_union_pw_op(isl_ctx *ctx, const char *a, const char *b,8258	__isl_give isl_union_pw_qpolynomial *(*fn)(8259		__isl_take isl_union_pw_qpolynomial *upwqp1,8260		__isl_take isl_union_pw_qpolynomial *upwqp2),8261	const char *res)8262{8263	isl_stat r;8264	isl_union_pw_qpolynomial *upwqp1, *upwqp2;8265 8266	upwqp1 = isl_union_pw_qpolynomial_read_from_str(ctx, a);8267	upwqp2 = isl_union_pw_qpolynomial_read_from_str(ctx, b);8268	upwqp1 = fn(upwqp1, upwqp2);8269	r = union_pw_qpolynomial_check_plain_equal(upwqp1, res);8270	isl_union_pw_qpolynomial_free(upwqp1);8271 8272	return r;8273}8274 8275int test_union_pw(isl_ctx *ctx)8276{8277	int equal;8278	const char *str;8279	isl_union_set *uset;8280	isl_union_pw_qpolynomial *upwqp1, *upwqp2;8281	const char *a, *b;8282 8283	str = "{ [x] -> x^2 }";8284	upwqp1 = isl_union_pw_qpolynomial_read_from_str(ctx, str);8285	upwqp2 = isl_union_pw_qpolynomial_copy(upwqp1);8286	uset = isl_union_pw_qpolynomial_domain(upwqp1);8287	upwqp1 = isl_union_pw_qpolynomial_copy(upwqp2);8288	upwqp1 = isl_union_pw_qpolynomial_intersect_domain(upwqp1, uset);8289	equal = isl_union_pw_qpolynomial_plain_is_equal(upwqp1, upwqp2);8290	isl_union_pw_qpolynomial_free(upwqp1);8291	isl_union_pw_qpolynomial_free(upwqp2);8292	if (equal < 0)8293		return -1;8294	if (!equal)8295		isl_die(ctx, isl_error_unknown, "unexpected result", return -1);8296 8297	a = "{ A[x] -> x^2 : x >= 0; B[x] -> x }";8298	b = "{ A[x] -> x }";8299	str = "{ A[x] -> x^2 + x : x >= 0; A[x] -> x : x < 0; B[x] -> x }";8300	if (test_union_pw_op(ctx, a, b, &isl_union_pw_qpolynomial_add, str) < 0)8301		return -1;8302	str = "{ A[x] -> x^2 - x : x >= 0; A[x] -> -x : x < 0; B[x] -> x }";8303	if (test_union_pw_op(ctx, a, b, &isl_union_pw_qpolynomial_sub, str) < 0)8304		return -1;8305 8306	str = "{ A[x] -> 0 }";8307	a = "{ A[x] -> 1 }";8308	b = "{ A[x] -> -1 }";8309	if (test_union_pw_op(ctx, a, b, &isl_union_pw_qpolynomial_add, str) < 0)8310		return -1;8311	a = "{ A[x] -> 1 }";8312	b = "{ A[x] -> 1 }";8313	if (test_union_pw_op(ctx, a, b, &isl_union_pw_qpolynomial_sub, str) < 0)8314		return -1;8315 8316	return 0;8317}8318 8319/* Inputs for basic tests of functions that select8320 * subparts of the domain of an isl_multi_union_pw_aff.8321 * "fn" is the function that is tested.8322 * "arg" is a string description of the input.8323 * "res" is a string description of the expected result.8324 */8325struct {8326	__isl_give isl_union_set *(*fn)(8327		__isl_take isl_multi_union_pw_aff *mupa);8328	const char *arg;8329	const char *res;8330} un_locus_tests[] = {8331	{ &isl_multi_union_pw_aff_zero_union_set,8332	  "F[{ A[i,j] -> [i]; B[i,j] -> [i] }]",8333	  "{ A[0,j]; B[0,j] }" },8334	{ &isl_multi_union_pw_aff_zero_union_set,8335	  "F[{ A[i,j] -> [i-j]; B[i,j] -> [i-j] : i >= 0 }]",8336	  "{ A[i,i]; B[i,i] : i >= 0 }" },8337	{ &isl_multi_union_pw_aff_zero_union_set,8338	  "(F[] : { A[i,j]; B[i,i] : i >= 0 })",8339	  "{ A[i,j]; B[i,i] : i >= 0 }" },8340};8341 8342/* Perform some basic tests of functions that select8343 * subparts of the domain of an isl_multi_union_pw_aff.8344 */8345static int test_un_locus(isl_ctx *ctx)8346{8347	int i;8348	isl_bool ok;8349	isl_union_set *uset, *res;8350	isl_multi_union_pw_aff *mupa;8351 8352	for (i = 0; i < ARRAY_SIZE(un_locus_tests); ++i) {8353		mupa = isl_multi_union_pw_aff_read_from_str(ctx,8354						    un_locus_tests[i].arg);8355		res = isl_union_set_read_from_str(ctx, un_locus_tests[i].res);8356		uset = un_locus_tests[i].fn(mupa);8357		ok = isl_union_set_is_equal(uset, res);8358		isl_union_set_free(uset);8359		isl_union_set_free(res);8360		if (ok < 0)8361			return -1;8362		if (!ok)8363			isl_die(ctx, isl_error_unknown,8364				"unexpected result", return -1);8365	}8366 8367	return 0;8368}8369 8370/* Inputs for basic tests of functions that select8371 * subparts of an isl_union_map based on a relation8372 * specified by an isl_multi_union_pw_aff.8373 * "fn" is the function that is tested.8374 * "arg1" and "arg2" are string descriptions of the inputs.8375 * "res" is a string description of the expected result.8376 */8377struct {8378	__isl_give isl_union_map *(*fn)(8379		__isl_take isl_union_map *umap,8380		__isl_take isl_multi_union_pw_aff *mupa);8381	const char *arg1;8382	const char *arg2;8383	const char *res;8384} bin_locus_tests[] = {8385	{ &isl_union_map_eq_at_multi_union_pw_aff,8386	  "{ A[i,j] -> B[i',j'] }",8387	  "F[{ A[i,j] -> [i]; B[i,j] -> [i] }]",8388	  "{ A[i,j] -> B[i,j'] }" },8389	{ &isl_union_map_eq_at_multi_union_pw_aff,8390	  "{ A[i,j] -> B[i',j'] }",8391	  "F[{ A[i,j] -> [i]; B[i,j] -> [i] }, "8392	    "{ A[i,j] -> [j]; B[i,j] -> [j] }]",8393	  "{ A[i,j] -> B[i,j] }" },8394	{ &isl_union_map_eq_at_multi_union_pw_aff,8395	  "{ A[i,j] -> B[i',j']; A[i,j] -> C[i',j'] }",8396	  "F[{ A[i,j] -> [i]; B[i,j] -> [i] }]",8397	  "{ A[i,j] -> B[i,j'] }" },8398	{ &isl_union_map_eq_at_multi_union_pw_aff,8399	  "{ A[i,j] -> B[i',j']; A[i,j] -> C[i',j'] }",8400	  "F[{ A[i,j] -> [i]; B[i,j] -> [i]; C[i,j] -> [0] }]",8401	  "{ A[i,j] -> B[i,j']; A[0,j] -> C[i',j'] }" },8402	{ &isl_union_map_eq_at_multi_union_pw_aff,8403	  "{ A[i,j] -> B[i',j'] }",8404	  "F[{ A[i,j] -> [i] : i > j; B[i,j] -> [i] }]",8405	  "{ A[i,j] -> B[i,j'] : i > j }" },8406	{ &isl_union_map_lex_le_at_multi_union_pw_aff,8407	  "{ A[i,j] -> B[i',j'] }",8408	  "F[{ A[i,j] -> [i]; B[i,j] -> [i] }, "8409	    "{ A[i,j] -> [j]; B[i,j] -> [j] }]",8410	  "{ A[i,j] -> B[i',j'] : i,j <<= i',j' }" },8411	{ &isl_union_map_lex_lt_at_multi_union_pw_aff,8412	  "{ A[i,j] -> B[i',j'] }",8413	  "F[{ A[i,j] -> [i]; B[i,j] -> [i] }, "8414	    "{ A[i,j] -> [j]; B[i,j] -> [j] }]",8415	  "{ A[i,j] -> B[i',j'] : i,j << i',j' }" },8416	{ &isl_union_map_lex_ge_at_multi_union_pw_aff,8417	  "{ A[i,j] -> B[i',j'] }",8418	  "F[{ A[i,j] -> [i]; B[i,j] -> [i] }, "8419	    "{ A[i,j] -> [j]; B[i,j] -> [j] }]",8420	  "{ A[i,j] -> B[i',j'] : i,j >>= i',j' }" },8421	{ &isl_union_map_lex_gt_at_multi_union_pw_aff,8422	  "{ A[i,j] -> B[i',j'] }",8423	  "F[{ A[i,j] -> [i]; B[i,j] -> [i] }, "8424	    "{ A[i,j] -> [j]; B[i,j] -> [j] }]",8425	  "{ A[i,j] -> B[i',j'] : i,j >> i',j' }" },8426	{ &isl_union_map_eq_at_multi_union_pw_aff,8427	  "{ A[i,j] -> B[i',j']; A[i,j] -> C[i',j'] }",8428	  "(F[] : { A[i,j]; B[i,j] })",8429	  "{ A[i,j] -> B[i',j'] }" },8430	{ &isl_union_map_eq_at_multi_union_pw_aff,8431	  "{ A[i,j] -> B[i',j'] }",8432	  "(F[] : { A[i,j] : i > j; B[i,j] : i < j })",8433	  "{ A[i,j] -> B[i',j'] : i > j and i' < j' }" },8434	{ &isl_union_map_eq_at_multi_union_pw_aff,8435	  "[N] -> { A[i,j] -> B[i',j'] : i,i' <= N }",8436	  "(F[] : { A[i,j] : i > j; B[i,j] : i < j })",8437	  "[N] -> { A[i,j] -> B[i',j'] : i > j and i' < j' and i,i' <= N }" },8438	{ &isl_union_map_eq_at_multi_union_pw_aff,8439	  "{ A[i,j] -> B[i',j'] }",8440	  "[N] -> (F[] : { A[i,j] : i < N; B[i,j] : i < N })",8441	  "[N] -> { A[i,j] -> B[i',j'] : i,i' < N }" },8442	{ &isl_union_map_eq_at_multi_union_pw_aff,8443	  "{ A[i,j] -> B[i',j'] }",8444	  "[N] -> (F[] : { : N >= 0 })",8445	  "[N] -> { A[i,j] -> B[i',j'] : N >= 0 }" },8446};8447 8448/* Perform some basic tests of functions that select8449 * subparts of an isl_union_map based on a relation8450 * specified by an isl_multi_union_pw_aff.8451 */8452static int test_bin_locus(isl_ctx *ctx)8453{8454	int i;8455	isl_bool ok;8456	isl_union_map *umap, *res;8457	isl_multi_union_pw_aff *mupa;8458 8459	for (i = 0; i < ARRAY_SIZE(bin_locus_tests); ++i) {8460		umap = isl_union_map_read_from_str(ctx,8461						    bin_locus_tests[i].arg1);8462		mupa = isl_multi_union_pw_aff_read_from_str(ctx,8463						    bin_locus_tests[i].arg2);8464		res = isl_union_map_read_from_str(ctx, bin_locus_tests[i].res);8465		umap = bin_locus_tests[i].fn(umap, mupa);8466		ok = isl_union_map_is_equal(umap, res);8467		isl_union_map_free(umap);8468		isl_union_map_free(res);8469		if (ok < 0)8470			return -1;8471		if (!ok)8472			isl_die(ctx, isl_error_unknown,8473				"unexpected result", return -1);8474	}8475 8476	return 0;8477}8478 8479/* Inputs for basic tests of functions that determine8480 * the part of the domain where two isl_multi_aff objects8481 * related to each other in a specific way.8482 * "fn" is the function that is being tested.8483 * "arg1" and "arg2" are string descriptions of the inputs.8484 * "res" is a string description of the expected result.8485 */8486static struct {8487	__isl_give isl_set *(*fn)(__isl_take isl_multi_aff *ma1,8488		__isl_take isl_multi_aff *ma2);8489	const char *arg1;8490	const char *arg2;8491	const char *res;8492} bin_locus_ma_tests[] = {8493	{ &isl_multi_aff_lex_le_set, "{ [] }", "{ [] }", "{ : }" },8494	{ &isl_multi_aff_lex_lt_set, "{ [] }", "{ [] }", "{ : false }" },8495	{ &isl_multi_aff_lex_le_set,8496	  "{ A[i] -> [i] }", "{ A[i] -> [0] }",8497	  "{ A[i] : i <= 0 }" },8498	{ &isl_multi_aff_lex_lt_set,8499	  "{ A[i] -> [i] }", "{ A[i] -> [0] }",8500	  "{ A[i] : i < 0 }" },8501	{ &isl_multi_aff_lex_le_set,8502	  "{ A[i] -> [i, i] }", "{ A[i] -> [0, 0] }",8503	  "{ A[i] : i <= 0 }" },8504	{ &isl_multi_aff_lex_le_set,8505	  "{ A[i] -> [i, 0] }", "{ A[i] -> [0, 0] }",8506	  "{ A[i] : i <= 0 }" },8507	{ &isl_multi_aff_lex_le_set,8508	  "{ A[i] -> [i, 1] }", "{ A[i] -> [0, 0] }",8509	  "{ A[i] : i < 0 }" },8510};8511 8512/* Perform some basic tests of functions that determine8513 * the part of the domain where two isl_multi_aff objects8514 * related to each other in a specific way.8515 */8516static isl_stat test_bin_locus_ma(isl_ctx *ctx)8517{8518	int i;8519 8520	for (i = 0; i < ARRAY_SIZE(bin_locus_ma_tests); ++i) {8521		const char *str;8522		isl_bool ok;8523		isl_multi_aff *ma1, *ma2;8524		isl_set *set, *res;8525 8526		str = bin_locus_ma_tests[i].arg1;8527		ma1 = isl_multi_aff_read_from_str(ctx, str);8528		str = bin_locus_ma_tests[i].arg2;8529		ma2 = isl_multi_aff_read_from_str(ctx, str);8530		res = isl_set_read_from_str(ctx, bin_locus_ma_tests[i].res);8531		set = bin_locus_ma_tests[i].fn(ma1, ma2);8532		ok = isl_set_is_equal(set, res);8533		isl_set_free(set);8534		isl_set_free(res);8535		if (ok < 0)8536			return isl_stat_error;8537		if (!ok)8538			isl_die(ctx, isl_error_unknown,8539				"unexpected result", return isl_stat_error);8540	}8541 8542	return isl_stat_ok;8543}8544 8545/* Perform basic locus tests.8546 */8547static int test_locus(isl_ctx *ctx)8548{8549	if (test_un_locus(ctx) < 0)8550		return -1;8551	if (test_bin_locus(ctx) < 0)8552		return -1;8553	if (test_bin_locus_ma(ctx) < 0)8554		return -1;8555	return 0;8556}8557 8558/* Test that isl_union_pw_qpolynomial_eval picks up the function8559 * defined over the correct domain space.8560 */8561static int test_eval_1(isl_ctx *ctx)8562{8563	const char *str;8564	isl_point *pnt;8565	isl_set *set;8566	isl_union_pw_qpolynomial *upwqp;8567	isl_val *v;8568	int cmp;8569 8570	str = "{ A[x] -> x^2; B[x] -> -x^2 }";8571	upwqp = isl_union_pw_qpolynomial_read_from_str(ctx, str);8572	str = "{ A[6] }";8573	set = isl_set_read_from_str(ctx, str);8574	pnt = isl_set_sample_point(set);8575	v = isl_union_pw_qpolynomial_eval(upwqp, pnt);8576	cmp = isl_val_cmp_si(v, 36);8577	isl_val_free(v);8578 8579	if (!v)8580		return -1;8581	if (cmp != 0)8582		isl_die(ctx, isl_error_unknown, "unexpected value", return -1);8583 8584	return 0;8585}8586 8587/* Check that isl_qpolynomial_eval handles getting called on a void point.8588 */8589static int test_eval_2(isl_ctx *ctx)8590{8591	const char *str;8592	isl_point *pnt;8593	isl_set *set;8594	isl_qpolynomial *qp;8595	isl_val *v;8596	isl_bool ok;8597 8598	str = "{ A[x] -> [x] }";8599	qp = isl_qpolynomial_from_aff(isl_aff_read_from_str(ctx, str));8600	str = "{ A[x] : false }";8601	set = isl_set_read_from_str(ctx, str);8602	pnt = isl_set_sample_point(set);8603	v = isl_qpolynomial_eval(qp, pnt);8604	ok = isl_val_is_nan(v);8605	isl_val_free(v);8606 8607	if (ok < 0)8608		return -1;8609	if (!ok)8610		isl_die(ctx, isl_error_unknown, "expecting NaN", return -1);8611 8612	return 0;8613}8614 8615/* Check that a polynomial (without local variables) can be evaluated8616 * in a rational point.8617 */8618static isl_stat test_eval_3(isl_ctx *ctx)8619{8620	isl_pw_qpolynomial *pwqp;8621	isl_point *pnt;8622	isl_val *v;8623	isl_stat r;8624 8625	pwqp = isl_pw_qpolynomial_read_from_str(ctx, "{ [x] -> x^2 }");8626	pnt = isl_point_zero(isl_pw_qpolynomial_get_domain_space(pwqp));8627	v = isl_val_read_from_str(ctx, "1/2");8628	pnt = isl_point_set_coordinate_val(pnt, isl_dim_set, 0, v);8629	v = isl_pw_qpolynomial_eval(pwqp, pnt);8630	r = val_check_equal(v, "1/4");8631	isl_val_free(v);8632 8633	return r;8634}8635 8636/* Inputs for isl_pw_aff_eval test.8637 * "f" is the affine function.8638 * "p" is the point where the function should be evaluated.8639 * "res" is the expected result.8640 */8641struct {8642	const char *f;8643	const char *p;8644	const char *res;8645} aff_eval_tests[] = {8646	{ "{ [i] -> [2 * i] }", "{ [4] }", "8" },8647	{ "{ [i] -> [2 * i] }", "{ [x] : false }", "NaN" },8648	{ "{ [i] -> [i + floor(i/2) + floor(i/3)] }", "{ [0] }", "0" },8649	{ "{ [i] -> [i + floor(i/2) + floor(i/3)] }", "{ [1] }", "1" },8650	{ "{ [i] -> [i + floor(i/2) + floor(i/3)] }", "{ [2] }", "3" },8651	{ "{ [i] -> [i + floor(i/2) + floor(i/3)] }", "{ [3] }", "5" },8652	{ "{ [i] -> [i + floor(i/2) + floor(i/3)] }", "{ [4] }", "7" },8653	{ "{ [i] -> [floor((3 * floor(i/2))/5)] }", "{ [0] }", "0" },8654	{ "{ [i] -> [floor((3 * floor(i/2))/5)] }", "{ [1] }", "0" },8655	{ "{ [i] -> [floor((3 * floor(i/2))/5)] }", "{ [2] }", "0" },8656	{ "{ [i] -> [floor((3 * floor(i/2))/5)] }", "{ [3] }", "0" },8657	{ "{ [i] -> [floor((3 * floor(i/2))/5)] }", "{ [4] }", "1" },8658	{ "{ [i] -> [floor((3 * floor(i/2))/5)] }", "{ [6] }", "1" },8659	{ "{ [i] -> [floor((3 * floor(i/2))/5)] }", "{ [8] }", "2" },8660	{ "{ [i] -> [i] : i > 0; [i] -> [-i] : i < 0 }", "{ [4] }", "4" },8661	{ "{ [i] -> [i] : i > 0; [i] -> [-i] : i < 0 }", "{ [-2] }", "2" },8662	{ "{ [i] -> [i] : i > 0; [i] -> [-i] : i < 0 }", "{ [0] }", "NaN" },8663	{ "[N] -> { [2 * N] }", "[N] -> { : N = 4 }", "8" },8664	{ "{ [i, j] -> [(i + j)/2] }", "{ [1, 1] }", "1" },8665	{ "{ [i, j] -> [(i + j)/2] }", "{ [1, 2] }", "3/2" },8666	{ "{ [i] -> [i] : i mod 2 = 0 }", "{ [4] }", "4" },8667	{ "{ [i] -> [i] : i mod 2 = 0 }", "{ [3] }", "NaN" },8668	{ "{ [i] -> [i] : i mod 2 = 0 }", "{ [x] : false }", "NaN" },8669	{ "[m, n] -> { [2m + 3n] }", "[n=1, m=10] -> { : }", "23" },8670};8671 8672/* Perform basic isl_pw_aff_eval tests.8673 */8674static int test_eval_aff(isl_ctx *ctx)8675{8676	int i;8677 8678	for (i = 0; i < ARRAY_SIZE(aff_eval_tests); ++i) {8679		isl_stat r;8680		isl_pw_aff *pa;8681		isl_set *set;8682		isl_point *pnt;8683		isl_val *v;8684 8685		pa = isl_pw_aff_read_from_str(ctx, aff_eval_tests[i].f);8686		set = isl_set_read_from_str(ctx, aff_eval_tests[i].p);8687		pnt = isl_set_sample_point(set);8688		v = isl_pw_aff_eval(pa, pnt);8689		r = val_check_equal(v, aff_eval_tests[i].res);8690		isl_val_free(v);8691		if (r < 0)8692			return -1;8693	}8694	return 0;8695}8696 8697/* Perform basic evaluation tests.8698 */8699static int test_eval(isl_ctx *ctx)8700{8701	if (test_eval_1(ctx) < 0)8702		return -1;8703	if (test_eval_2(ctx) < 0)8704		return -1;8705	if (test_eval_3(ctx) < 0)8706		return -1;8707	if (test_eval_aff(ctx) < 0)8708		return -1;8709	return 0;8710}8711 8712/* Descriptions of sets that are tested for reparsing after printing.8713 */8714const char *output_tests[] = {8715	"{ [1, y] : 0 <= y <= 1; [x, -x] : 0 <= x <= 1 }",8716	"{ [x] : 1 = 0 }",8717	"{ [x] : false }",8718	"{ [x] : x mod 2 = 0 }",8719	"{ [x] : x mod 2 = 1 }",8720	"{ [x, y] : x mod 2 = 0 and 3*floor(y/2) < x }",8721	"{ [y, x] : x mod 2 = 0 and 3*floor(y/2) < x }",8722	"{ [x, y] : x mod 2 = 0 and 3*floor(y/2) = x + y }",8723	"{ [y, x] : x mod 2 = 0 and 3*floor(y/2) = x + y }",8724	"[n] -> { [y, x] : 2*((x + 2y) mod 3) = n }",8725	"{ [x, y] : (2*floor(x/3) + 3*floor(y/4)) mod 5 = x }",8726};8727 8728/* Check that printing a set and reparsing a set from the printed output8729 * results in the same set.8730 */8731static int test_output_set(isl_ctx *ctx)8732{8733	int i;8734	char *str;8735	isl_set *set1, *set2;8736	isl_bool equal;8737 8738	for (i = 0; i < ARRAY_SIZE(output_tests); ++i) {8739		set1 = isl_set_read_from_str(ctx, output_tests[i]);8740		str = isl_set_to_str(set1);8741		set2 = isl_set_read_from_str(ctx, str);8742		free(str);8743		equal = isl_set_is_equal(set1, set2);8744		isl_set_free(set1);8745		isl_set_free(set2);8746		if (equal < 0)8747			return -1;8748		if (!equal)8749			isl_die(ctx, isl_error_unknown,8750				"parsed output not the same", return -1);8751	}8752 8753	return 0;8754}8755 8756/* Check that an isl_multi_aff is printed using a consistent space.8757 */8758static isl_stat test_output_ma(isl_ctx *ctx)8759{8760	char *str;8761	isl_bool equal;8762	isl_aff *aff;8763	isl_multi_aff *ma, *ma2;8764 8765	ma = isl_multi_aff_read_from_str(ctx, "{ [a, b] -> [a + b] }");8766	aff = isl_aff_read_from_str(ctx, "{ [c, d] -> [c + d] }");8767	ma = isl_multi_aff_set_aff(ma, 0, aff);8768	str = isl_multi_aff_to_str(ma);8769	ma2 = isl_multi_aff_read_from_str(ctx, str);8770	free(str);8771	equal = isl_multi_aff_plain_is_equal(ma, ma2);8772	isl_multi_aff_free(ma2);8773	isl_multi_aff_free(ma);8774 8775	if (equal < 0)8776		return isl_stat_error;8777	if (!equal)8778		isl_die(ctx, isl_error_unknown, "bad conversion",8779			return isl_stat_error);8780 8781	return isl_stat_ok;8782}8783 8784/* Check that an isl_multi_pw_aff is printed using a consistent space.8785 */8786static isl_stat test_output_mpa(isl_ctx *ctx)8787{8788	char *str;8789	isl_bool equal;8790	isl_pw_aff *pa;8791	isl_multi_pw_aff *mpa, *mpa2;8792 8793	mpa = isl_multi_pw_aff_read_from_str(ctx, "{ [a, b] -> [a + b] }");8794	pa = isl_pw_aff_read_from_str(ctx, "{ [c, d] -> [c + d] }");8795	mpa = isl_multi_pw_aff_set_pw_aff(mpa, 0, pa);8796	str = isl_multi_pw_aff_to_str(mpa);8797	mpa2 = isl_multi_pw_aff_read_from_str(ctx, str);8798	free(str);8799	equal = isl_multi_pw_aff_plain_is_equal(mpa, mpa2);8800	isl_multi_pw_aff_free(mpa2);8801	isl_multi_pw_aff_free(mpa);8802 8803	if (equal < 0)8804		return isl_stat_error;8805	if (!equal)8806		isl_die(ctx, isl_error_unknown, "bad conversion",8807			return isl_stat_error);8808 8809	return isl_stat_ok;8810}8811 8812int test_output(isl_ctx *ctx)8813{8814	char *s;8815	const char *str;8816	isl_pw_aff *pa;8817	isl_printer *p;8818	int equal;8819 8820	if (test_output_set(ctx) < 0)8821		return -1;8822	if (test_output_ma(ctx) < 0)8823		return -1;8824	if (test_output_mpa(ctx) < 0)8825		return -1;8826 8827	str = "[x] -> { [1] : x % 4 <= 2; [2] : x = 3 }";8828	pa = isl_pw_aff_read_from_str(ctx, str);8829 8830	p = isl_printer_to_str(ctx);8831	p = isl_printer_set_output_format(p, ISL_FORMAT_C);8832	p = isl_printer_print_pw_aff(p, pa);8833	s = isl_printer_get_str(p);8834	isl_printer_free(p);8835	isl_pw_aff_free(pa);8836	if (!s)8837		equal = -1;8838	else8839		equal = !strcmp(s, "4 * floord(x, 4) + 2 >= x ? 1 : 2");8840	free(s);8841	if (equal < 0)8842		return -1;8843	if (!equal)8844		isl_die(ctx, isl_error_unknown, "unexpected result", return -1);8845 8846	return 0;8847}8848 8849int test_sample(isl_ctx *ctx)8850{8851	const char *str;8852	isl_basic_set *bset1, *bset2;8853	int empty, subset;8854 8855	str = "{ [a, b, c, d, e, f, g, h, i, j, k] : "8856	    "3i >= 1073741823b - c - 1073741823e + f and c >= 0 and "8857	    "3i >= -1 + 3221225466b + c + d - 3221225466e - f and "8858	    "2e >= a - b and 3e <= 2a and 3k <= -a and f <= -1 + a and "8859	    "3i <= 4 - a + 4b + 2c - e - 2f and 3k <= -a + c - f and "8860	    "3h >= -2 + a and 3g >= -3 - a and 3k >= -2 - a and "8861	    "3i >= -2 - a - 2c + 3e + 2f and 3h <= a + c - f and "8862	    "3h >= a + 2147483646b + 2c - 2147483646e - 2f and "8863	    "3g <= -1 - a and 3i <= 1 + c + d - f and a <= 1073741823 and "8864	    "f >= 1 - a + 1073741822b + c + d - 1073741822e and "8865	    "3i >= 1 + 2b - 2c + e + 2f + 3g and "8866	    "1073741822f <= 1073741822 - a + 1073741821b + 1073741822c +"8867		"d - 1073741821e and "8868	    "3j <= 3 - a + 3b and 3g <= -2 - 2b + c + d - e - f and "8869	    "3j >= 1 - a + b + 2e and "8870	    "3f >= -3 + a + 3221225462b + 3c + d - 3221225465e and "8871	    "3i <= 4 - a + 4b - e and "8872	    "f <= 1073741822 + 1073741822b - 1073741822e and 3h <= a and "8873	    "f >= 0 and 2e <= 4 - a + 5b - d and 2e <= a - b + d and "8874	    "c <= -1 + a and 3i >= -2 - a + 3e and "8875	    "1073741822e <= 1073741823 - a + 1073741822b + c and "8876	    "3g >= -4 + 3221225464b + 3c + d - 3221225467e - 3f and "8877	    "3i >= -1 + 3221225466b + 3c + d - 3221225466e - 3f and "8878	    "1073741823e >= 1 + 1073741823b - d and "8879	    "3i >= 1073741823b + c - 1073741823e - f and "8880	    "3i >= 1 + 2b + e + 3g }";8881	bset1 = isl_basic_set_read_from_str(ctx, str);8882	bset2 = isl_basic_set_sample(isl_basic_set_copy(bset1));8883	empty = isl_basic_set_is_empty(bset2);8884	subset = isl_basic_set_is_subset(bset2, bset1);8885	isl_basic_set_free(bset1);8886	isl_basic_set_free(bset2);8887	if (empty < 0 || subset < 0)8888		return -1;8889	if (empty)8890		isl_die(ctx, isl_error_unknown, "point not found", return -1);8891	if (!subset)8892		isl_die(ctx, isl_error_unknown, "bad point found", return -1);8893 8894	return 0;8895}8896 8897/* Perform a projection on a basic set that is known to be empty8898 * but that has not been assigned a canonical representation.8899 * Earlier versions of isl would run into a stack overflow8900 * on this example.8901 */8902static int test_empty_projection(isl_ctx *ctx)8903{8904	const char *str;8905	isl_bool empty;8906	isl_basic_set *bset;8907 8908	str = "{ [a, b, c, d, e, f, g, h] : 5f = 1 + 4a - b + 5c - d - 2e and "8909		"3h = 2 + b + c and 14c >= 9 - 3a + 25b and "8910		"4c <= 50 - 3a + 23b and 6b <= -39 + a and "8911		"9g >= -6 + 3a + b + c and e < a + b - 2d and "8912		"7d >= -5 + 2a + 2b and 5g >= -14 + a - 4b + d + 2e and "8913		"9g <= -28 - 5b - 2c + 3d + 6e }";8914	bset = isl_basic_set_read_from_str(ctx, str);8915	empty = isl_basic_set_is_empty(bset);8916	bset = isl_basic_set_params(bset);8917	isl_basic_set_free(bset);8918 8919	if (empty < 0)8920		return -1;8921 8922	return 0;8923}8924 8925int test_slice(isl_ctx *ctx)8926{8927	const char *str;8928	isl_map *map;8929	int equal;8930 8931	str = "{ [i] -> [j] }";8932	map = isl_map_read_from_str(ctx, str);8933	map = isl_map_equate(map, isl_dim_in, 0, isl_dim_out, 0);8934	equal = map_check_equal(map, "{ [i] -> [i] }");8935	isl_map_free(map);8936	if (equal < 0)8937		return -1;8938 8939	str = "{ [i] -> [j] }";8940	map = isl_map_read_from_str(ctx, str);8941	map = isl_map_equate(map, isl_dim_in, 0, isl_dim_in, 0);8942	equal = map_check_equal(map, "{ [i] -> [j] }");8943	isl_map_free(map);8944	if (equal < 0)8945		return -1;8946 8947	str = "{ [i] -> [j] }";8948	map = isl_map_read_from_str(ctx, str);8949	map = isl_map_oppose(map, isl_dim_in, 0, isl_dim_out, 0);8950	equal = map_check_equal(map, "{ [i] -> [-i] }");8951	isl_map_free(map);8952	if (equal < 0)8953		return -1;8954 8955	str = "{ [i] -> [j] }";8956	map = isl_map_read_from_str(ctx, str);8957	map = isl_map_oppose(map, isl_dim_in, 0, isl_dim_in, 0);8958	equal = map_check_equal(map, "{ [0] -> [j] }");8959	isl_map_free(map);8960	if (equal < 0)8961		return -1;8962 8963	str = "{ [i] -> [j] }";8964	map = isl_map_read_from_str(ctx, str);8965	map = isl_map_order_gt(map, isl_dim_in, 0, isl_dim_out, 0);8966	equal = map_check_equal(map, "{ [i] -> [j] : i > j }");8967	isl_map_free(map);8968	if (equal < 0)8969		return -1;8970 8971	str = "{ [i] -> [j] }";8972	map = isl_map_read_from_str(ctx, str);8973	map = isl_map_order_gt(map, isl_dim_in, 0, isl_dim_in, 0);8974	equal = map_check_equal(map, "{ [i] -> [j] : false }");8975	isl_map_free(map);8976	if (equal < 0)8977		return -1;8978 8979	return 0;8980}8981 8982int test_eliminate(isl_ctx *ctx)8983{8984	const char *str;8985	isl_map *map;8986	int equal;8987 8988	str = "{ [i] -> [j] : i = 2j }";8989	map = isl_map_read_from_str(ctx, str);8990	map = isl_map_eliminate(map, isl_dim_out, 0, 1);8991	equal = map_check_equal(map, "{ [i] -> [j] : exists a : i = 2a }");8992	isl_map_free(map);8993	if (equal < 0)8994		return -1;8995 8996	return 0;8997}8998 8999/* Check basic functionality of isl_map_deltas_map.9000 */9001static int test_deltas_map(isl_ctx *ctx)9002{9003	const char *str;9004	isl_map *map;9005	int equal;9006 9007	str = "{ A[i] -> A[i + 1] }";9008	map = isl_map_read_from_str(ctx, str);9009	map = isl_map_deltas_map(map);9010	equal = map_check_equal(map, "{ [A[i] -> A[i + 1]] -> A[1] }");9011	isl_map_free(map);9012	if (equal < 0)9013		return -1;9014 9015	return 0;9016}9017 9018/* Check that isl_set_dim_residue_class detects that the values of j9019 * in the set below are all odd and that it does not detect any spurious9020 * strides.9021 */9022static int test_residue_class(isl_ctx *ctx)9023{9024	const char *str;9025	isl_set *set;9026	isl_int m, r;9027	isl_stat res;9028 9029	str = "{ [i,j] : j = 4 i + 1 and 0 <= i <= 100; "9030		"[i,j] : j = 4 i + 3 and 500 <= i <= 600 }";9031	set = isl_set_read_from_str(ctx, str);9032	isl_int_init(m);9033	isl_int_init(r);9034	res = isl_set_dim_residue_class(set, 1, &m, &r);9035	if (res >= 0 &&9036	    (isl_int_cmp_si(m, 2) != 0 || isl_int_cmp_si(r, 1) != 0))9037		isl_die(ctx, isl_error_unknown, "incorrect residue class",9038			res = isl_stat_error);9039	isl_int_clear(r);9040	isl_int_clear(m);9041	isl_set_free(set);9042 9043	return res;9044}9045 9046static int test_align_parameters_1(isl_ctx *ctx)9047{9048	const char *str;9049	isl_space *space;9050	isl_multi_aff *ma1, *ma2;9051	int equal;9052 9053	str = "{ A[B[] -> C[]] -> D[E[] -> F[]] }";9054	ma1 = isl_multi_aff_read_from_str(ctx, str);9055 9056	space = isl_space_params_alloc(ctx, 1);9057	space = isl_space_set_dim_name(space, isl_dim_param, 0, "N");9058	ma1 = isl_multi_aff_align_params(ma1, space);9059 9060	str = "[N] -> { A[B[] -> C[]] -> D[E[] -> F[]] }";9061	ma2 = isl_multi_aff_read_from_str(ctx, str);9062 9063	equal = isl_multi_aff_plain_is_equal(ma1, ma2);9064 9065	isl_multi_aff_free(ma1);9066	isl_multi_aff_free(ma2);9067 9068	if (equal < 0)9069		return -1;9070	if (!equal)9071		isl_die(ctx, isl_error_unknown,9072			"result not as expected", return -1);9073 9074	return 0;9075}9076 9077/* Check the isl_multi_*_from_*_list operation in case inputs9078 * have unaligned parameters.9079 * In particular, older versions of isl would simply fail9080 * (without printing any error message).9081 */9082static isl_stat test_align_parameters_2(isl_ctx *ctx)9083{9084	isl_space *space;9085	isl_map *map;9086	isl_aff *aff;9087	isl_multi_aff *ma;9088 9089	map = isl_map_read_from_str(ctx, "{ A[] -> M[x] }");9090	space = isl_map_get_space(map);9091	isl_map_free(map);9092 9093	aff = isl_aff_read_from_str(ctx, "[N] -> { A[] -> [N] }");9094	ma = isl_multi_aff_from_aff_list(space, isl_aff_list_from_aff(aff));9095	isl_multi_aff_free(ma);9096 9097	if (!ma)9098		return isl_stat_error;9099	return isl_stat_ok;9100}9101 9102/* Perform basic parameter alignment tests.9103 */9104static int test_align_parameters(isl_ctx *ctx)9105{9106	if (test_align_parameters_1(ctx) < 0)9107		return -1;9108	if (test_align_parameters_2(ctx) < 0)9109		return -1;9110 9111	return 0;9112}9113 9114/* Check that isl_*_drop_unused_params actually drops the unused parameters9115 * by comparing the result using isl_*_plain_is_equal.9116 * Note that this assumes that isl_*_plain_is_equal does not consider9117 * objects that only differ by unused parameters to be equal.9118 */9119int test_drop_unused_parameters(isl_ctx *ctx)9120{9121	const char *str_with, *str_without;9122	isl_basic_set *bset1, *bset2;9123	isl_set *set1, *set2;9124	isl_pw_aff *pwa1, *pwa2;9125	int equal;9126 9127	str_with = "[n, m, o] -> { [m] }";9128	str_without = "[m] -> { [m] }";9129 9130	bset1 = isl_basic_set_read_from_str(ctx, str_with);9131	bset2 = isl_basic_set_read_from_str(ctx, str_without);9132	bset1 = isl_basic_set_drop_unused_params(bset1);9133	equal = isl_basic_set_plain_is_equal(bset1, bset2);9134	isl_basic_set_free(bset1);9135	isl_basic_set_free(bset2);9136 9137	if (equal < 0)9138		return -1;9139	if (!equal)9140		isl_die(ctx, isl_error_unknown,9141			"result not as expected", return -1);9142 9143	set1 = isl_set_read_from_str(ctx, str_with);9144	set2 = isl_set_read_from_str(ctx, str_without);9145	set1 = isl_set_drop_unused_params(set1);9146	equal = isl_set_plain_is_equal(set1, set2);9147	isl_set_free(set1);9148	isl_set_free(set2);9149 9150	if (equal < 0)9151		return -1;9152	if (!equal)9153		isl_die(ctx, isl_error_unknown,9154			"result not as expected", return -1);9155 9156	pwa1 = isl_pw_aff_read_from_str(ctx, str_with);9157	pwa2 = isl_pw_aff_read_from_str(ctx, str_without);9158	pwa1 = isl_pw_aff_drop_unused_params(pwa1);9159	equal = isl_pw_aff_plain_is_equal(pwa1, pwa2);9160	isl_pw_aff_free(pwa1);9161	isl_pw_aff_free(pwa2);9162 9163	if (equal < 0)9164		return -1;9165	if (!equal)9166		isl_die(ctx, isl_error_unknown,9167			"result not as expected", return -1);9168 9169	return 0;9170}9171 9172static int test_list(isl_ctx *ctx)9173{9174	isl_id *a, *b, *c, *d, *id;9175	isl_id_list *list;9176	isl_size n;9177	int ok;9178 9179	a = isl_id_alloc(ctx, "a", NULL);9180	b = isl_id_alloc(ctx, "b", NULL);9181	c = isl_id_alloc(ctx, "c", NULL);9182	d = isl_id_alloc(ctx, "d", NULL);9183 9184	list = isl_id_list_alloc(ctx, 4);9185	list = isl_id_list_add(list, b);9186	list = isl_id_list_insert(list, 0, a);9187	list = isl_id_list_add(list, c);9188	list = isl_id_list_add(list, d);9189	list = isl_id_list_drop(list, 1, 1);9190 9191	n = isl_id_list_n_id(list);9192	if (n < 0)9193		return -1;9194	if (n != 3) {9195		isl_id_list_free(list);9196		isl_die(ctx, isl_error_unknown,9197			"unexpected number of elements in list", return -1);9198	}9199 9200	id = isl_id_list_get_id(list, 0);9201	ok = id == a;9202	isl_id_free(id);9203	id = isl_id_list_get_id(list, 1);9204	ok = ok && id == c;9205	isl_id_free(id);9206	id = isl_id_list_get_id(list, 2);9207	ok = ok && id == d;9208	isl_id_free(id);9209 9210	isl_id_list_free(list);9211 9212	if (!ok)9213		isl_die(ctx, isl_error_unknown,9214			"unexpected elements in list", return -1);9215 9216	return 0;9217}9218 9219/* Check the conversion from an isl_multi_aff to an isl_basic_set.9220 */9221static isl_stat test_ma_conversion(isl_ctx *ctx)9222{9223	const char *str;9224	isl_bool equal;9225	isl_multi_aff *ma;9226	isl_basic_set *bset1, *bset2;9227 9228	str = "[N] -> { A[0, N + 1] }";9229	ma = isl_multi_aff_read_from_str(ctx, str);9230	bset1 = isl_basic_set_read_from_str(ctx, str);9231	bset2 = isl_basic_set_from_multi_aff(ma);9232	equal = isl_basic_set_is_equal(bset1, bset2);9233	isl_basic_set_free(bset1);9234	isl_basic_set_free(bset2);9235	if (equal < 0)9236		return isl_stat_error;9237	if (!equal)9238		isl_die(ctx, isl_error_unknown, "bad conversion",9239			return isl_stat_error);9240	return isl_stat_ok;9241}9242 9243const char *set_conversion_tests[] = {9244	"[N] -> { [i] : N - 1 <= 2 i <= N }",9245	"[N] -> { [i] : exists a : i = 4 a and N - 1 <= i <= N }",9246	"[N] -> { [i,j] : exists a : i = 4 a and N - 1 <= i, 2j <= N }",9247	"[N] -> { [[i]->[j]] : exists a : i = 4 a and N - 1 <= i, 2j <= N }",9248	"[N] -> { [3*floor(N/2) + 5*floor(N/3)] }",9249	"[a, b] -> { [c, d] : (4*floor((-a + c)/4) = -a + c and "9250			"32*floor((-b + d)/32) = -b + d and 5 <= c <= 8 and "9251			"-3 + c <= d <= 28 + c) }",9252};9253 9254/* Check that converting from isl_set to isl_pw_multi_aff and back9255 * to isl_set produces the original isl_set.9256 */9257static int test_set_conversion(isl_ctx *ctx)9258{9259	int i;9260	const char *str;9261	isl_set *set1, *set2;9262	isl_pw_multi_aff *pma;9263	int equal;9264 9265	for (i = 0; i < ARRAY_SIZE(set_conversion_tests); ++i) {9266		str = set_conversion_tests[i];9267		set1 = isl_set_read_from_str(ctx, str);9268		pma = isl_pw_multi_aff_from_set(isl_set_copy(set1));9269		set2 = isl_set_from_pw_multi_aff(pma);9270		equal = isl_set_is_equal(set1, set2);9271		isl_set_free(set1);9272		isl_set_free(set2);9273 9274		if (equal < 0)9275			return -1;9276		if (!equal)9277			isl_die(ctx, isl_error_unknown, "bad conversion",9278				return -1);9279	}9280 9281	return 0;9282}9283 9284const char *conversion_tests[] = {9285	"{ [a, b, c, d] -> s0[a, b, e, f] : "9286	    "exists (e0 = [(a - 2c)/3], e1 = [(-4 + b - 5d)/9], "9287	    "e2 = [(-d + f)/9]: 3e0 = a - 2c and 9e1 = -4 + b - 5d and "9288	    "9e2 = -d + f and f >= 0 and f <= 8 and 9e >= -5 - 2a and "9289	    "9e <= -2 - 2a) }",9290	"{ [a, b] -> [c] : exists (e0 = floor((-a - b + c)/5): "9291	    "5e0 = -a - b + c and c >= -a and c <= 4 - a) }",9292	"{ [a, b] -> [c] : exists d : 18 * d = -3 - a + 2c and 1 <= c <= 3 }",9293};9294 9295/* Check that converting from isl_map to isl_pw_multi_aff and back9296 * to isl_map produces the original isl_map.9297 */9298static int test_map_conversion(isl_ctx *ctx)9299{9300	int i;9301	isl_map *map1, *map2;9302	isl_pw_multi_aff *pma;9303	int equal;9304 9305	for (i = 0; i < ARRAY_SIZE(conversion_tests); ++i) {9306		map1 = isl_map_read_from_str(ctx, conversion_tests[i]);9307		pma = isl_pw_multi_aff_from_map(isl_map_copy(map1));9308		map2 = isl_map_from_pw_multi_aff(pma);9309		equal = isl_map_is_equal(map1, map2);9310		isl_map_free(map1);9311		isl_map_free(map2);9312 9313		if (equal < 0)9314			return -1;9315		if (!equal)9316			isl_die(ctx, isl_error_unknown, "bad conversion",9317				return -1);9318	}9319 9320	return 0;9321}9322 9323/* Descriptions of isl_pw_multi_aff objects for testing conversion9324 * to isl_multi_pw_aff and back.9325 */9326const char *mpa_conversion_tests[] = {9327	"{ [x] -> A[x] }",9328	"{ [x] -> A[x] : x >= 0 }",9329	"{ [x] -> A[x] : x >= 0; [x] -> A[-x] : x < 0 }",9330	"{ [x] -> A[x, x + 1] }",9331	"{ [x] -> A[] }",9332	"{ [x] -> A[] : x >= 0 }",9333};9334 9335/* Check that conversion from isl_pw_multi_aff to isl_multi_pw_aff and9336 * back to isl_pw_multi_aff preserves the original meaning.9337 */9338static int test_mpa_conversion(isl_ctx *ctx)9339{9340	int i;9341	isl_pw_multi_aff *pma1, *pma2;9342	isl_multi_pw_aff *mpa;9343	int equal;9344 9345	for (i = 0; i < ARRAY_SIZE(mpa_conversion_tests); ++i) {9346		const char *str;9347		str = mpa_conversion_tests[i];9348		pma1 = isl_pw_multi_aff_read_from_str(ctx, str);9349		pma2 = isl_pw_multi_aff_copy(pma1);9350		mpa = isl_multi_pw_aff_from_pw_multi_aff(pma1);9351		pma1 = isl_pw_multi_aff_from_multi_pw_aff(mpa);9352		equal = isl_pw_multi_aff_plain_is_equal(pma1, pma2);9353		isl_pw_multi_aff_free(pma1);9354		isl_pw_multi_aff_free(pma2);9355 9356		if (equal < 0)9357			return -1;9358		if (!equal)9359			isl_die(ctx, isl_error_unknown, "bad conversion",9360				return -1);9361	}9362 9363	return 0;9364}9365 9366/* Descriptions of union maps that should be convertible9367 * to an isl_multi_union_pw_aff.9368 */9369const char *umap_mupa_conversion_tests[] = {9370	"{ [a, b, c, d] -> s0[a, b, e, f] : "9371	    "exists (e0 = [(a - 2c)/3], e1 = [(-4 + b - 5d)/9], "9372	    "e2 = [(-d + f)/9]: 3e0 = a - 2c and 9e1 = -4 + b - 5d and "9373	    "9e2 = -d + f and f >= 0 and f <= 8 and 9e >= -5 - 2a and "9374	    "9e <= -2 - 2a) }",9375	"{ [a, b] -> [c] : exists (e0 = floor((-a - b + c)/5): "9376	    "5e0 = -a - b + c and c >= -a and c <= 4 - a) }",9377	"{ [a, b] -> [c] : exists d : 18 * d = -3 - a + 2c and 1 <= c <= 3 }",9378	"{ A[] -> B[0]; C[] -> B[1] }",9379	"{ A[] -> B[]; C[] -> B[] }",9380};9381 9382/* Check that converting from isl_union_map to isl_multi_union_pw_aff and back9383 * to isl_union_map produces the original isl_union_map.9384 */9385static int test_union_map_mupa_conversion(isl_ctx *ctx)9386{9387	int i;9388	isl_union_map *umap1, *umap2;9389	isl_multi_union_pw_aff *mupa;9390	int equal;9391 9392	for (i = 0; i < ARRAY_SIZE(umap_mupa_conversion_tests); ++i) {9393		const char *str;9394		str = umap_mupa_conversion_tests[i];9395		umap1 = isl_union_map_read_from_str(ctx, str);9396		umap2 = isl_union_map_copy(umap1);9397		mupa = isl_multi_union_pw_aff_from_union_map(umap2);9398		umap2 = isl_union_map_from_multi_union_pw_aff(mupa);9399		equal = isl_union_map_is_equal(umap1, umap2);9400		isl_union_map_free(umap1);9401		isl_union_map_free(umap2);9402 9403		if (equal < 0)9404			return -1;9405		if (!equal)9406			isl_die(ctx, isl_error_unknown, "bad conversion",9407				return -1);9408	}9409 9410	return 0;9411}9412 9413static int test_conversion(isl_ctx *ctx)9414{9415	if (test_ma_conversion(ctx) < 0)9416		return -1;9417	if (test_set_conversion(ctx) < 0)9418		return -1;9419	if (test_map_conversion(ctx) < 0)9420		return -1;9421	if (test_mpa_conversion(ctx) < 0)9422		return -1;9423	if (test_union_map_mupa_conversion(ctx) < 0)9424		return -1;9425	return 0;9426}9427 9428/* Check that isl_basic_map_curry does not modify input.9429 */9430static int test_curry(isl_ctx *ctx)9431{9432	const char *str;9433	isl_basic_map *bmap1, *bmap2;9434	int equal;9435 9436	str = "{ [A[] -> B[]] -> C[] }";9437	bmap1 = isl_basic_map_read_from_str(ctx, str);9438	bmap2 = isl_basic_map_curry(isl_basic_map_copy(bmap1));9439	equal = isl_basic_map_is_equal(bmap1, bmap2);9440	isl_basic_map_free(bmap1);9441	isl_basic_map_free(bmap2);9442 9443	if (equal < 0)9444		return -1;9445	if (equal)9446		isl_die(ctx, isl_error_unknown,9447			"curried map should not be equal to original",9448			return -1);9449 9450	return 0;9451}9452 9453struct {9454	const char *ma1;9455	const char *ma;9456	const char *res;9457} pullback_tests[] = {9458	{ "{ B[i,j] -> C[i + 2j] }" , "{ A[a,b] -> B[b,a] }",9459	  "{ A[a,b] -> C[b + 2a] }" },9460	{ "{ B[i] -> C[2i] }", "{ A[a] -> B[(a)/2] }", "{ A[a] -> C[a] }" },9461	{ "{ B[i] -> C[(i)/2] }", "{ A[a] -> B[2a] }", "{ A[a] -> C[a] }" },9462	{ "{ B[i] -> C[(i)/2] }", "{ A[a] -> B[(a)/3] }",9463	  "{ A[a] -> C[(a)/6] }" },9464	{ "{ B[i] -> C[2i] }", "{ A[a] -> B[5a] }", "{ A[a] -> C[10a] }" },9465	{ "{ B[i] -> C[2i] }", "{ A[a] -> B[(a)/3] }",9466	  "{ A[a] -> C[(2a)/3] }" },9467	{ "{ B[i,j] -> C[i + j] }", "{ A[a] -> B[a,a] }", "{ A[a] -> C[2a] }"},9468	{ "{ B[a] -> C[a,a] }", "{ A[i,j] -> B[i + j] }",9469	  "{ A[i,j] -> C[i + j, i + j] }"},9470	{ "{ B[i] -> C[([i/2])] }", "{ B[5] }", "{ C[2] }" },9471	{ "[n] -> { B[i,j] -> C[([i/2]) + 2j] }",9472	  "[n] -> { B[n,[n/3]] }", "[n] -> { C[([n/2]) + 2*[n/3]] }", },9473	{ "{ [i, j] -> [floor((i)/4) + floor((2*i+j)/5)] }",9474	  "{ [i, j] -> [floor((i)/3), j] }",9475	  "{ [i, j] -> [(floor((i)/12) + floor((j + 2*floor((i)/3))/5))] }" },9476};9477 9478static int test_pullback(isl_ctx *ctx)9479{9480	int i;9481	isl_multi_aff *ma1, *ma2;9482	isl_multi_aff *ma;9483	int equal;9484 9485	for (i = 0; i < ARRAY_SIZE(pullback_tests); ++i) {9486		ma1 = isl_multi_aff_read_from_str(ctx, pullback_tests[i].ma1);9487		ma = isl_multi_aff_read_from_str(ctx, pullback_tests[i].ma);9488		ma2 = isl_multi_aff_read_from_str(ctx, pullback_tests[i].res);9489		ma1 = isl_multi_aff_pullback_multi_aff(ma1, ma);9490		equal = isl_multi_aff_plain_is_equal(ma1, ma2);9491		isl_multi_aff_free(ma1);9492		isl_multi_aff_free(ma2);9493		if (equal < 0)9494			return -1;9495		if (!equal)9496			isl_die(ctx, isl_error_unknown, "bad pullback",9497				return -1);9498	}9499 9500	return 0;9501}9502 9503/* Check that negation is printed correctly and that equal expressions9504 * are correctly identified.9505 */9506static int test_ast(isl_ctx *ctx)9507{9508	isl_ast_expr *expr, *expr1, *expr2, *expr3;9509	char *str;9510	int ok, equal;9511 9512	expr1 = isl_ast_expr_from_id(isl_id_alloc(ctx, "A", NULL));9513	expr2 = isl_ast_expr_from_id(isl_id_alloc(ctx, "B", NULL));9514	expr = isl_ast_expr_add(expr1, expr2);9515	expr2 = isl_ast_expr_copy(expr);9516	expr = isl_ast_expr_neg(expr);9517	expr2 = isl_ast_expr_neg(expr2);9518	equal = isl_ast_expr_is_equal(expr, expr2);9519	str = isl_ast_expr_to_C_str(expr);9520	ok = str ? !strcmp(str, "-(A + B)") : -1;9521	free(str);9522	isl_ast_expr_free(expr);9523	isl_ast_expr_free(expr2);9524 9525	if (ok < 0 || equal < 0)9526		return -1;9527	if (!equal)9528		isl_die(ctx, isl_error_unknown,9529			"equal expressions not considered equal", return -1);9530	if (!ok)9531		isl_die(ctx, isl_error_unknown,9532			"isl_ast_expr printed incorrectly", return -1);9533 9534	expr1 = isl_ast_expr_from_id(isl_id_alloc(ctx, "A", NULL));9535	expr2 = isl_ast_expr_from_id(isl_id_alloc(ctx, "B", NULL));9536	expr = isl_ast_expr_add(expr1, expr2);9537	expr3 = isl_ast_expr_from_id(isl_id_alloc(ctx, "C", NULL));9538	expr = isl_ast_expr_sub(expr3, expr);9539	str = isl_ast_expr_to_C_str(expr);9540	ok = str ? !strcmp(str, "C - (A + B)") : -1;9541	free(str);9542	isl_ast_expr_free(expr);9543 9544	if (ok < 0)9545		return -1;9546	if (!ok)9547		isl_die(ctx, isl_error_unknown,9548			"isl_ast_expr printed incorrectly", return -1);9549 9550	return 0;9551}9552 9553/* Check that isl_ast_build_expr_from_set returns a valid expression9554 * for an empty set.  Note that isl_ast_build_expr_from_set getting9555 * called on an empty set probably indicates a bug in the caller.9556 */9557static int test_ast_build(isl_ctx *ctx)9558{9559	isl_set *set;9560	isl_ast_build *build;9561	isl_ast_expr *expr;9562 9563	set = isl_set_universe(isl_space_params_alloc(ctx, 0));9564	build = isl_ast_build_from_context(set);9565 9566	set = isl_set_empty(isl_space_params_alloc(ctx, 0));9567	expr = isl_ast_build_expr_from_set(build, set);9568 9569	isl_ast_expr_free(expr);9570	isl_ast_build_free(build);9571 9572	if (!expr)9573		return -1;9574 9575	return 0;9576}9577 9578/* Internal data structure for before_for and after_for callbacks.9579 *9580 * depth is the current depth9581 * before is the number of times before_for has been called9582 * after is the number of times after_for has been called9583 */9584struct isl_test_codegen_data {9585	int depth;9586	int before;9587	int after;9588};9589 9590/* This function is called before each for loop in the AST generated9591 * from test_ast_gen1.9592 *9593 * Increment the number of calls and the depth.9594 * Check that the space returned by isl_ast_build_get_schedule_space9595 * matches the target space of the schedule returned by9596 * isl_ast_build_get_schedule.9597 * Return an isl_id that is checked by the corresponding call9598 * to after_for.9599 */9600static __isl_give isl_id *before_for(__isl_keep isl_ast_build *build,9601	void *user)9602{9603	struct isl_test_codegen_data *data = user;9604	isl_ctx *ctx;9605	isl_space *space;9606	isl_union_map *schedule;9607	isl_union_set *uset;9608	isl_set *set;9609	isl_bool empty;9610	isl_size n;9611	char name[] = "d0";9612 9613	ctx = isl_ast_build_get_ctx(build);9614 9615	if (data->before >= 3)9616		isl_die(ctx, isl_error_unknown,9617			"unexpected number of for nodes", return NULL);9618	if (data->depth < 0 || data->depth >= 2)9619		isl_die(ctx, isl_error_unknown,9620			"unexpected depth", return NULL);9621 9622	snprintf(name, sizeof(name), "d%d", data->depth);9623	data->before++;9624	data->depth++;9625 9626	schedule = isl_ast_build_get_schedule(build);9627	uset = isl_union_map_range(schedule);9628	n = isl_union_set_n_set(uset);9629	if (n != 1) {9630		isl_union_set_free(uset);9631		if (n < 0)9632			return NULL;9633		isl_die(ctx, isl_error_unknown,9634			"expecting single range space", return NULL);9635	}9636 9637	space = isl_ast_build_get_schedule_space(build);9638	set = isl_union_set_extract_set(uset, space);9639	isl_union_set_free(uset);9640	empty = isl_set_is_empty(set);9641	isl_set_free(set);9642 9643	if (empty < 0)9644		return NULL;9645	if (empty)9646		isl_die(ctx, isl_error_unknown,9647			"spaces don't match", return NULL);9648 9649	return isl_id_alloc(ctx, name, NULL);9650}9651 9652/* This function is called after each for loop in the AST generated9653 * from test_ast_gen1.9654 *9655 * Increment the number of calls and decrement the depth.9656 * Check that the annotation attached to the node matches9657 * the isl_id returned by the corresponding call to before_for.9658 */9659static __isl_give isl_ast_node *after_for(__isl_take isl_ast_node *node,9660	__isl_keep isl_ast_build *build, void *user)9661{9662	struct isl_test_codegen_data *data = user;9663	isl_id *id;9664	const char *name;9665	int valid;9666 9667	data->after++;9668	data->depth--;9669 9670	if (data->after > data->before)9671		isl_die(isl_ast_node_get_ctx(node), isl_error_unknown,9672			"mismatch in number of for nodes",9673			return isl_ast_node_free(node));9674 9675	id = isl_ast_node_get_annotation(node);9676	if (!id)9677		isl_die(isl_ast_node_get_ctx(node), isl_error_unknown,9678			"missing annotation", return isl_ast_node_free(node));9679 9680	name = isl_id_get_name(id);9681	valid = name && atoi(name + 1) == data->depth;9682	isl_id_free(id);9683 9684	if (!valid)9685		isl_die(isl_ast_node_get_ctx(node), isl_error_unknown,9686			"wrong annotation", return isl_ast_node_free(node));9687 9688	return node;9689}9690 9691/* This function is called after node in the AST generated9692 * from test_ast_gen1.9693 *9694 * Increment the count in "user" if this is a for node and9695 * return true to indicate that descendant should also be visited.9696 */9697static isl_bool count_for(__isl_keep isl_ast_node *node, void *user)9698{9699	int *count = user;9700 9701	if (isl_ast_node_get_type(node) == isl_ast_node_for)9702		++*count;9703 9704	return isl_bool_true;9705}9706 9707/* If "node" is a block node, then replace it by its first child.9708 */9709static __isl_give isl_ast_node *select_first(__isl_take isl_ast_node *node,9710	void *user)9711{9712	isl_ast_node_list *children;9713	isl_ast_node *child;9714 9715	if (isl_ast_node_get_type(node) != isl_ast_node_block)9716		return node;9717 9718	children = isl_ast_node_block_get_children(node);9719	child = isl_ast_node_list_get_at(children, 0);9720	isl_ast_node_list_free(children);9721	isl_ast_node_free(node);9722 9723	return child;9724}9725 9726/* Check that the before_each_for and after_each_for callbacks9727 * are called for each for loop in the generated code,9728 * that they are called in the right order and that the isl_id9729 * returned from the before_each_for callback is attached to9730 * the isl_ast_node passed to the corresponding after_each_for call.9731 *9732 * Additionally, check the basic functionality of9733 * isl_ast_node_foreach_descendant_top_down by counting the number9734 * of for loops in the resulting AST,9735 * as well as that of isl_ast_node_map_descendant_bottom_up9736 * by replacing the block node by its first child and9737 * counting the number of for loops again.9738 */9739static isl_stat test_ast_gen1(isl_ctx *ctx)9740{9741	int count = 0;9742	int modified_count = 0;9743	const char *str;9744	isl_set *set;9745	isl_union_map *schedule;9746	isl_ast_build *build;9747	isl_ast_node *tree;9748	struct isl_test_codegen_data data;9749 9750	str = "[N] -> { : N >= 10 }";9751	set = isl_set_read_from_str(ctx, str);9752	str = "[N] -> { A[i,j] -> S[8,i,3,j] : 0 <= i,j <= N; "9753		    "B[i,j] -> S[8,j,9,i] : 0 <= i,j <= N }";9754	schedule = isl_union_map_read_from_str(ctx, str);9755 9756	data.before = 0;9757	data.after = 0;9758	data.depth = 0;9759	build = isl_ast_build_from_context(set);9760	build = isl_ast_build_set_before_each_for(build,9761			&before_for, &data);9762	build = isl_ast_build_set_after_each_for(build,9763			&after_for, &data);9764	tree = isl_ast_build_node_from_schedule_map(build, schedule);9765	isl_ast_build_free(build);9766 9767	if (isl_ast_node_foreach_descendant_top_down(tree,9768							&count_for, &count) < 0)9769		tree = isl_ast_node_free(tree);9770 9771	tree = isl_ast_node_map_descendant_bottom_up(tree, &select_first, NULL);9772 9773	if (isl_ast_node_foreach_descendant_top_down(tree, &count_for,9774							&modified_count) < 0)9775		tree = isl_ast_node_free(tree);9776 9777	if (!tree)9778		return isl_stat_error;9779 9780	isl_ast_node_free(tree);9781 9782	if (data.before != 3 || data.after != 3 || count != 3)9783		isl_die(ctx, isl_error_unknown,9784			"unexpected number of for nodes",9785			return isl_stat_error);9786 9787	if (modified_count != 2)9788		isl_die(ctx, isl_error_unknown,9789			"unexpected number of for nodes after changes",9790			return isl_stat_error);9791 9792	return isl_stat_ok;9793}9794 9795/* Check that the AST generator handles domains that are integrally disjoint9796 * but not rationally disjoint.9797 */9798static int test_ast_gen2(isl_ctx *ctx)9799{9800	const char *str;9801	isl_set *set;9802	isl_union_map *schedule;9803	isl_union_map *options;9804	isl_ast_build *build;9805	isl_ast_node *tree;9806 9807	str = "{ A[i,j] -> [i,j] : 0 <= i,j <= 1 }";9808	schedule = isl_union_map_read_from_str(ctx, str);9809	set = isl_set_universe(isl_space_params_alloc(ctx, 0));9810	build = isl_ast_build_from_context(set);9811 9812	str = "{ [i,j] -> atomic[1] : i + j = 1; [i,j] -> unroll[1] : i = j }";9813	options = isl_union_map_read_from_str(ctx, str);9814	build = isl_ast_build_set_options(build, options);9815	tree = isl_ast_build_node_from_schedule_map(build, schedule);9816	isl_ast_build_free(build);9817	if (!tree)9818		return -1;9819	isl_ast_node_free(tree);9820 9821	return 0;9822}9823 9824/* Increment *user on each call.9825 */9826static __isl_give isl_ast_node *count_domains(__isl_take isl_ast_node *node,9827	__isl_keep isl_ast_build *build, void *user)9828{9829	int *n = user;9830 9831	(*n)++;9832 9833	return node;9834}9835 9836/* Test that unrolling tries to minimize the number of instances.9837 * In particular, for the schedule given below, make sure it generates9838 * 3 nodes (rather than 101).9839 */9840static int test_ast_gen3(isl_ctx *ctx)9841{9842	const char *str;9843	isl_set *set;9844	isl_union_map *schedule;9845	isl_union_map *options;9846	isl_ast_build *build;9847	isl_ast_node *tree;9848	int n_domain = 0;9849 9850	str = "[n] -> { A[i] -> [i] : 0 <= i <= 100 and n <= i <= n + 2 }";9851	schedule = isl_union_map_read_from_str(ctx, str);9852	set = isl_set_universe(isl_space_params_alloc(ctx, 0));9853 9854	str = "{ [i] -> unroll[0] }";9855	options = isl_union_map_read_from_str(ctx, str);9856 9857	build = isl_ast_build_from_context(set);9858	build = isl_ast_build_set_options(build, options);9859	build = isl_ast_build_set_at_each_domain(build,9860			&count_domains, &n_domain);9861	tree = isl_ast_build_node_from_schedule_map(build, schedule);9862	isl_ast_build_free(build);9863	if (!tree)9864		return -1;9865 9866	isl_ast_node_free(tree);9867 9868	if (n_domain != 3)9869		isl_die(ctx, isl_error_unknown,9870			"unexpected number of for nodes", return -1);9871 9872	return 0;9873}9874 9875/* Check that if the ast_build_exploit_nested_bounds options is set,9876 * we do not get an outer if node in the generated AST,9877 * while we do get such an outer if node if the options is not set.9878 */9879static int test_ast_gen4(isl_ctx *ctx)9880{9881	const char *str;9882	isl_set *set;9883	isl_union_map *schedule;9884	isl_ast_build *build;9885	isl_ast_node *tree;9886	enum isl_ast_node_type type;9887	int enb;9888 9889	enb = isl_options_get_ast_build_exploit_nested_bounds(ctx);9890	str = "[N,M] -> { A[i,j] -> [i,j] : 0 <= i <= N and 0 <= j <= M }";9891 9892	isl_options_set_ast_build_exploit_nested_bounds(ctx, 1);9893 9894	schedule = isl_union_map_read_from_str(ctx, str);9895	set = isl_set_universe(isl_space_params_alloc(ctx, 0));9896	build = isl_ast_build_from_context(set);9897	tree = isl_ast_build_node_from_schedule_map(build, schedule);9898	isl_ast_build_free(build);9899	if (!tree)9900		return -1;9901 9902	type = isl_ast_node_get_type(tree);9903	isl_ast_node_free(tree);9904 9905	if (type == isl_ast_node_if)9906		isl_die(ctx, isl_error_unknown,9907			"not expecting if node", return -1);9908 9909	isl_options_set_ast_build_exploit_nested_bounds(ctx, 0);9910 9911	schedule = isl_union_map_read_from_str(ctx, str);9912	set = isl_set_universe(isl_space_params_alloc(ctx, 0));9913	build = isl_ast_build_from_context(set);9914	tree = isl_ast_build_node_from_schedule_map(build, schedule);9915	isl_ast_build_free(build);9916	if (!tree)9917		return -1;9918 9919	type = isl_ast_node_get_type(tree);9920	isl_ast_node_free(tree);9921 9922	if (type != isl_ast_node_if)9923		isl_die(ctx, isl_error_unknown,9924			"expecting if node", return -1);9925 9926	isl_options_set_ast_build_exploit_nested_bounds(ctx, enb);9927 9928	return 0;9929}9930 9931/* This function is called for each leaf in the AST generated9932 * from test_ast_gen5.9933 *9934 * We finalize the AST generation by extending the outer schedule9935 * with a zero-dimensional schedule.  If this results in any for loops,9936 * then this means that we did not pass along enough information9937 * about the outer schedule to the inner AST generation.9938 */9939static __isl_give isl_ast_node *create_leaf(__isl_take isl_ast_build *build,9940	void *user)9941{9942	isl_union_map *schedule, *extra;9943	isl_ast_node *tree;9944 9945	schedule = isl_ast_build_get_schedule(build);9946	extra = isl_union_map_copy(schedule);9947	extra = isl_union_map_from_domain(isl_union_map_domain(extra));9948	schedule = isl_union_map_range_product(schedule, extra);9949	tree = isl_ast_build_node_from_schedule_map(build, schedule);9950	isl_ast_build_free(build);9951 9952	if (!tree)9953		return NULL;9954 9955	if (isl_ast_node_get_type(tree) == isl_ast_node_for)9956		isl_die(isl_ast_node_get_ctx(tree), isl_error_unknown,9957			"code should not contain any for loop",9958			return isl_ast_node_free(tree));9959 9960	return tree;9961}9962 9963/* Check that we do not lose any information when going back and9964 * forth between internal and external schedule.9965 *9966 * In particular, we create an AST where we unroll the only9967 * non-constant dimension in the schedule.  We therefore do9968 * not expect any for loops in the AST.  However, older versions9969 * of isl would not pass along enough information about the outer9970 * schedule when performing an inner code generation from a create_leaf9971 * callback, resulting in the inner code generation producing a for loop.9972 */9973static int test_ast_gen5(isl_ctx *ctx)9974{9975	const char *str;9976	isl_set *set;9977	isl_union_map *schedule, *options;9978	isl_ast_build *build;9979	isl_ast_node *tree;9980 9981	str = "{ A[] -> [1, 1, 2]; B[i] -> [1, i, 0] : i >= 1 and i <= 2 }";9982	schedule = isl_union_map_read_from_str(ctx, str);9983 9984	str = "{ [a, b, c] -> unroll[1] : exists (e0 = [(a)/4]: "9985				"4e0 >= -1 + a - b and 4e0 <= -2 + a + b) }";9986	options = isl_union_map_read_from_str(ctx, str);9987 9988	set = isl_set_universe(isl_space_params_alloc(ctx, 0));9989	build = isl_ast_build_from_context(set);9990	build = isl_ast_build_set_options(build, options);9991        build = isl_ast_build_set_create_leaf(build, &create_leaf, NULL);9992	tree = isl_ast_build_node_from_schedule_map(build, schedule);9993	isl_ast_build_free(build);9994	isl_ast_node_free(tree);9995	if (!tree)9996		return -1;9997 9998	return 0;9999}10000 10001/* Check that the expression10002 *10003 *	[n] -> { [n/2] : n <= 0 and n % 2 = 0; [0] : n > 0 }10004 *10005 * is not combined into10006 *10007 *	min(n/2, 0)10008 *10009 * as this would result in n/2 being evaluated in parts of10010 * the definition domain where n is not a multiple of 2.10011 */10012static int test_ast_expr(isl_ctx *ctx)10013{10014	const char *str;10015	isl_pw_aff *pa;10016	isl_ast_build *build;10017	isl_ast_expr *expr;10018	int min_max;10019	int is_min;10020 10021	min_max = isl_options_get_ast_build_detect_min_max(ctx);10022	isl_options_set_ast_build_detect_min_max(ctx, 1);10023 10024	str = "[n] -> { [n/2] : n <= 0 and n % 2 = 0; [0] : n > 0 }";10025	pa = isl_pw_aff_read_from_str(ctx, str);10026	build = isl_ast_build_alloc(ctx);10027	expr = isl_ast_build_expr_from_pw_aff(build, pa);10028	is_min = isl_ast_expr_get_type(expr) == isl_ast_expr_op &&10029		 isl_ast_expr_get_op_type(expr) == isl_ast_expr_op_min;10030	isl_ast_build_free(build);10031	isl_ast_expr_free(expr);10032 10033	isl_options_set_ast_build_detect_min_max(ctx, min_max);10034 10035	if (!expr)10036		return -1;10037	if (is_min)10038		isl_die(ctx, isl_error_unknown,10039			"expressions should not be combined", return -1);10040 10041	return 0;10042}10043 10044static int test_ast_gen(isl_ctx *ctx)10045{10046	if (test_ast_gen1(ctx) < 0)10047		return -1;10048	if (test_ast_gen2(ctx) < 0)10049		return -1;10050	if (test_ast_gen3(ctx) < 0)10051		return -1;10052	if (test_ast_gen4(ctx) < 0)10053		return -1;10054	if (test_ast_gen5(ctx) < 0)10055		return -1;10056	if (test_ast_expr(ctx) < 0)10057		return -1;10058	return 0;10059}10060 10061/* Check if dropping output dimensions from an isl_pw_multi_aff10062 * works properly.10063 */10064static int test_pw_multi_aff(isl_ctx *ctx)10065{10066	const char *str;10067	isl_pw_multi_aff *pma1, *pma2;10068	int equal;10069 10070	str = "{ [i,j] -> [i+j, 4i-j] }";10071	pma1 = isl_pw_multi_aff_read_from_str(ctx, str);10072	str = "{ [i,j] -> [4i-j] }";10073	pma2 = isl_pw_multi_aff_read_from_str(ctx, str);10074 10075	pma1 = isl_pw_multi_aff_drop_dims(pma1, isl_dim_out, 0, 1);10076 10077	equal = isl_pw_multi_aff_plain_is_equal(pma1, pma2);10078 10079	isl_pw_multi_aff_free(pma1);10080	isl_pw_multi_aff_free(pma2);10081	if (equal < 0)10082		return -1;10083	if (!equal)10084		isl_die(ctx, isl_error_unknown,10085			"expressions not equal", return -1);10086 10087	return 0;10088}10089 10090/* Check that we can properly parse multi piecewise affine expressions10091 * where the piecewise affine expressions have different domains.10092 */10093static int test_multi_pw_aff_1(isl_ctx *ctx)10094{10095	const char *str;10096	isl_set *dom, *dom2;10097	isl_multi_pw_aff *mpa1, *mpa2;10098	isl_pw_aff *pa;10099	int equal;10100	int equal_domain;10101 10102	mpa1 = isl_multi_pw_aff_read_from_str(ctx, "{ [i] -> [i] }");10103	dom = isl_set_read_from_str(ctx, "{ [i] : i > 0 }");10104	mpa1 = isl_multi_pw_aff_intersect_domain(mpa1, dom);10105	mpa2 = isl_multi_pw_aff_read_from_str(ctx, "{ [i] -> [2i] }");10106	mpa2 = isl_multi_pw_aff_flat_range_product(mpa1, mpa2);10107	str = "{ [i] -> [(i : i > 0), 2i] }";10108	mpa1 = isl_multi_pw_aff_read_from_str(ctx, str);10109 10110	equal = isl_multi_pw_aff_plain_is_equal(mpa1, mpa2);10111 10112	pa = isl_multi_pw_aff_get_pw_aff(mpa1, 0);10113	dom = isl_pw_aff_domain(pa);10114	pa = isl_multi_pw_aff_get_pw_aff(mpa1, 1);10115	dom2 = isl_pw_aff_domain(pa);10116	equal_domain = isl_set_is_equal(dom, dom2);10117 10118	isl_set_free(dom);10119	isl_set_free(dom2);10120	isl_multi_pw_aff_free(mpa1);10121	isl_multi_pw_aff_free(mpa2);10122 10123	if (equal < 0)10124		return -1;10125	if (!equal)10126		isl_die(ctx, isl_error_unknown,10127			"expressions not equal", return -1);10128 10129	if (equal_domain < 0)10130		return -1;10131	if (equal_domain)10132		isl_die(ctx, isl_error_unknown,10133			"domains unexpectedly equal", return -1);10134 10135	return 0;10136}10137 10138/* Check that the dimensions in the explicit domain10139 * of a multi piecewise affine expression are properly10140 * taken into account.10141 */10142static int test_multi_pw_aff_2(isl_ctx *ctx)10143{10144	const char *str;10145	isl_bool involves1, involves2, involves3, equal;10146	isl_multi_pw_aff *mpa, *mpa1, *mpa2;10147 10148	str = "{ A[x,y] -> B[] : x >= y }";10149	mpa = isl_multi_pw_aff_read_from_str(ctx, str);10150	involves1 = isl_multi_pw_aff_involves_dims(mpa, isl_dim_in, 0, 2);10151	mpa1 = isl_multi_pw_aff_copy(mpa);10152 10153	mpa = isl_multi_pw_aff_insert_dims(mpa, isl_dim_in, 0, 1);10154	involves2 = isl_multi_pw_aff_involves_dims(mpa, isl_dim_in, 0, 1);10155	involves3 = isl_multi_pw_aff_involves_dims(mpa, isl_dim_in, 1, 2);10156	str = "{ [a,x,y] -> B[] : x >= y }";10157	mpa2 = isl_multi_pw_aff_read_from_str(ctx, str);10158	equal = isl_multi_pw_aff_plain_is_equal(mpa, mpa2);10159	isl_multi_pw_aff_free(mpa2);10160 10161	mpa = isl_multi_pw_aff_drop_dims(mpa, isl_dim_in, 0, 1);10162	mpa = isl_multi_pw_aff_set_tuple_name(mpa, isl_dim_in, "A");10163	if (equal >= 0 && equal)10164		equal = isl_multi_pw_aff_plain_is_equal(mpa, mpa1);10165	isl_multi_pw_aff_free(mpa1);10166	isl_multi_pw_aff_free(mpa);10167 10168	if (involves1 < 0 || involves2 < 0 || involves3 < 0 || equal < 0)10169		return -1;10170	if (!equal)10171		isl_die(ctx, isl_error_unknown,10172			"incorrect result of dimension insertion/removal",10173			return isl_stat_error);10174	if (!involves1 || involves2 || !involves3)10175		isl_die(ctx, isl_error_unknown,10176			"incorrect characterization of involved dimensions",10177			return isl_stat_error);10178 10179	return 0;10180}10181 10182/* Check that isl_multi_union_pw_aff_multi_val_on_domain10183 * sets the explicit domain of a zero-dimensional result,10184 * such that it can be converted to an isl_union_map.10185 */10186static isl_stat test_multi_pw_aff_3(isl_ctx *ctx)10187{10188	isl_space *space;10189	isl_union_set *dom;10190	isl_multi_val *mv;10191	isl_multi_union_pw_aff *mupa;10192	isl_union_map *umap;10193 10194	dom = isl_union_set_read_from_str(ctx, "{ A[]; B[] }");10195	space = isl_union_set_get_space(dom);10196	mv = isl_multi_val_zero(isl_space_set_from_params(space));10197	mupa = isl_multi_union_pw_aff_multi_val_on_domain(dom, mv);10198	umap = isl_union_map_from_multi_union_pw_aff(mupa);10199	isl_union_map_free(umap);10200	if (!umap)10201		return isl_stat_error;10202 10203	return isl_stat_ok;10204}10205 10206/* String descriptions of boxes that10207 * are used for reconstructing box maps from their lower and upper bounds.10208 */10209static const char *multi_pw_aff_box_tests[] = {10210	"{ A[x, y] -> [] : x + y >= 0 }",10211	"[N] -> { A[x, y] -> [x] : x + y <= N }",10212	"[N] -> { A[x, y] -> [x : y] : x + y <= N }",10213};10214 10215/* Check that map representations of boxes can be reconstructed10216 * from their lower and upper bounds.10217 */10218static isl_stat test_multi_pw_aff_box(isl_ctx *ctx)10219{10220	int i;10221 10222	for (i = 0; i < ARRAY_SIZE(multi_pw_aff_box_tests); ++i) {10223		const char *str;10224		isl_bool equal;10225		isl_map *map, *box;10226		isl_multi_pw_aff *min, *max;10227 10228		str = multi_pw_aff_box_tests[i];10229		map = isl_map_read_from_str(ctx, str);10230		min = isl_map_min_multi_pw_aff(isl_map_copy(map));10231		max = isl_map_max_multi_pw_aff(isl_map_copy(map));10232		box = isl_map_universe(isl_map_get_space(map));10233		box = isl_map_lower_bound_multi_pw_aff(box, min);10234		box = isl_map_upper_bound_multi_pw_aff(box, max);10235		equal = isl_map_is_equal(map, box);10236		isl_map_free(map);10237		isl_map_free(box);10238		if (equal < 0)10239			return isl_stat_error;10240		if (!equal)10241			isl_die(ctx, isl_error_unknown,10242				"unexpected result", return isl_stat_error);10243	}10244 10245	return isl_stat_ok;10246}10247 10248/* Perform some tests on multi piecewise affine expressions.10249 */10250static int test_multi_pw_aff(isl_ctx *ctx)10251{10252	if (test_multi_pw_aff_1(ctx) < 0)10253		return -1;10254	if (test_multi_pw_aff_2(ctx) < 0)10255		return -1;10256	if (test_multi_pw_aff_3(ctx) < 0)10257		return -1;10258	if (test_multi_pw_aff_box(ctx) < 0)10259		return -1;10260	return 0;10261}10262 10263/* This is a regression test for a bug where isl_basic_map_simplify10264 * would end up in an infinite loop.  In particular, we construct10265 * an empty basic set that is not obviously empty.10266 * isl_basic_set_is_empty marks the basic set as empty.10267 * After projecting out i3, the variable can be dropped completely,10268 * but isl_basic_map_simplify refrains from doing so if the basic set10269 * is empty and would end up in an infinite loop if it didn't test10270 * explicitly for empty basic maps in the outer loop.10271 */10272static int test_simplify_1(isl_ctx *ctx)10273{10274	const char *str;10275	isl_basic_set *bset;10276	int empty;10277 10278	str = "{ [i0, i1, i2, i3] : i0 >= -2 and 6i2 <= 4 + i0 + 5i1 and "10279		"i2 <= 22 and 75i2 <= 111 + 13i0 + 60i1 and "10280		"25i2 >= 38 + 6i0 + 20i1 and i0 <= -1 and i2 >= 20 and "10281		"i3 >= i2 }";10282	bset = isl_basic_set_read_from_str(ctx, str);10283	empty = isl_basic_set_is_empty(bset);10284	bset = isl_basic_set_project_out(bset, isl_dim_set, 3, 1);10285	isl_basic_set_free(bset);10286	if (!bset)10287		return -1;10288	if (!empty)10289		isl_die(ctx, isl_error_unknown,10290			"basic set should be empty", return -1);10291 10292	return 0;10293}10294 10295/* Check that the equality in the set description below10296 * is simplified away.10297 */10298static int test_simplify_2(isl_ctx *ctx)10299{10300	const char *str;10301	isl_basic_set *bset;10302	isl_bool universe;10303 10304	str = "{ [a] : exists e0, e1: 32e1 = 31 + 31a + 31e0 }";10305	bset = isl_basic_set_read_from_str(ctx, str);10306	universe = isl_basic_set_plain_is_universe(bset);10307	isl_basic_set_free(bset);10308 10309	if (universe < 0)10310		return -1;10311	if (!universe)10312		isl_die(ctx, isl_error_unknown,10313			"equality not simplified away", return -1);10314	return 0;10315}10316 10317/* Some simplification tests.10318 */10319static int test_simplify(isl_ctx *ctx)10320{10321	if (test_simplify_1(ctx) < 0)10322		return -1;10323	if (test_simplify_2(ctx) < 0)10324		return -1;10325	return 0;10326}10327 10328/* This is a regression test for a bug where isl_tab_basic_map_partial_lexopt10329 * with gbr context would fail to disable the use of the shifted tableau10330 * when transferring equalities for the input to the context, resulting10331 * in invalid sample values.10332 */10333static int test_partial_lexmin(isl_ctx *ctx)10334{10335	const char *str;10336	isl_basic_set *bset;10337	isl_basic_map *bmap;10338	isl_map *map;10339 10340	str = "{ [1, b, c, 1 - c] -> [e] : 2e <= -c and 2e >= -3 + c }";10341	bmap = isl_basic_map_read_from_str(ctx, str);10342	str = "{ [a, b, c, d] : c <= 1 and 2d >= 6 - 4b - c }";10343	bset = isl_basic_set_read_from_str(ctx, str);10344	map = isl_basic_map_partial_lexmin(bmap, bset, NULL);10345	isl_map_free(map);10346 10347	if (!map)10348		return -1;10349 10350	return 0;10351}10352 10353/* Check that the variable compression performed on the existentially10354 * quantified variables inside isl_basic_set_compute_divs is not confused10355 * by the implicit equalities among the parameters.10356 */10357static int test_compute_divs(isl_ctx *ctx)10358{10359	const char *str;10360	isl_basic_set *bset;10361	isl_set *set;10362 10363	str = "[a, b, c, d, e] -> { [] : exists (e0: 2d = b and a <= 124 and "10364		"b <= 2046 and b >= 0 and b <= 60 + 64a and 2e >= b + 2c and "10365		"2e >= b and 2e <= 1 + b and 2e <= 1 + b + 2c and "10366		"32768e0 >= -124 + a and 2097152e0 <= 60 + 64a - b) }";10367	bset = isl_basic_set_read_from_str(ctx, str);10368	set = isl_basic_set_compute_divs(bset);10369	isl_set_free(set);10370	if (!set)10371		return -1;10372 10373	return 0;10374}10375 10376/* Check that isl_schedule_get_map is not confused by a schedule tree10377 * with divergent filter node parameters, as can result from a call10378 * to isl_schedule_intersect_domain.10379 */10380static int test_schedule_tree(isl_ctx *ctx)10381{10382	const char *str;10383	isl_union_set *uset;10384	isl_schedule *sched1, *sched2;10385	isl_union_map *umap;10386 10387	uset = isl_union_set_read_from_str(ctx, "{ A[i] }");10388	sched1 = isl_schedule_from_domain(uset);10389	uset = isl_union_set_read_from_str(ctx, "{ B[] }");10390	sched2 = isl_schedule_from_domain(uset);10391 10392	sched1 = isl_schedule_sequence(sched1, sched2);10393	str = "[n] -> { A[i] : 0 <= i < n; B[] }";10394	uset = isl_union_set_read_from_str(ctx, str);10395	sched1 = isl_schedule_intersect_domain(sched1, uset);10396	umap = isl_schedule_get_map(sched1);10397	isl_schedule_free(sched1);10398	isl_union_map_free(umap);10399	if (!umap)10400		return -1;10401 10402	return 0;10403}10404 10405/* Check that a zero-dimensional prefix schedule keeps track10406 * of the domain and outer filters.10407 */10408static int test_schedule_tree_prefix(isl_ctx *ctx)10409{10410	const char *str;10411	isl_bool equal;10412	isl_union_set *uset;10413	isl_union_set_list *filters;10414	isl_multi_union_pw_aff *mupa, *mupa2;10415	isl_schedule_node *node;10416 10417	str = "{ S1[i,j] : 0 <= i,j < 10; S2[i,j] : 0 <= i,j < 10 }";10418	uset = isl_union_set_read_from_str(ctx, str);10419	node = isl_schedule_node_from_domain(uset);10420	node = isl_schedule_node_child(node, 0);10421 10422	str = "{ S1[i,j] : i > j }";10423	uset = isl_union_set_read_from_str(ctx, str);10424	filters = isl_union_set_list_from_union_set(uset);10425	str = "{ S1[i,j] : i <= j; S2[i,j] }";10426	uset = isl_union_set_read_from_str(ctx, str);10427	filters = isl_union_set_list_add(filters, uset);10428	node = isl_schedule_node_insert_sequence(node, filters);10429 10430	node = isl_schedule_node_grandchild(node, 0, 0);10431	mupa = isl_schedule_node_get_prefix_schedule_multi_union_pw_aff(node);10432	str = "([] : { S1[i,j] : i > j })";10433	mupa2 = isl_multi_union_pw_aff_read_from_str(ctx, str);10434	equal = isl_multi_union_pw_aff_plain_is_equal(mupa, mupa2);10435	isl_multi_union_pw_aff_free(mupa2);10436	isl_multi_union_pw_aff_free(mupa);10437	isl_schedule_node_free(node);10438 10439	if (equal < 0)10440		return -1;10441	if (!equal)10442		isl_die(ctx, isl_error_unknown, "unexpected prefix schedule",10443			return -1);10444 10445	return 0;10446}10447 10448/* Check that the reaching domain elements and the prefix schedule10449 * at a leaf node are the same before and after grouping.10450 */10451static int test_schedule_tree_group_1(isl_ctx *ctx)10452{10453	int equal;10454	const char *str;10455	isl_id *id;10456	isl_union_set *uset;10457	isl_multi_union_pw_aff *mupa;10458	isl_union_pw_multi_aff *upma1, *upma2;10459	isl_union_set *domain1, *domain2;10460	isl_union_map *umap1, *umap2;10461	isl_schedule_node *node;10462 10463	str = "{ S1[i,j] : 0 <= i,j < 10; S2[i,j] : 0 <= i,j < 10 }";10464	uset = isl_union_set_read_from_str(ctx, str);10465	node = isl_schedule_node_from_domain(uset);10466	node = isl_schedule_node_child(node, 0);10467	str = "[{ S1[i,j] -> [i]; S2[i,j] -> [9 - i] }]";10468	mupa = isl_multi_union_pw_aff_read_from_str(ctx, str);10469	node = isl_schedule_node_insert_partial_schedule(node, mupa);10470	node = isl_schedule_node_child(node, 0);10471	str = "[{ S1[i,j] -> [j]; S2[i,j] -> [j] }]";10472	mupa = isl_multi_union_pw_aff_read_from_str(ctx, str);10473	node = isl_schedule_node_insert_partial_schedule(node, mupa);10474	node = isl_schedule_node_child(node, 0);10475	umap1 = isl_schedule_node_get_prefix_schedule_union_map(node);10476	upma1 = isl_schedule_node_get_prefix_schedule_union_pw_multi_aff(node);10477	domain1 = isl_schedule_node_get_domain(node);10478	id = isl_id_alloc(ctx, "group", NULL);10479	node = isl_schedule_node_parent(node);10480	node = isl_schedule_node_group(node, id);10481	node = isl_schedule_node_child(node, 0);10482	umap2 = isl_schedule_node_get_prefix_schedule_union_map(node);10483	upma2 = isl_schedule_node_get_prefix_schedule_union_pw_multi_aff(node);10484	domain2 = isl_schedule_node_get_domain(node);10485	equal = isl_union_pw_multi_aff_plain_is_equal(upma1, upma2);10486	if (equal >= 0 && equal)10487		equal = isl_union_set_is_equal(domain1, domain2);10488	if (equal >= 0 && equal)10489		equal = isl_union_map_is_equal(umap1, umap2);10490	isl_union_map_free(umap1);10491	isl_union_map_free(umap2);10492	isl_union_set_free(domain1);10493	isl_union_set_free(domain2);10494	isl_union_pw_multi_aff_free(upma1);10495	isl_union_pw_multi_aff_free(upma2);10496	isl_schedule_node_free(node);10497 10498	if (equal < 0)10499		return -1;10500	if (!equal)10501		isl_die(ctx, isl_error_unknown,10502			"expressions not equal", return -1);10503 10504	return 0;10505}10506 10507/* Check that we can have nested groupings and that the union map10508 * schedule representation is the same before and after the grouping.10509 * Note that after the grouping, the union map representation contains10510 * the domain constraints from the ranges of the expansion nodes,10511 * while they are missing from the union map representation of10512 * the tree without expansion nodes.10513 *10514 * Also check that the global expansion is as expected.10515 */10516static int test_schedule_tree_group_2(isl_ctx *ctx)10517{10518	int equal, equal_expansion;10519	const char *str;10520	isl_id *id;10521	isl_union_set *uset;10522	isl_union_map *umap1, *umap2;10523	isl_union_map *expansion1, *expansion2;10524	isl_union_set_list *filters;10525	isl_multi_union_pw_aff *mupa;10526	isl_schedule *schedule;10527	isl_schedule_node *node;10528 10529	str = "{ S1[i,j] : 0 <= i,j < 10; S2[i,j] : 0 <= i,j < 10; "10530		"S3[i,j] : 0 <= i,j < 10 }";10531	uset = isl_union_set_read_from_str(ctx, str);10532	node = isl_schedule_node_from_domain(uset);10533	node = isl_schedule_node_child(node, 0);10534	str = "[{ S1[i,j] -> [i]; S2[i,j] -> [i]; S3[i,j] -> [i] }]";10535	mupa = isl_multi_union_pw_aff_read_from_str(ctx, str);10536	node = isl_schedule_node_insert_partial_schedule(node, mupa);10537	node = isl_schedule_node_child(node, 0);10538	str = "{ S1[i,j] }";10539	uset = isl_union_set_read_from_str(ctx, str);10540	filters = isl_union_set_list_from_union_set(uset);10541	str = "{ S2[i,j]; S3[i,j] }";10542	uset = isl_union_set_read_from_str(ctx, str);10543	filters = isl_union_set_list_add(filters, uset);10544	node = isl_schedule_node_insert_sequence(node, filters);10545	node = isl_schedule_node_grandchild(node, 1, 0);10546	str = "{ S2[i,j] }";10547	uset = isl_union_set_read_from_str(ctx, str);10548	filters = isl_union_set_list_from_union_set(uset);10549	str = "{ S3[i,j] }";10550	uset = isl_union_set_read_from_str(ctx, str);10551	filters = isl_union_set_list_add(filters, uset);10552	node = isl_schedule_node_insert_sequence(node, filters);10553 10554	schedule = isl_schedule_node_get_schedule(node);10555	umap1 = isl_schedule_get_map(schedule);10556	uset = isl_schedule_get_domain(schedule);10557	umap1 = isl_union_map_intersect_domain(umap1, uset);10558	isl_schedule_free(schedule);10559 10560	node = isl_schedule_node_grandparent(node);10561	id = isl_id_alloc(ctx, "group1", NULL);10562	node = isl_schedule_node_group(node, id);10563	node = isl_schedule_node_grandchild(node, 1, 0);10564	id = isl_id_alloc(ctx, "group2", NULL);10565	node = isl_schedule_node_group(node, id);10566 10567	schedule = isl_schedule_node_get_schedule(node);10568	umap2 = isl_schedule_get_map(schedule);10569	isl_schedule_free(schedule);10570 10571	node = isl_schedule_node_root(node);10572	node = isl_schedule_node_child(node, 0);10573	expansion1 = isl_schedule_node_get_subtree_expansion(node);10574	isl_schedule_node_free(node);10575 10576	str = "{ group1[i] -> S1[i,j] : 0 <= i,j < 10; "10577		"group1[i] -> S2[i,j] : 0 <= i,j < 10; "10578		"group1[i] -> S3[i,j] : 0 <= i,j < 10 }";10579 10580	expansion2 = isl_union_map_read_from_str(ctx, str);10581 10582	equal = isl_union_map_is_equal(umap1, umap2);10583	equal_expansion = isl_union_map_is_equal(expansion1, expansion2);10584 10585	isl_union_map_free(umap1);10586	isl_union_map_free(umap2);10587	isl_union_map_free(expansion1);10588	isl_union_map_free(expansion2);10589 10590	if (equal < 0 || equal_expansion < 0)10591		return -1;10592	if (!equal)10593		isl_die(ctx, isl_error_unknown,10594			"expressions not equal", return -1);10595	if (!equal_expansion)10596		isl_die(ctx, isl_error_unknown,10597			"unexpected expansion", return -1);10598 10599	return 0;10600}10601 10602/* Some tests for the isl_schedule_node_group function.10603 */10604static int test_schedule_tree_group(isl_ctx *ctx)10605{10606	if (test_schedule_tree_group_1(ctx) < 0)10607		return -1;10608	if (test_schedule_tree_group_2(ctx) < 0)10609		return -1;10610	return 0;10611}10612 10613struct {10614	const char *set;10615	const char *dual;10616} coef_tests[] = {10617	{ "{ rat: [i] : 0 <= i <= 10 }",10618	  "{ rat: coefficients[[cst] -> [a]] : cst >= 0 and 10a + cst >= 0 }" },10619	{ "{ rat: [i] : FALSE }",10620	  "{ rat: coefficients[[cst] -> [a]] }" },10621	{ "{ rat: [i] : }",10622	  "{ rat: coefficients[[cst] -> [0]] : cst >= 0 }" },10623	{ "{ [0:,1,2:3] }",10624	  "{ rat: coefficients[[c_cst] -> [a, b, c]] : "10625		"a >= 0 and 2c >= -c_cst - b and 3c >= -c_cst - b }" },10626	{ "[M, N] -> { [x = (1 - N):-1, -4x:(M - 4x)] }",10627	  "{ rat: coefficients[[c_cst, c_M = 0:, c_N = 0:] -> [a, b = -c_M:]] :"10628		"4b >= -c_N + a and 4b >= -c_cst - 2c_N + a }" },10629	{ "{ rat : [x, y] : 1 <= 2x <= 9 and 2 <= 3y <= 16 }",10630	  "{ rat: coefficients[[c_cst] -> [c_x, c_y]] : "10631		"4c_y >= -6c_cst - 3c_x and 4c_y >= -6c_cst - 27c_x and "10632		"32c_y >= -6c_cst - 3c_x and 32c_y >= -6c_cst - 27c_x }" },10633	{ "{ [x, y, z] : 3y <= 2x - 2 and y >= -2 + 2x and 2y >= 2 - x }",10634	  "{ rat: coefficients[[cst] -> [a, b, c]] }" },10635};10636 10637struct {10638	const char *set;10639	const char *dual;10640} sol_tests[] = {10641	{ "{ rat: coefficients[[cst] -> [a]] : cst >= 0 and 10a + cst >= 0 }",10642	  "{ rat: [i] : 0 <= i <= 10 }" },10643	{ "{ rat: coefficients[[cst] -> [a]] : FALSE }",10644	  "{ rat: [i] }" },10645	{ "{ rat: coefficients[[cst] -> [a]] }",10646	  "{ rat: [i] : FALSE }" },10647};10648 10649/* Test the basic functionality of isl_basic_set_coefficients and10650 * isl_basic_set_solutions.10651 */10652static int test_dual(isl_ctx *ctx)10653{10654	int i;10655 10656	for (i = 0; i < ARRAY_SIZE(coef_tests); ++i) {10657		int equal;10658		isl_basic_set *bset1, *bset2;10659 10660		bset1 = isl_basic_set_read_from_str(ctx, coef_tests[i].set);10661		bset2 = isl_basic_set_read_from_str(ctx, coef_tests[i].dual);10662		bset1 = isl_basic_set_coefficients(bset1);10663		equal = isl_basic_set_is_equal(bset1, bset2);10664		isl_basic_set_free(bset1);10665		isl_basic_set_free(bset2);10666		if (equal < 0)10667			return -1;10668		if (!equal)10669			isl_die(ctx, isl_error_unknown,10670				"incorrect dual", return -1);10671	}10672 10673	for (i = 0; i < ARRAY_SIZE(sol_tests); ++i) {10674		int equal;10675		isl_basic_set *bset1, *bset2;10676 10677		bset1 = isl_basic_set_read_from_str(ctx, sol_tests[i].set);10678		bset2 = isl_basic_set_read_from_str(ctx, sol_tests[i].dual);10679		bset1 = isl_basic_set_solutions(bset1);10680		equal = isl_basic_set_is_equal(bset1, bset2);10681		isl_basic_set_free(bset1);10682		isl_basic_set_free(bset2);10683		if (equal < 0)10684			return -1;10685		if (!equal)10686			isl_die(ctx, isl_error_unknown,10687				"incorrect dual", return -1);10688	}10689 10690	return 0;10691}10692 10693struct {10694	int scale_tile;10695	int shift_point;10696	const char *domain;10697	const char *schedule;10698	const char *sizes;10699	const char *tile;10700	const char *point;10701} tile_tests[] = {10702	{ 0, 0, "[n] -> { S[i,j] : 0 <= i,j < n }",10703	  "[{ S[i,j] -> [i] }, { S[i,j] -> [j] }]",10704	  "{ [32,32] }",10705	  "[{ S[i,j] -> [floor(i/32)] }, { S[i,j] -> [floor(j/32)] }]",10706	  "[{ S[i,j] -> [i] }, { S[i,j] -> [j] }]",10707	},10708	{ 1, 0, "[n] -> { S[i,j] : 0 <= i,j < n }",10709	  "[{ S[i,j] -> [i] }, { S[i,j] -> [j] }]",10710	  "{ [32,32] }",10711	  "[{ S[i,j] -> [32*floor(i/32)] }, { S[i,j] -> [32*floor(j/32)] }]",10712	  "[{ S[i,j] -> [i] }, { S[i,j] -> [j] }]",10713	},10714	{ 0, 1, "[n] -> { S[i,j] : 0 <= i,j < n }",10715	  "[{ S[i,j] -> [i] }, { S[i,j] -> [j] }]",10716	  "{ [32,32] }",10717	  "[{ S[i,j] -> [floor(i/32)] }, { S[i,j] -> [floor(j/32)] }]",10718	  "[{ S[i,j] -> [i%32] }, { S[i,j] -> [j%32] }]",10719	},10720	{ 1, 1, "[n] -> { S[i,j] : 0 <= i,j < n }",10721	  "[{ S[i,j] -> [i] }, { S[i,j] -> [j] }]",10722	  "{ [32,32] }",10723	  "[{ S[i,j] -> [32*floor(i/32)] }, { S[i,j] -> [32*floor(j/32)] }]",10724	  "[{ S[i,j] -> [i%32] }, { S[i,j] -> [j%32] }]",10725	},10726};10727 10728/* Basic tiling tests.  Create a schedule tree with a domain and a band node,10729 * tile the band and then check if the tile and point bands have the10730 * expected partial schedule.10731 */10732static int test_tile(isl_ctx *ctx)10733{10734	int i;10735	int scale;10736	int shift;10737 10738	scale = isl_options_get_tile_scale_tile_loops(ctx);10739	shift = isl_options_get_tile_shift_point_loops(ctx);10740 10741	for (i = 0; i < ARRAY_SIZE(tile_tests); ++i) {10742		int opt;10743		int equal;10744		const char *str;10745		isl_union_set *domain;10746		isl_multi_union_pw_aff *mupa, *mupa2;10747		isl_schedule_node *node;10748		isl_multi_val *sizes;10749 10750		opt = tile_tests[i].scale_tile;10751		isl_options_set_tile_scale_tile_loops(ctx, opt);10752		opt = tile_tests[i].shift_point;10753		isl_options_set_tile_shift_point_loops(ctx, opt);10754 10755		str = tile_tests[i].domain;10756		domain = isl_union_set_read_from_str(ctx, str);10757		node = isl_schedule_node_from_domain(domain);10758		node = isl_schedule_node_child(node, 0);10759		str = tile_tests[i].schedule;10760		mupa = isl_multi_union_pw_aff_read_from_str(ctx, str);10761		node = isl_schedule_node_insert_partial_schedule(node, mupa);10762		str = tile_tests[i].sizes;10763		sizes = isl_multi_val_read_from_str(ctx, str);10764		node = isl_schedule_node_band_tile(node, sizes);10765 10766		str = tile_tests[i].tile;10767		mupa = isl_multi_union_pw_aff_read_from_str(ctx, str);10768		mupa2 = isl_schedule_node_band_get_partial_schedule(node);10769		equal = isl_multi_union_pw_aff_plain_is_equal(mupa, mupa2);10770		isl_multi_union_pw_aff_free(mupa);10771		isl_multi_union_pw_aff_free(mupa2);10772 10773		node = isl_schedule_node_child(node, 0);10774 10775		str = tile_tests[i].point;10776		mupa = isl_multi_union_pw_aff_read_from_str(ctx, str);10777		mupa2 = isl_schedule_node_band_get_partial_schedule(node);10778		if (equal >= 0 && equal)10779			equal = isl_multi_union_pw_aff_plain_is_equal(mupa,10780									mupa2);10781		isl_multi_union_pw_aff_free(mupa);10782		isl_multi_union_pw_aff_free(mupa2);10783 10784		isl_schedule_node_free(node);10785 10786		if (equal < 0)10787			return -1;10788		if (!equal)10789			isl_die(ctx, isl_error_unknown,10790				"unexpected result", return -1);10791	}10792 10793	isl_options_set_tile_scale_tile_loops(ctx, scale);10794	isl_options_set_tile_shift_point_loops(ctx, shift);10795 10796	return 0;10797}10798 10799/* Check that the domain hash of a space is equal to the hash10800 * of the domain of the space, both ignoring parameters.10801 */10802static int test_domain_hash(isl_ctx *ctx)10803{10804	isl_map *map;10805	isl_space *space;10806	uint32_t hash1, hash2;10807 10808	map = isl_map_read_from_str(ctx, "[n] -> { A[B[x] -> C[]] -> D[] }");10809	space = isl_map_get_space(map);10810	isl_map_free(map);10811	hash1 = isl_space_get_tuple_domain_hash(space);10812	space = isl_space_domain(space);10813	hash2 = isl_space_get_tuple_hash(space);10814	isl_space_free(space);10815 10816	if (!space)10817		return -1;10818	if (hash1 != hash2)10819		isl_die(ctx, isl_error_unknown,10820			"domain hash not equal to hash of domain", return -1);10821 10822	return 0;10823}10824 10825/* Check that a universe basic set that is not obviously equal to the universe10826 * is still recognized as being equal to the universe.10827 */10828static int test_universe(isl_ctx *ctx)10829{10830	const char *s;10831	isl_basic_set *bset;10832	isl_bool is_univ;10833 10834	s = "{ [] : exists x, y : 3y <= 2x and y >= -3 + 2x and 2y >= 2 - x }";10835	bset = isl_basic_set_read_from_str(ctx, s);10836	is_univ = isl_basic_set_is_universe(bset);10837	isl_basic_set_free(bset);10838 10839	if (is_univ < 0)10840		return -1;10841	if (!is_univ)10842		isl_die(ctx, isl_error_unknown,10843			"not recognized as universe set", return -1);10844 10845	return 0;10846}10847 10848/* Sets for which chambers are computed and checked.10849 */10850const char *chambers_tests[] = {10851	"[A, B, C] -> { [x, y, z] : x >= 0 and y >= 0 and y <= A - x and "10852				"z >= 0 and z <= C - y and z <= B - x - y }",10853};10854 10855/* Add the domain of "cell" to "cells".10856 */10857static isl_stat add_cell(__isl_take isl_cell *cell, void *user)10858{10859	isl_basic_set_list **cells = user;10860	isl_basic_set *dom;10861 10862	dom = isl_cell_get_domain(cell);10863	isl_cell_free(cell);10864	*cells = isl_basic_set_list_add(*cells, dom);10865 10866	return *cells ? isl_stat_ok : isl_stat_error;10867}10868 10869/* Check that the elements of "list" are pairwise disjoint.10870 */10871static isl_stat check_pairwise_disjoint(__isl_keep isl_basic_set_list *list)10872{10873	int i, j;10874	isl_size n;10875 10876	n = isl_basic_set_list_n_basic_set(list);10877	if (n < 0)10878		return isl_stat_error;10879 10880	for (i = 0; i < n; ++i) {10881		isl_basic_set *bset_i;10882 10883		bset_i = isl_basic_set_list_get_basic_set(list, i);10884		for (j = i + 1; j < n; ++j) {10885			isl_basic_set *bset_j;10886			isl_bool disjoint;10887 10888			bset_j = isl_basic_set_list_get_basic_set(list, j);10889			disjoint = isl_basic_set_is_disjoint(bset_i, bset_j);10890			isl_basic_set_free(bset_j);10891			if (!disjoint)10892				isl_die(isl_basic_set_list_get_ctx(list),10893					isl_error_unknown, "not disjoint",10894					break);10895			if (disjoint < 0 || !disjoint)10896				break;10897		}10898		isl_basic_set_free(bset_i);10899		if (j < n)10900			return isl_stat_error;10901	}10902 10903	return isl_stat_ok;10904}10905 10906/* Check that the chambers computed by isl_vertices_foreach_disjoint_cell10907 * are pairwise disjoint.10908 */10909static int test_chambers(isl_ctx *ctx)10910{10911	int i;10912 10913	for (i = 0; i < ARRAY_SIZE(chambers_tests); ++i) {10914		isl_basic_set *bset;10915		isl_vertices *vertices;10916		isl_basic_set_list *cells;10917		isl_stat ok;10918 10919		bset = isl_basic_set_read_from_str(ctx, chambers_tests[i]);10920		vertices = isl_basic_set_compute_vertices(bset);10921		cells = isl_basic_set_list_alloc(ctx, 0);10922		if (isl_vertices_foreach_disjoint_cell(vertices, &add_cell,10923							&cells) < 0)10924			cells = isl_basic_set_list_free(cells);10925		ok = check_pairwise_disjoint(cells);10926		isl_basic_set_list_free(cells);10927		isl_vertices_free(vertices);10928		isl_basic_set_free(bset);10929 10930		if (ok < 0)10931			return -1;10932	}10933 10934	return 0;10935}10936 10937struct {10938	const char *name;10939	int (*fn)(isl_ctx *ctx);10940} tests [] = {10941	{ "universe", &test_universe },10942	{ "domain hash", &test_domain_hash },10943	{ "dual", &test_dual },10944	{ "dependence analysis", &test_flow },10945	{ "val", &test_val },10946	{ "compute divs", &test_compute_divs },10947	{ "partial lexmin", &test_partial_lexmin },10948	{ "simplify", &test_simplify },10949	{ "curry", &test_curry },10950	{ "piecewise multi affine expressions", &test_pw_multi_aff },10951	{ "multi piecewise affine expressions", &test_multi_pw_aff },10952	{ "conversion", &test_conversion },10953	{ "list", &test_list },10954	{ "align parameters", &test_align_parameters },10955	{ "drop unused parameters", &test_drop_unused_parameters },10956	{ "pullback", &test_pullback },10957	{ "AST", &test_ast },10958	{ "AST build", &test_ast_build },10959	{ "AST generation", &test_ast_gen },10960	{ "eliminate", &test_eliminate },10961	{ "deltas_map", &test_deltas_map },10962	{ "residue class", &test_residue_class },10963	{ "div", &test_div },10964	{ "slice", &test_slice },10965	{ "sample", &test_sample },10966	{ "empty projection", &test_empty_projection },10967	{ "output", &test_output },10968	{ "vertices", &test_vertices },10969	{ "chambers", &test_chambers },10970	{ "fixed", &test_fixed },10971	{ "equal", &test_equal },10972	{ "disjoint", &test_disjoint },10973	{ "product", &test_product },10974	{ "dim_max", &test_dim_max },10975	{ "affine", &test_aff },10976	{ "injective", &test_injective },10977	{ "schedule (whole component)", &test_schedule_whole },10978	{ "schedule (incremental)", &test_schedule_incremental },10979	{ "schedule tree", &test_schedule_tree },10980	{ "schedule tree prefix", &test_schedule_tree_prefix },10981	{ "schedule tree grouping", &test_schedule_tree_group },10982	{ "tile", &test_tile },10983	{ "union map", &test_union_map },10984	{ "union_pw", &test_union_pw },10985	{ "locus", &test_locus },10986	{ "eval", &test_eval },10987	{ "parse", &test_parse },10988	{ "single-valued", &test_sv },10989	{ "recession cone", &test_recession_cone },10990	{ "affine hull", &test_affine_hull },10991	{ "simple_hull", &test_simple_hull },10992	{ "box hull", &test_box_hull },10993	{ "coalesce", &test_coalesce },10994	{ "factorize", &test_factorize },10995	{ "subset", &test_subset },10996	{ "subtract", &test_subtract },10997	{ "intersect", &test_intersect },10998	{ "lexmin", &test_lexmin },10999	{ "min", &test_min },11000	{ "set lower bounds", &test_min_mpa },11001	{ "gist", &test_gist },11002	{ "piecewise quasi-polynomials", &test_pwqp },11003	{ "lift", &test_lift },11004	{ "bind parameters", &test_bind },11005	{ "unbind parameters", &test_unbind },11006	{ "bound", &test_bound },11007	{ "get lists", &test_get_list },11008	{ "union", &test_union },11009	{ "split periods", &test_split_periods },11010	{ "lexicographic order", &test_lex },11011	{ "bijectivity", &test_bijective },11012	{ "dataflow analysis", &test_dep },11013	{ "reading", &test_read },11014	{ "bounded", &test_bounded },11015	{ "construction", &test_construction },11016	{ "dimension manipulation", &test_dim },11017	{ "map application", &test_application },11018	{ "convex hull", &test_convex_hull },11019	{ "transitive closure", &test_closure },11020	{ "isl_bool", &test_isl_bool},11021};11022 11023int main(int argc, char **argv)11024{11025	int i;11026	struct isl_ctx *ctx;11027	struct isl_options *options;11028 11029	options = isl_options_new_with_defaults();11030	assert(options);11031	argc = isl_options_parse(options, argc, argv, ISL_ARG_ALL);11032 11033	ctx = isl_ctx_alloc_with_options(&isl_options_args, options);11034	for (i = 0; i < ARRAY_SIZE(tests); ++i) {11035		printf("%s\n", tests[i].name);11036		if (tests[i].fn(ctx) < 0)11037			goto error;11038	}11039	isl_ctx_free(ctx);11040	return 0;11041error:11042	isl_ctx_free(ctx);11043	return -1;11044}11045