isl_sched_graph_extract_sccs: extract out isl_sched_graph_extract_scc
[isl.git] / isl_test2.cc
blobaec1c9bb3049d5971e999250a14508808838062d
1 #include <assert.h>
2 #include <stdlib.h>
4 #include <functional>
5 #include <iostream>
6 #include <sstream>
7 #include <string>
8 #include <type_traits>
9 #include <utility>
10 #include <vector>
12 #include <isl/cpp.h>
14 /* A binary isl function that appears in the C++ bindings
15 * as a unary method in a class T, taking an extra argument
16 * of type A1 and returning an object of type R.
18 template <typename A1, typename R, typename T>
19 using binary_fn = R (T::*)(A1) const;
21 /* A function for selecting an overload of a pointer to a unary C++ method
22 * based on the single argument type.
23 * The object type and the return type are meant to be deduced.
25 template <typename A1, typename R, typename T>
26 static binary_fn<A1, R, T> const arg(const binary_fn<A1, R, T> &fn)
28 return fn;
31 /* A description of the input and the output of a unary operation.
33 struct unary {
34 const char *arg;
35 const char *res;
38 /* A description of the inputs and the output of a binary operation.
40 struct binary {
41 const char *arg1;
42 const char *arg2;
43 const char *res;
46 /* A template function for checking whether two objects
47 * of the same (isl) type are (obviously) equal.
48 * The spelling depends on the isl type and
49 * in particular on whether an equality method is available or
50 * whether only obvious equality can be tested.
52 template <typename T, typename std::decay<decltype(
53 std::declval<T>().is_equal(std::declval<T>()))>::type = true>
54 static bool is_equal(const T &a, const T &b)
56 return a.is_equal(b);
58 template <typename T, typename std::decay<decltype(
59 std::declval<T>().plain_is_equal(std::declval<T>()))>::type = true>
60 static bool is_equal(const T &a, const T &b)
62 return a.plain_is_equal(b);
65 /* A helper macro for throwing an isl::exception_invalid with message "msg".
67 #define THROW_INVALID(msg) \
68 isl::exception::throw_error(isl_error_invalid, msg, __FILE__, __LINE__)
70 /* Run a sequence of tests of method "fn" with stringification "name" and
71 * with input and output described by "test",
72 * throwing an exception when an unexpected result is produced.
74 template <typename R, typename T>
75 static void test(isl::ctx ctx, R (T::*fn)() const, const std::string &name,
76 const std::vector<unary> &tests)
78 for (const auto &test : tests) {
79 T obj(ctx, test.arg);
80 R expected(ctx, test.res);
81 const auto &res = (obj.*fn)();
82 std::ostringstream ss;
84 if (is_equal(expected, res))
85 continue;
87 ss << name << "(" << test.arg << ") =\n"
88 << res << "\n"
89 << "expecting:\n"
90 << expected;
91 THROW_INVALID(ss.str().c_str());
95 /* Run a sequence of tests of method "fn" with stringification "name" and
96 * with inputs and output described by "test",
97 * throwing an exception when an unexpected result is produced.
99 template <typename R, typename T, typename A1>
100 static void test(isl::ctx ctx, R (T::*fn)(A1) const, const std::string &name,
101 const std::vector<binary> &tests)
103 for (const auto &test : tests) {
104 T obj(ctx, test.arg1);
105 A1 arg1(ctx, test.arg2);
106 R expected(ctx, test.res);
107 const auto &res = (obj.*fn)(arg1);
108 std::ostringstream ss;
110 if (is_equal(expected, res))
111 continue;
113 ss << name << "(" << test.arg1 << ", " << test.arg2 << ") =\n"
114 << res << "\n"
115 << "expecting:\n"
116 << test.res;
117 THROW_INVALID(ss.str().c_str());
121 /* A helper macro that calls test with as implicit initial argument "ctx" and
122 * as extra argument a stringification of "FN".
124 #define C(FN, ...) test(ctx, FN, #FN, __VA_ARGS__)
126 /* Perform some basic isl::space tests.
128 static void test_space(isl::ctx ctx)
130 C(&isl::space::domain, {
131 { "{ A[] -> B[] }", "{ A[] }" },
132 { "{ A[C[] -> D[]] -> B[E[] -> F[]] }", "{ A[C[] -> D[]] }" },
135 C(&isl::space::range, {
136 { "{ A[] -> B[] }", "{ B[] }" },
137 { "{ A[C[] -> D[]] -> B[E[] -> F[]] }", "{ B[E[] -> F[]] }" },
140 C(&isl::space::params, {
141 { "{ A[] -> B[] }", "{ : }" },
142 { "{ A[C[] -> D[]] -> B[E[] -> F[]] }", "{ : }" },
146 /* Perform some basic conversion tests.
148 static void test_conversion(isl::ctx ctx)
150 C(&isl::multi_pw_aff::as_set, {
151 { "[n] -> { [] : n >= 0 } ",
152 "[n] -> { [] : n >= 0 } " },
156 /* Perform some basic preimage tests.
158 static void test_preimage(isl::ctx ctx)
160 C(arg<isl::multi_aff>(&isl::set::preimage), {
161 { "{ B[i,j] : 0 <= i < 10 and 0 <= j < 100 }",
162 "{ A[j,i] -> B[i,j] }",
163 "{ A[j,i] : 0 <= i < 10 and 0 <= j < 100 }" },
164 { "{ rat: B[i,j] : 0 <= i, j and 3 i + 5 j <= 100 }",
165 "{ A[a,b] -> B[a/2,b/6] }",
166 "{ rat: A[a,b] : 0 <= a, b and 9 a + 5 b <= 600 }" },
167 { "{ B[i,j] : 0 <= i, j and 3 i + 5 j <= 100 }",
168 "{ A[a,b] -> B[a/2,b/6] }",
169 "{ A[a,b] : 0 <= a, b and 9 a + 5 b <= 600 and "
170 "exists i,j : a = 2 i and b = 6 j }" },
171 { "[n] -> { S[i] : 0 <= i <= 100 }", "[n] -> { S[n] }",
172 "[n] -> { : 0 <= n <= 100 }" },
173 { "{ B[i] : 0 <= i < 100 and exists a : i = 4 a }",
174 "{ A[a] -> B[2a] }",
175 "{ A[a] : 0 <= a < 50 and exists b : a = 2 b }" },
176 { "{ B[i] : 0 <= i < 100 and exists a : i = 4 a }",
177 "{ A[a] -> B[([a/2])] }",
178 "{ A[a] : 0 <= a < 200 and exists b : [a/2] = 4 b }" },
179 { "{ B[i,j,k] : 0 <= i,j,k <= 100 }",
180 "{ A[a] -> B[a,a,a/3] }",
181 "{ A[a] : 0 <= a <= 100 and exists b : a = 3 b }" },
182 { "{ B[i,j] : j = [(i)/2] } ", "{ A[i,j] -> B[i/3,j] }",
183 "{ A[i,j] : j = [(i)/6] and exists a : i = 3 a }" },
186 C(arg<isl::multi_aff>(&isl::union_map::preimage_domain), {
187 { "{ B[i,j] -> C[2i + 3j] : 0 <= i < 10 and 0 <= j < 100 }",
188 "{ A[j,i] -> B[i,j] }",
189 "{ A[j,i] -> C[2i + 3j] : 0 <= i < 10 and 0 <= j < 100 }" },
190 { "{ B[i] -> C[i]; D[i] -> E[i] }",
191 "{ A[i] -> B[i + 1] }",
192 "{ A[i] -> C[i + 1] }" },
193 { "{ B[i] -> C[i]; B[i] -> E[i] }",
194 "{ A[i] -> B[i + 1] }",
195 "{ A[i] -> C[i + 1]; A[i] -> E[i + 1] }" },
196 { "{ B[i] -> C[([i/2])] }",
197 "{ A[i] -> B[2i] }",
198 "{ A[i] -> C[i] }" },
199 { "{ B[i,j] -> C[([i/2]), ([(i+j)/3])] }",
200 "{ A[i] -> B[([i/5]), ([i/7])] }",
201 "{ A[i] -> C[([([i/5])/2]), ([(([i/5])+([i/7]))/3])] }" },
202 { "[N] -> { B[i] -> C[([N/2]), i, ([N/3])] }",
203 "[N] -> { A[] -> B[([N/5])] }",
204 "[N] -> { A[] -> C[([N/2]), ([N/5]), ([N/3])] }" },
205 { "{ B[i] -> C[i] : exists a : i = 5 a }",
206 "{ A[i] -> B[2i] }",
207 "{ A[i] -> C[2i] : exists a : 2i = 5 a }" },
208 { "{ B[i] -> C[i] : exists a : i = 2 a; "
209 "B[i] -> D[i] : exists a : i = 2 a + 1 }",
210 "{ A[i] -> B[2i] }",
211 "{ A[i] -> C[2i] }" },
212 { "{ A[i] -> B[i] }", "{ C[i] -> A[(i + floor(i/3))/2] }",
213 "{ C[i] -> B[j] : 2j = i + floor(i/3) }" },
216 C(arg<isl::multi_aff>(&isl::union_map::preimage_range), {
217 { "[M] -> { A[a] -> B[a] }", "[M] -> { C[] -> B[floor(M/2)] }",
218 "[M] -> { A[floor(M/2)] -> C[] }" },
222 /* Perform some basic intersection tests.
224 static void test_intersect(isl::ctx ctx)
226 C(&isl::union_map::intersect_domain_wrapped_domain, {
227 { "{ [A[x] -> B[y]] -> C[z]; [D[x] -> A[y]] -> E[z] }",
228 "{ A[0] }",
229 "{ [A[0] -> B[y]] -> C[z] }" },
230 { "{ C[z] -> [A[x] -> B[y]]; E[z] -> [D[x] -> A[y]] }",
231 "{ A[0] }",
232 "{ }" },
235 C(&isl::union_map::intersect_range_wrapped_domain, {
236 { "{ [A[x] -> B[y]] -> C[z]; [D[x] -> A[y]] -> E[z] }",
237 "{ A[0] }",
238 "{ }" },
239 { "{ C[z] -> [A[x] -> B[y]]; E[z] -> [D[x] -> A[y]] }",
240 "{ A[0] }",
241 "{ C[z] -> [A[0] -> B[y]] }" },
245 /* Perform some basic gist tests.
247 static void test_gist(isl::ctx ctx)
249 C(&isl::pw_aff::gist_params, {
250 { "[N] -> { D[x] -> [x] : N >= 0; D[x] -> [0] : N < 0 }",
251 "[N] -> { : N >= 0 }",
252 "[N] -> { D[x] -> [x] }" },
256 /* Perform some basic scaling tests.
258 static void test_scale(isl::ctx ctx)
260 C(arg<isl::multi_val>(&isl::pw_multi_aff::scale), {
261 { "{ A[a] -> B[a, a + 1, a - 1] : a >= 0 }", "{ B[2, 7, 0] }",
262 "{ A[a] -> B[2a, 7a + 7, 0] : a >= 0 }" },
264 C(arg<isl::multi_val>(&isl::pw_multi_aff::scale), {
265 { "{ A[a] -> B[a, a - 1] : a >= 0 }", "{ B[1/2, 7] }",
266 "{ A[a] -> B[a/2, 7a - 7] : a >= 0 }" },
269 C(arg<isl::multi_val>(&isl::pw_multi_aff::scale_down), {
270 { "{ A[a] -> B[a, a + 1] : a >= 0 }", "{ B[2, 7] }",
271 "{ A[a] -> B[a/2, (a + 1)/7] : a >= 0 }" },
273 C(arg<isl::multi_val>(&isl::pw_multi_aff::scale_down), {
274 { "{ A[a] -> B[a, a - 1] : a >= 0 }", "{ B[2, 1/7] }",
275 "{ A[a] -> B[a/2, 7a - 7] : a >= 0 }" },
279 /* The list of tests to perform.
281 static std::vector<std::pair<const char *, void (*)(isl::ctx)>> tests =
283 { "space", &test_space },
284 { "conversion", &test_conversion },
285 { "preimage", &test_preimage },
286 { "intersect", &test_intersect },
287 { "gist", &test_gist },
288 { "scale", &test_scale },
291 /* Perform some basic checks by means of the C++ bindings.
293 int main(int argc, char **argv)
295 int ret = EXIT_SUCCESS;
296 struct isl_ctx *ctx;
297 struct isl_options *options;
299 options = isl_options_new_with_defaults();
300 assert(options);
301 argc = isl_options_parse(options, argc, argv, ISL_ARG_ALL);
302 ctx = isl_ctx_alloc_with_options(&isl_options_args, options);
304 try {
305 for (const auto &f : tests) {
306 std::cout << f.first << "\n";
307 f.second(ctx);
309 } catch (const isl::exception &e) {
310 std::cerr << e.what() << "\n";
311 ret = EXIT_FAILURE;
314 isl_ctx_free(ctx);
315 return ret;