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