isl_basic_map_reduce_coefficients: introduce isl_reduce_coefficients_data
[isl.git] / isl_test2.cc
blobca4f9c0f48497326ee2ae9e6ae7a974d430b5cf0
1 /*
2 * Copyright 2008-2009 Katholieke Universiteit Leuven
3 * Copyright 2010 INRIA Saclay
4 * Copyright 2012-2013 Ecole Normale Superieure
5 * Copyright 2014 INRIA Rocquencourt
6 * Copyright 2021-2022 Cerebras Systems
8 * Use of this software is governed by the MIT license
10 * Written by Sven Verdoolaege, K.U.Leuven, Departement
11 * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
12 * and INRIA Saclay - Ile-de-France, Parc Club Orsay Universite,
13 * ZAC des vignes, 4 rue Jacques Monod, 91893 Orsay, France
14 * and Ecole Normale Superieure, 45 rue d'Ulm, 75230 Paris, France
15 * and Inria Paris - Rocquencourt, Domaine de Voluceau - Rocquencourt,
16 * B.P. 105 - 78153 Le Chesnay, France
17 * and Cerebras Systems, 1237 E Arques Ave, Sunnyvale, CA, USA
20 #include <assert.h>
21 #include <stdlib.h>
23 #include <functional>
24 #include <iostream>
25 #include <sstream>
26 #include <string>
27 #include <type_traits>
28 #include <utility>
29 #include <vector>
31 #include <isl/cpp.h>
33 /* A binary isl function that appears in the C++ bindings
34 * as a unary method in a class T, taking an extra argument
35 * of type A1 and returning an object of type R.
37 template <typename A1, typename R, typename T>
38 using binary_fn = R (T::*)(A1) const;
40 /* A function for selecting an overload of a pointer to a unary C++ method
41 * based on the single argument type.
42 * The object type and the return type are meant to be deduced.
44 template <typename A1, typename R, typename T>
45 static binary_fn<A1, R, T> const arg(const binary_fn<A1, R, T> &fn)
47 return fn;
50 /* A ternary isl function that appears in the C++ bindings
51 * as a binary method in a class T, taking extra arguments
52 * of type A1 and A2 and returning an object of type R.
54 template <typename A1, typename A2, typename R, typename T>
55 using ternary_fn = R (T::*)(A1, A2) const;
57 /* A function for selecting an overload of a pointer to a binary C++ method
58 * based on the (first) argument type(s).
59 * The object type and the return type are meant to be deduced.
61 template <typename A1, typename A2, typename R, typename T>
62 static ternary_fn<A1, A2, R, T> const arg(const ternary_fn<A1, A2, R, T> &fn)
64 return fn;
67 /* A description of the input and the output of a unary operation.
69 struct unary {
70 const char *arg;
71 const char *res;
74 /* A description of the inputs and the output of a binary operation.
76 struct binary {
77 const char *arg1;
78 const char *arg2;
79 const char *res;
82 /* A description of the inputs and the output of a ternary operation.
84 struct ternary {
85 const char *arg1;
86 const char *arg2;
87 const char *arg3;
88 const char *res;
91 /* A template function for checking whether two objects
92 * of the same (isl) type are (obviously) equal.
93 * The spelling depends on the isl type and
94 * in particular on whether an equality method is available or
95 * whether only obvious equality can be tested.
97 template <typename T, typename std::decay<decltype(
98 std::declval<T>().is_equal(std::declval<T>()))>::type = true>
99 static bool is_equal(const T &a, const T &b)
101 return a.is_equal(b);
103 template <typename T, typename std::decay<decltype(
104 std::declval<T>().plain_is_equal(std::declval<T>()))>::type = true>
105 static bool is_equal(const T &a, const T &b)
107 return a.plain_is_equal(b);
110 /* A helper macro for throwing an isl::exception_invalid with message "msg".
112 #define THROW_INVALID(msg) \
113 isl::exception::throw_error(isl_error_invalid, msg, __FILE__, __LINE__)
115 /* Run a sequence of tests of method "fn" with stringification "name" and
116 * with input and output described by "test",
117 * throwing an exception when an unexpected result is produced.
119 template <typename R, typename T>
120 static void test(isl::ctx ctx, R (T::*fn)() const, const std::string &name,
121 const std::vector<unary> &tests)
123 for (const auto &test : tests) {
124 T obj(ctx, test.arg);
125 R expected(ctx, test.res);
126 const auto &res = (obj.*fn)();
127 std::ostringstream ss;
129 if (is_equal(expected, res))
130 continue;
132 ss << name << "(" << test.arg << ") =\n"
133 << res << "\n"
134 << "expecting:\n"
135 << expected;
136 THROW_INVALID(ss.str().c_str());
140 /* Run a sequence of tests of method "fn" with stringification "name" and
141 * with inputs and output described by "test",
142 * throwing an exception when an unexpected result is produced.
144 template <typename R, typename T, typename A1>
145 static void test(isl::ctx ctx, R (T::*fn)(A1) const, const std::string &name,
146 const std::vector<binary> &tests)
148 for (const auto &test : tests) {
149 T obj(ctx, test.arg1);
150 A1 arg1(ctx, test.arg2);
151 R expected(ctx, test.res);
152 const auto &res = (obj.*fn)(arg1);
153 std::ostringstream ss;
155 if (is_equal(expected, res))
156 continue;
158 ss << name << "(" << test.arg1 << ", " << test.arg2 << ") =\n"
159 << res << "\n"
160 << "expecting:\n"
161 << expected;
162 THROW_INVALID(ss.str().c_str());
166 /* Run a sequence of tests of method "fn" with stringification "name" and
167 * with inputs and output described by "test",
168 * throwing an exception when an unexpected result is produced.
170 template <typename R, typename T, typename A1, typename A2>
171 static void test(isl::ctx ctx, R (T::*fn)(A1, A2) const,
172 const std::string &name, const std::vector<ternary> &tests)
174 for (const auto &test : tests) {
175 T obj(ctx, test.arg1);
176 A1 arg1(ctx, test.arg2);
177 A2 arg2(ctx, test.arg3);
178 R expected(ctx, test.res);
179 const auto &res = (obj.*fn)(arg1, arg2);
180 std::ostringstream ss;
182 if (is_equal(expected, res))
183 continue;
185 ss << name << "(" << test.arg1 << ", " << test.arg2 << ", "
186 << test.arg3 << ") =\n"
187 << res << "\n"
188 << "expecting:\n"
189 << expected;
190 THROW_INVALID(ss.str().c_str());
194 /* A helper macro that calls test with as implicit initial argument "ctx" and
195 * as extra argument a stringification of "FN".
197 #define C(FN, ...) test(ctx, FN, #FN, __VA_ARGS__)
199 /* Perform some basic isl::space tests.
201 static void test_space(isl::ctx ctx)
203 C(&isl::space::domain, {
204 { "{ A[] -> B[] }", "{ A[] }" },
205 { "{ A[C[] -> D[]] -> B[E[] -> F[]] }", "{ A[C[] -> D[]] }" },
208 C(&isl::space::range, {
209 { "{ A[] -> B[] }", "{ B[] }" },
210 { "{ A[C[] -> D[]] -> B[E[] -> F[]] }", "{ B[E[] -> F[]] }" },
213 C(&isl::space::params, {
214 { "{ A[] -> B[] }", "{ : }" },
215 { "{ A[C[] -> D[]] -> B[E[] -> F[]] }", "{ : }" },
219 /* Perform some basic conversion tests.
221 * In particular, check that a map with an output dimension
222 * that is equal to some integer division over a domain involving
223 * a local variable without a known integer division expression or
224 * to some linear combination of integer divisions
225 * can be converted to a function expressed in the same way.
227 static void test_conversion(isl::ctx ctx)
229 C(&isl::set::as_pw_multi_aff, {
230 { "[N=0:] -> { [] }",
231 "[N=0:] -> { [] }" },
234 C(&isl::multi_pw_aff::as_set, {
235 { "[n] -> { [] : n >= 0 } ",
236 "[n] -> { [] : n >= 0 } " },
239 C(&isl::map::as_pw_multi_aff, {
240 { "{ [a] -> [a//2] : "
241 "exists (e0: 8*floor((-a + e0)/8) <= -8 - a + 8e0) }",
242 "{ [a] -> [a//2] : "
243 "exists (e0: 8*floor((-a + e0)/8) <= -8 - a + 8e0) }" },
244 { "{ [a, b] -> [(2*floor((a)/8) + floor((b)/6))] }",
245 "{ [a, b] -> [(2*floor((a)/8) + floor((b)/6))] }" },
249 /* Perform some basic preimage tests.
251 static void test_preimage(isl::ctx ctx)
253 C(arg<isl::multi_aff>(&isl::set::preimage), {
254 { "{ B[i,j] : 0 <= i < 10 and 0 <= j < 100 }",
255 "{ A[j,i] -> B[i,j] }",
256 "{ A[j,i] : 0 <= i < 10 and 0 <= j < 100 }" },
257 { "{ rat: B[i,j] : 0 <= i, j and 3 i + 5 j <= 100 }",
258 "{ A[a,b] -> B[a/2,b/6] }",
259 "{ rat: A[a,b] : 0 <= a, b and 9 a + 5 b <= 600 }" },
260 { "{ B[i,j] : 0 <= i, j and 3 i + 5 j <= 100 }",
261 "{ A[a,b] -> B[a/2,b/6] }",
262 "{ A[a,b] : 0 <= a, b and 9 a + 5 b <= 600 and "
263 "exists i,j : a = 2 i and b = 6 j }" },
264 { "[n] -> { S[i] : 0 <= i <= 100 }", "[n] -> { S[n] }",
265 "[n] -> { : 0 <= n <= 100 }" },
266 { "{ B[i] : 0 <= i < 100 and exists a : i = 4 a }",
267 "{ A[a] -> B[2a] }",
268 "{ A[a] : 0 <= a < 50 and exists b : a = 2 b }" },
269 { "{ B[i] : 0 <= i < 100 and exists a : i = 4 a }",
270 "{ A[a] -> B[([a/2])] }",
271 "{ A[a] : 0 <= a < 200 and exists b : [a/2] = 4 b }" },
272 { "{ B[i,j,k] : 0 <= i,j,k <= 100 }",
273 "{ A[a] -> B[a,a,a/3] }",
274 "{ A[a] : 0 <= a <= 100 and exists b : a = 3 b }" },
275 { "{ B[i,j] : j = [(i)/2] } ", "{ A[i,j] -> B[i/3,j] }",
276 "{ A[i,j] : j = [(i)/6] and exists a : i = 3 a }" },
279 C(arg<isl::pw_multi_aff>(&isl::set::preimage), {
280 { "{ B[i,j] : 0 <= i < 10 and 0 <= j < 100 }",
281 "{ A[j,i] -> B[i,j] : false }",
282 "{ A[j,i] : false }" },
285 C(arg<isl::multi_aff>(&isl::union_map::preimage_domain), {
286 { "{ B[i,j] -> C[2i + 3j] : 0 <= i < 10 and 0 <= j < 100 }",
287 "{ A[j,i] -> B[i,j] }",
288 "{ A[j,i] -> C[2i + 3j] : 0 <= i < 10 and 0 <= j < 100 }" },
289 { "{ B[i] -> C[i]; D[i] -> E[i] }",
290 "{ A[i] -> B[i + 1] }",
291 "{ A[i] -> C[i + 1] }" },
292 { "{ B[i] -> C[i]; B[i] -> E[i] }",
293 "{ A[i] -> B[i + 1] }",
294 "{ A[i] -> C[i + 1]; A[i] -> E[i + 1] }" },
295 { "{ B[i] -> C[([i/2])] }",
296 "{ A[i] -> B[2i] }",
297 "{ A[i] -> C[i] }" },
298 { "{ B[i,j] -> C[([i/2]), ([(i+j)/3])] }",
299 "{ A[i] -> B[([i/5]), ([i/7])] }",
300 "{ A[i] -> C[([([i/5])/2]), ([(([i/5])+([i/7]))/3])] }" },
301 { "[N] -> { B[i] -> C[([N/2]), i, ([N/3])] }",
302 "[N] -> { A[] -> B[([N/5])] }",
303 "[N] -> { A[] -> C[([N/2]), ([N/5]), ([N/3])] }" },
304 { "{ B[i] -> C[i] : exists a : i = 5 a }",
305 "{ A[i] -> B[2i] }",
306 "{ A[i] -> C[2i] : exists a : 2i = 5 a }" },
307 { "{ B[i] -> C[i] : exists a : i = 2 a; "
308 "B[i] -> D[i] : exists a : i = 2 a + 1 }",
309 "{ A[i] -> B[2i] }",
310 "{ A[i] -> C[2i] }" },
311 { "{ A[i] -> B[i] }", "{ C[i] -> A[(i + floor(i/3))/2] }",
312 "{ C[i] -> B[j] : 2j = i + floor(i/3) }" },
315 C(arg<isl::multi_aff>(&isl::union_map::preimage_range), {
316 { "[M] -> { A[a] -> B[a] }", "[M] -> { C[] -> B[floor(M/2)] }",
317 "[M] -> { A[floor(M/2)] -> C[] }" },
321 /* Perform some basic fixed power tests.
323 static void test_fixed_power(isl::ctx ctx)
325 C(arg<isl::val>(&isl::map::fixed_power), {
326 { "{ [i] -> [i + 1] }", "23",
327 "{ [i] -> [i + 23] }" },
328 { "{ [a = 0:1, b = 0:15, c = 0:1, d = 0:1, 0] -> [a, b, c, d, 1]; "
329 "[a = 0:1, b = 0:15, c = 0:1, 0, 1] -> [a, b, c, 1, 0]; "
330 "[a = 0:1, b = 0:15, 0, 1, 1] -> [a, b, 1, 0, 0]; "
331 "[a = 0:1, b = 0:14, 1, 1, 1] -> [a, 1 + b, 0, 0, 0]; "
332 "[0, 15, 1, 1, 1] -> [1, 0, 0, 0, 0] }",
333 "128",
334 "{ [0, b = 0:15, c = 0:1, d = 0:1, e = 0:1] -> [1, b, c, d, e] }" },
338 /* Perform some basic intersection tests.
340 static void test_intersect(isl::ctx ctx)
342 C(arg<isl::basic_set>(&isl::basic_map::intersect_params), {
343 { "[n] -> { A[x] -> B[y] }", "[n] -> { : n >= 0 }",
344 "[n] -> { A[x] -> B[y] : n >= 0 }" },
347 C(&isl::union_map::intersect_domain_wrapped_domain, {
348 { "{ [A[x] -> B[y]] -> C[z]; [D[x] -> A[y]] -> E[z] }",
349 "{ A[0] }",
350 "{ [A[0] -> B[y]] -> C[z] }" },
351 { "{ C[z] -> [A[x] -> B[y]]; E[z] -> [D[x] -> A[y]] }",
352 "{ A[0] }",
353 "{ }" },
354 { "{ T[A[x] -> B[y]] -> C[z]; [D[x] -> A[y]] -> E[z] }",
355 "{ A[0] }",
356 "{ T[A[0] -> B[y]] -> C[z] }" },
359 C(&isl::union_map::intersect_range_wrapped_domain, {
360 { "{ [A[x] -> B[y]] -> C[z]; [D[x] -> A[y]] -> E[z] }",
361 "{ A[0] }",
362 "{ }" },
363 { "{ C[z] -> [A[x] -> B[y]]; E[z] -> [D[x] -> A[y]] }",
364 "{ A[0] }",
365 "{ C[z] -> [A[0] -> B[y]] }" },
366 { "{ C[z] -> T[A[x] -> B[y]]; E[z] -> [D[x] -> A[y]] }",
367 "{ A[0] }",
368 "{ C[z] -> T[A[0] -> B[y]] }" },
372 /* Perform some basic gist tests.
374 static void test_gist(isl::ctx ctx)
376 C(arg<isl::set>(&isl::pw_aff::gist), {
377 { "{ [x] -> [x] : x != 0 }", "{ [x] : x < -1 or x > 1 }",
378 "{ [x] -> [x] }" },
381 C(&isl::pw_aff::gist_params, {
382 { "[N] -> { D[x] -> [x] : N >= 0; D[x] -> [0] : N < 0 }",
383 "[N] -> { : N >= 0 }",
384 "[N] -> { D[x] -> [x] }" },
387 C(arg<isl::set>(&isl::multi_aff::gist), {
388 { "{ A[i] -> B[i, i] }", "{ A[0] }",
389 "{ A[i] -> B[0, 0] }" },
390 { "[N] -> { A[i] -> B[i, N] }", "[N] -> { A[0] : N = 5 }",
391 "[N] -> { A[i] -> B[0, 5] }" },
392 { "[N] -> { B[N + 1, N] }", "[N] -> { : N = 5 }",
393 "[N] -> { B[6, 5] }" },
394 { "[N] -> { A[i] -> B[] }", "[N] -> { A[0] : N = 5 }",
395 "[N] -> { A[i] -> B[] }" },
396 { "[N] -> { B[] }", "[N] -> { : N = 5 }",
397 "[N] -> { B[] }" },
400 C(&isl::multi_aff::gist_params, {
401 { "[N] -> { A[i] -> B[i, N] }", "[N] -> { : N = 5 }",
402 "[N] -> { A[i] -> B[i, 5] }" },
403 { "[N] -> { B[N + 1, N] }", "[N] -> { : N = 5 }",
404 "[N] -> { B[6, 5] }" },
405 { "[N] -> { A[i] -> B[] }", "[N] -> { : N = 5 }",
406 "[N] -> { A[i] -> B[] }" },
407 { "[N] -> { B[] }", "[N] -> { : N = 5 }",
408 "[N] -> { B[] }" },
411 C(arg<isl::set>(&isl::multi_pw_aff::gist), {
412 { "{ A[i] -> B[i, i] : i >= 0 }", "{ A[0] }",
413 "{ A[i] -> B[0, 0] }" },
414 { "[N] -> { A[i] -> B[i, N] : N >= 0 }", "[N] -> { A[0] : N = 5 }",
415 "[N] -> { A[i] -> B[0, 5] }" },
416 { "[N] -> { B[N + 1, N] }", "[N] -> { : N = 5 }",
417 "[N] -> { B[6, 5] }" },
418 { "[N] -> { A[i] -> B[] }", "[N] -> { A[0] : N = 5 }",
419 "[N] -> { A[i] -> B[] }" },
420 { "[N] -> { B[] }", "[N] -> { : N = 5 }",
421 "[N] -> { B[] }" },
422 { "{ A[i=0:10] -> B[i] }", "{ A[5] }",
423 "{ A[i] -> B[5] }" },
424 { "{ A[0:10] -> B[] }", "{ A[0:10] }",
425 "{ A[i] -> B[] }" },
426 { "[N] -> { A[i] -> B[] : N >= 0 }", "[N] -> { A[0] : N = 5 }",
427 "[N] -> { A[i] -> B[] }" },
428 { "[N] -> { B[] : N >= 0 }", "[N] -> { : N = 5 }",
429 "[N] -> { B[] }" },
430 { "[N] -> { B[] : N = 5 }", "[N] -> { : N >= 0 }",
431 "[N] -> { B[] : N = 5 }" },
434 C(&isl::multi_pw_aff::gist_params, {
435 { "[N] -> { A[i] -> B[i, N] : N >= 0 }", "[N] -> { : N = 5 }",
436 "[N] -> { A[i] -> B[i, 5] }" },
437 { "[N] -> { B[N + 1, N] }", "[N] -> { : N = 5 }",
438 "[N] -> { B[6, 5] }" },
439 { "[N] -> { A[i] -> B[] : N >= 0 }", "[N] -> { : N = 5 }",
440 "[N] -> { A[i] -> B[] }" },
441 { "[N] -> { B[] : N >= 0 }", "[N] -> { : N = 5 }",
442 "[N] -> { B[] }" },
443 { "[N] -> { B[] : N >= 5 }", "[N] -> { : N >= 0 }",
444 "[N] -> { B[] : N >= 5 }" },
447 C(&isl::multi_union_pw_aff::gist, {
448 { "C[{ B[i,i] -> [3i] }]", "{ B[i,i] }",
449 "C[{ B[i,j] -> [3i] }]" },
450 { "(C[] : { B[i,i] })", "{ B[i,i] }",
451 "(C[] : { B[i,j] })" },
452 { "[N] -> (C[] : { B[N,N] })", "[N] -> { B[N,N] }",
453 "[N] -> (C[] : { B[i,j] })" },
454 { "C[]", "{ B[i,i] }",
455 "C[]" },
456 { "[N] -> (C[] : { B[i,i] : N >= 0 })", "{ B[i,i] }",
457 "[N] -> (C[] : { B[i,j] : N >= 0 })" },
458 { "[N] -> (C[] : { : N >= 0 })", "{ B[i,i] }",
459 "[N] -> (C[] : { : N >= 0 })" },
460 { "[N] -> (C[] : { : N >= 0 })", "[N] -> { B[i,i] : N >= 0 }",
461 "[N] -> C[]" },
464 C(&isl::multi_union_pw_aff::gist_params, {
465 { "[N] -> C[{ B[i,i] -> [3i + N] }]", "[N] -> { : N = 1 }",
466 "[N] -> C[{ B[i,i] -> [3i + 1] }]" },
467 { "C[{ B[i,i] -> [3i] }]", "[N] -> { : N >= 0 }",
468 "[N] -> C[{ B[i,i] -> [3i] }]" },
469 { "[N] -> C[{ B[i,i] -> [3i] : N >= 0 }]", "[N] -> { : N >= 0 }",
470 "[N] -> C[{ B[i,i] -> [3i] }]" },
471 { "[N] -> C[{ B[i,i] -> [3i] : N >= 1 }]", "[N] -> { : N >= 0 }",
472 "[N] -> C[{ B[i,i] -> [3i] : N >= 1 }]" },
473 { "[N] -> (C[] : { B[i,i] : N >= 0 })", "[N] -> { : N >= 0 }",
474 "[N] -> (C[] : { B[i,i] })" },
475 { "[N] -> (C[] : { : N >= 0 })", "[N] -> { : N >= 0 }",
476 "[N] -> C[]" },
477 { "C[{ B[i,i] -> [3i] }]", "[N] -> { : N >= 0 }",
478 "[N] -> C[{ B[i,i] -> [3i] }]" },
482 /* Perform tests that project out parameters.
484 static void test_project(isl::ctx ctx)
486 C(arg<isl::id>(&isl::union_map::project_out_param), {
487 { "[N] -> { D[i] -> A[0:N-1]; D[i] -> B[i] }", "N",
488 "{ D[i] -> A[0:]; D[i] -> B[i] }" },
489 { "[N] -> { D[i] -> A[0:N-1]; D[i] -> B[i] }", "M",
490 "[N] -> { D[i] -> A[0:N-1]; D[i] -> B[i] }" },
493 C(arg<isl::id_list>(&isl::union_map::project_out_param), {
494 { "[M, N, O] -> { D[i] -> A[j] : i <= j < M, N, O }", "(M, N)",
495 "[O] -> { D[i] -> A[j] : i <= j < O }" },
499 /* Perform some basic reverse tests.
501 static void test_reverse(isl::ctx ctx)
503 C(&isl::aff::domain_reverse, {
504 { "{ T[A[] -> B[*]] -> [0] }",
505 "{ [B[*] -> A[]] -> [0] }" },
506 { "{ T[A[] -> A[]] -> [0] }",
507 "{ T[A[] -> A[]] -> [0] }" },
508 { "{ [A[x] -> B[y]] -> [5*(x // 2) + 7*(y // 3)] }",
509 "{ [B[y] -> A[x]] -> [5*(x // 2) + 7*(y // 3)] }" },
512 C(&isl::multi_aff::domain_reverse, {
513 { "{ [A[x] -> B[y]] -> [5*(x // 2) + 7*(y // 3)] }",
514 "{ [B[y] -> A[x]] -> [5*(x // 2) + 7*(y // 3)] }" },
515 { "{ [A[x] -> B[y]] -> T[5*(x // 2) + 7*(y // 3), 0] }",
516 "{ [B[y] -> A[x]] -> T[5*(x // 2) + 7*(y // 3), 0] }" },
519 C(&isl::set::wrapped_reverse, {
520 { "{ T[A[] -> B[*]] }",
521 "{ [B[*] -> A[]] }" },
522 { "{ T[A[] -> A[]] }",
523 "{ T[A[] -> A[]] }" },
524 { "{ [A[x] -> B[2x]] }",
525 "{ [B[y] -> A[x]] : y = 2x }" },
528 C(&isl::pw_aff::domain_reverse, {
529 { "{ [A[x] -> B[y]] -> [5*(x // 2) + 7*(y // 3)] }",
530 "{ [B[y] -> A[x]] -> [5*(x // 2) + 7*(y // 3)] }" },
531 { "{ [A[x] -> B[y]] -> [5*(x // 2) + 7*(y // 3)] : x > y }",
532 "{ [B[y] -> A[x]] -> [5*(x // 2) + 7*(y // 3)] : x > y }" },
533 { "{ [A[i] -> B[i + 1]] -> [i + 2] }",
534 "{ [B[i] -> A[i - 1]] -> [i + 1] }" },
537 C(&isl::pw_multi_aff::domain_reverse, {
538 { "{ [A[x] -> B[y]] -> T[5*(x // 2) + 7*(y // 3), 0] : x > y }",
539 "{ [B[y] -> A[x]] -> T[5*(x // 2) + 7*(y // 3), 0] : x > y }" },
540 { "{ [A[i] -> B[i + 1]] -> T[0, i + 2] }",
541 "{ [B[i] -> A[i - 1]] -> T[0, i + 1] }" },
544 C(&isl::multi_pw_aff::domain_reverse, {
545 { "{ [A[x] -> B[y]] -> T[5*(x // 2) + 7*(y // 3) : x > y, 0] }",
546 "{ [B[y] -> A[x]] -> T[5*(x // 2) + 7*(y // 3) : x > y, 0] }" },
549 C(&isl::map::domain_reverse, {
550 { "{ [A[] -> B[]] -> [C[] -> D[]] }",
551 "{ [B[] -> A[]] -> [C[] -> D[]] }" },
552 { "{ N[B[] -> C[]] -> A[] }",
553 "{ [C[] -> B[]] -> A[] }" },
554 { "{ N[B[x] -> B[y]] -> A[] }",
555 "{ N[B[*] -> B[*]] -> A[] }" },
558 C(&isl::union_map::domain_reverse, {
559 { "{ [A[] -> B[]] -> [C[] -> D[]] }",
560 "{ [B[] -> A[]] -> [C[] -> D[]] }" },
561 { "{ A[] -> [B[] -> C[]]; A[] -> B[]; A[0] -> N[B[1] -> B[2]] }",
562 "{ }" },
563 { "{ N[B[] -> C[]] -> A[] }",
564 "{ [C[] -> B[]] -> A[] }" },
565 { "{ N[B[x] -> B[y]] -> A[] }",
566 "{ N[B[*] -> B[*]] -> A[] }" },
569 C(&isl::union_map::range_reverse, {
570 { "{ A[] -> [B[] -> C[]]; A[] -> B[]; A[0] -> N[B[1] -> B[2]] }",
571 "{ A[] -> [C[] -> B[]]; A[0] -> N[B[2] -> B[1]] }" },
572 { "{ A[] -> N[B[] -> C[]] }",
573 "{ A[] -> [C[] -> B[]] }" },
574 { "{ A[] -> N[B[x] -> B[y]] }",
575 "{ A[] -> N[B[*] -> B[*]] }" },
579 /* Perform some basic scaling tests.
581 static void test_scale(isl::ctx ctx)
583 C(arg<isl::multi_val>(&isl::pw_multi_aff::scale), {
584 { "{ A[a] -> B[a, a + 1, a - 1] : a >= 0 }", "{ B[2, 7, 0] }",
585 "{ A[a] -> B[2a, 7a + 7, 0] : a >= 0 }" },
587 C(arg<isl::multi_val>(&isl::pw_multi_aff::scale), {
588 { "{ A[a] -> B[1, a - 1] : a >= 0 }", "{ B[1/2, 7] }",
589 "{ A[a] -> B[1/2, 7a - 7] : a >= 0 }" },
592 C(arg<isl::multi_val>(&isl::pw_multi_aff::scale_down), {
593 { "{ A[a] -> B[a, a + 1] : a >= 0 }", "{ B[2, 7] }",
594 "{ A[a] -> B[a/2, (a + 1)/7] : a >= 0 }" },
596 C(arg<isl::multi_val>(&isl::pw_multi_aff::scale_down), {
597 { "{ A[a] -> B[a, a - 1] : a >= 0 }", "{ B[2, 1/7] }",
598 "{ A[a] -> B[a/2, 7a - 7] : a >= 0 }" },
602 /* Perform some basic isl::id_to_id tests.
604 static void test_id_to_id(isl::ctx ctx)
606 C((arg<isl::id, isl::id>(&isl::id_to_id::set)), {
607 { "{ }", "a", "b",
608 "{ a: b }" },
609 { "{ a: b }", "a", "b",
610 "{ a: b }" },
611 { "{ a: c }", "a", "b",
612 "{ a: b }" },
613 { "{ a: b }", "b", "a",
614 "{ a: b, b: a }" },
615 { "{ a: b }", "b", "a",
616 "{ b: a, a: b }" },
620 /* The list of tests to perform.
622 static std::vector<std::pair<const char *, void (*)(isl::ctx)>> tests =
624 { "space", &test_space },
625 { "conversion", &test_conversion },
626 { "preimage", &test_preimage },
627 { "fixed power", &test_fixed_power },
628 { "intersect", &test_intersect },
629 { "gist", &test_gist },
630 { "project out parameters", &test_project },
631 { "reverse", &test_reverse },
632 { "scale", &test_scale },
633 { "id-to-id", &test_id_to_id },
636 /* Perform some basic checks by means of the C++ bindings.
638 int main(int argc, char **argv)
640 int ret = EXIT_SUCCESS;
641 struct isl_ctx *ctx;
642 struct isl_options *options;
644 options = isl_options_new_with_defaults();
645 assert(options);
646 argc = isl_options_parse(options, argc, argv, ISL_ARG_ALL);
647 ctx = isl_ctx_alloc_with_options(&isl_options_args, options);
649 try {
650 for (const auto &f : tests) {
651 std::cout << f.first << "\n";
652 f.second(ctx);
654 } catch (const isl::exception &e) {
655 std::cerr << e.what() << "\n";
656 ret = EXIT_FAILURE;
659 isl_ctx_free(ctx);
660 return ret;