Home | History | Annotate | Line # | Download | only in dist
      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