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
)
31 /* A description of the inputs and the output of a binary operation.
39 /* A template function for checking whether two objects
40 * of the same (isl) type are (obviously) equal.
41 * The spelling depends on the isl type and
42 * in particular on whether an equality method is available or
43 * whether only obvious equality can be tested.
45 template <typename T
, typename
std::decay
<decltype(
46 std::declval
<T
>().is_equal(std::declval
<T
>()))>::type
= true>
47 static bool is_equal(const T
&a
, const T
&b
)
51 template <typename T
, typename
std::decay
<decltype(
52 std::declval
<T
>().plain_is_equal(std::declval
<T
>()))>::type
= true>
53 static bool is_equal(const T
&a
, const T
&b
)
55 return a
.plain_is_equal(b
);
58 /* A helper macro for throwing an isl::exception_invalid with message "msg".
60 #define THROW_INVALID(msg) \
61 isl::exception::throw_error(isl_error_invalid, msg, __FILE__, __LINE__)
63 /* Run a sequence of tests of method "fn" with stringification "name" and
64 * with inputs and output described by "test",
65 * throwing an exception when an unexpected result is produced.
67 template <typename R
, typename T
, typename A1
>
68 static void test(isl::ctx ctx
, R (T::*fn
)(A1
) const, const std::string
&name
,
69 const std::vector
<binary
> &tests
)
71 for (const auto &test
: tests
) {
72 T
obj(ctx
, test
.arg1
);
73 A1
arg1(ctx
, test
.arg2
);
74 R
expected(ctx
, test
.res
);
75 const auto &res
= (obj
.*fn
)(arg1
);
76 std::ostringstream ss
;
78 if (is_equal(expected
, res
))
81 ss
<< name
<< "(" << test
.arg1
<< ", " << test
.arg2
<< ") =\n"
85 THROW_INVALID(ss
.str().c_str());
89 /* A helper macro that calls test with as implicit initial argument "ctx" and
90 * as extra argument a stringification of "FN".
92 #define C(FN, ...) test(ctx, FN, #FN, __VA_ARGS__)
94 /* Perform some basic preimage tests.
96 static void test_preimage(isl::ctx ctx
)
98 C(arg
<isl::multi_aff
>(&isl::set::preimage
), {
99 { "{ B[i,j] : 0 <= i < 10 and 0 <= j < 100 }",
100 "{ A[j,i] -> B[i,j] }",
101 "{ A[j,i] : 0 <= i < 10 and 0 <= j < 100 }" },
102 { "{ rat: B[i,j] : 0 <= i, j and 3 i + 5 j <= 100 }",
103 "{ A[a,b] -> B[a/2,b/6] }",
104 "{ rat: A[a,b] : 0 <= a, b and 9 a + 5 b <= 600 }" },
105 { "{ B[i,j] : 0 <= i, j and 3 i + 5 j <= 100 }",
106 "{ A[a,b] -> B[a/2,b/6] }",
107 "{ A[a,b] : 0 <= a, b and 9 a + 5 b <= 600 and "
108 "exists i,j : a = 2 i and b = 6 j }" },
109 { "[n] -> { S[i] : 0 <= i <= 100 }", "[n] -> { S[n] }",
110 "[n] -> { : 0 <= n <= 100 }" },
111 { "{ B[i] : 0 <= i < 100 and exists a : i = 4 a }",
113 "{ A[a] : 0 <= a < 50 and exists b : a = 2 b }" },
114 { "{ B[i] : 0 <= i < 100 and exists a : i = 4 a }",
115 "{ A[a] -> B[([a/2])] }",
116 "{ A[a] : 0 <= a < 200 and exists b : [a/2] = 4 b }" },
117 { "{ B[i,j,k] : 0 <= i,j,k <= 100 }",
118 "{ A[a] -> B[a,a,a/3] }",
119 "{ A[a] : 0 <= a <= 100 and exists b : a = 3 b }" },
120 { "{ B[i,j] : j = [(i)/2] } ", "{ A[i,j] -> B[i/3,j] }",
121 "{ A[i,j] : j = [(i)/6] and exists a : i = 3 a }" },
124 C(arg
<isl::multi_aff
>(&isl::union_map::preimage_domain
), {
125 { "{ B[i,j] -> C[2i + 3j] : 0 <= i < 10 and 0 <= j < 100 }",
126 "{ A[j,i] -> B[i,j] }",
127 "{ A[j,i] -> C[2i + 3j] : 0 <= i < 10 and 0 <= j < 100 }" },
128 { "{ B[i] -> C[i]; D[i] -> E[i] }",
129 "{ A[i] -> B[i + 1] }",
130 "{ A[i] -> C[i + 1] }" },
131 { "{ B[i] -> C[i]; B[i] -> E[i] }",
132 "{ A[i] -> B[i + 1] }",
133 "{ A[i] -> C[i + 1]; A[i] -> E[i + 1] }" },
134 { "{ B[i] -> C[([i/2])] }",
136 "{ A[i] -> C[i] }" },
137 { "{ B[i,j] -> C[([i/2]), ([(i+j)/3])] }",
138 "{ A[i] -> B[([i/5]), ([i/7])] }",
139 "{ A[i] -> C[([([i/5])/2]), ([(([i/5])+([i/7]))/3])] }" },
140 { "[N] -> { B[i] -> C[([N/2]), i, ([N/3])] }",
141 "[N] -> { A[] -> B[([N/5])] }",
142 "[N] -> { A[] -> C[([N/2]), ([N/5]), ([N/3])] }" },
143 { "{ B[i] -> C[i] : exists a : i = 5 a }",
145 "{ A[i] -> C[2i] : exists a : 2i = 5 a }" },
146 { "{ B[i] -> C[i] : exists a : i = 2 a; "
147 "B[i] -> D[i] : exists a : i = 2 a + 1 }",
149 "{ A[i] -> C[2i] }" },
150 { "{ A[i] -> B[i] }", "{ C[i] -> A[(i + floor(i/3))/2] }",
151 "{ C[i] -> B[j] : 2j = i + floor(i/3) }" },
154 C(arg
<isl::multi_aff
>(&isl::union_map::preimage_range
), {
155 { "[M] -> { A[a] -> B[a] }", "[M] -> { C[] -> B[floor(M/2)] }",
156 "[M] -> { A[floor(M/2)] -> C[] }" },
160 /* Perform some basic scaling tests.
162 static void test_scale(isl::ctx ctx
)
164 C(arg
<isl::multi_val
>(&isl::pw_multi_aff::scale
), {
165 { "{ A[a] -> B[a, a + 1, a - 1] : a >= 0 }", "{ B[2, 7, 0] }",
166 "{ A[a] -> B[2a, 7a + 7, 0] : a >= 0 }" },
168 C(arg
<isl::multi_val
>(&isl::pw_multi_aff::scale
), {
169 { "{ A[a] -> B[a, a - 1] : a >= 0 }", "{ B[1/2, 7] }",
170 "{ A[a] -> B[a/2, 7a - 7] : a >= 0 }" },
173 C(arg
<isl::multi_val
>(&isl::pw_multi_aff::scale_down
), {
174 { "{ A[a] -> B[a, a + 1] : a >= 0 }", "{ B[2, 7] }",
175 "{ A[a] -> B[a/2, (a + 1)/7] : a >= 0 }" },
177 C(arg
<isl::multi_val
>(&isl::pw_multi_aff::scale_down
), {
178 { "{ A[a] -> B[a, a - 1] : a >= 0 }", "{ B[2, 1/7] }",
179 "{ A[a] -> B[a/2, 7a - 7] : a >= 0 }" },
183 /* The list of tests to perform.
185 static std::vector
<std::pair
<const char *, void (*)(isl::ctx
)>> tests
=
187 { "preimage", &test_preimage
},
188 { "scale", &test_scale
},
191 /* Perform some basic checks by means of the C++ bindings.
193 int main(int argc
, char **argv
)
195 int ret
= EXIT_SUCCESS
;
197 struct isl_options
*options
;
199 options
= isl_options_new_with_defaults();
201 argc
= isl_options_parse(options
, argc
, argv
, ISL_ARG_ALL
);
202 ctx
= isl_ctx_alloc_with_options(&isl_options_args
, options
);
205 for (const auto &f
: tests
) {
206 std::cout
<< f
.first
<< "\n";
209 } catch (const isl::exception
&e
) {
210 std::cerr
<< e
.what() << "\n";