Skip to content

Commit 9c02918

Browse files
committed
Example
1 parent d1824d6 commit 9c02918

1 file changed

Lines changed: 206 additions & 1 deletion

File tree

README.md

Lines changed: 206 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,206 @@
1-
# How to use isl via the C++ / Python interface
1+
Warning: This is a proposal, which does not document the current isl
2+
3+
# How to use isl via the C++ and Python interface
4+
5+
## Constructing an integer set or map (isl::set / isl::map)
6+
7+
We create an integer set as follows. We first create a set of identifiers for
8+
each of the needed dimensions (`isl::id Id_N(ctx, "N"`). We then introduce
9+
initial expressions for all identifiers and required constants (`isl::pw_aff
10+
N(Id_N), Ten(ctx, 10)`). From these initial expressions the actual affine
11+
expressions are constructed (`isl::pw_aff LHS = Two.mul(M)`). Pairs of
12+
expressions are combined with the operators lt_set (<), le_set (<=), ge_set
13+
(>=), gt_set (>), eq_set (=), ne_set (!=) into a parameteric set of constraints
14+
(`isl::set PSet = LHS.le_set(RHS)`). Finally, a non-parameteric set is
15+
constructed from 1) a parameteric set specifying its constraints and 2) a list
16+
of identifiers that specify the parameter dimensions that should be promoted to
17+
set dimensions (`isl::set Set({Id_i, Id_j}, PSet)`). Similary, a map can be
18+
constructed by providing two lists of identifiers defining the input and output
19+
dimensions (`isl::map Map({Id_i}, {Id_j}, PSet)`)
20+
21+
Example:
22+
*{ [N, M] -> { [i,j] : 2 * M + 3 * N <= 2 * i + j + 10 }*
23+
24+
### Explicit Interface (today)
25+
26+
We first describe how the current C++ interface should be used to construct
27+
isl sets, just proposing a small number of extensions beyond what exists
28+
today. The resulting code is still somehow verbose, but very explicit.
29+
30+
31+
```
32+
// Identifiers
33+
isl::id Id_N(ctx, "N"), Id_M(ctx, "M"), Id_i(ctx, "i"), Id_j(ctx, "j");
34+
35+
// One (piece-wise) affine expression per identifier
36+
// [N] -> { [(N)]}, [N] -> { [(M)]}, [i] -> { [(i)]}, [j] -> { [(j)]}
37+
isl::pw_aff N(Id_N), M(Id_M), i(Id_i), j(Id_j);
38+
39+
// One (piece-wise) affine expression per constant
40+
// {[(10)]}, {[(2)]}, {[(3)]}
41+
isl::pw_aff Ten(ctx, 10), Two(ctx, 2), Three(ctx, 3);
42+
43+
// Build the left and right hand side of the expression
44+
// [M, N] -> { [(2 * M + 3 * M)] }
45+
isl::pw_aff LHS = Two.mul(M).add(Three.mul(N));
46+
47+
// [M, N] -> { [(2 * i + j + 10)] }
48+
isl::pw_aff RHS = Two.mul(i).add(j).add(Ten);
49+
50+
// [N, M, i, j] -> { : 2 * M + 3 * N <= 2 * i + j + 10 }
51+
isl::set PSet = LHS.le_set(RHS);
52+
53+
// [N, M] -> { [i, j] : 2 * M + 3 * N <= 2 * i + j + 10 }
54+
isl::set Set({Id_i, Id_j}, PSet);
55+
56+
// [N, M] -> { [i] -> [j] : 2 * M + 3 * N <= 2 * i + j + 10 }
57+
isl::map Map({Id_i}, {Id_j}, PSet);
58+
```
59+
60+
#### New functions
61+
62+
```
63+
__isl_export
64+
isl_pw_aff *isl_pw_aff_param_on_domain_id(isl_id *);
65+
__isl_constructor
66+
isl_set *isl_set_from_id_list_and_set(isl_id_list *dims, isl_set *pset);
67+
__isl_constructor
68+
isl_map *isl_map_from_id_list_and_set(isl_id_list *input_dims, isl_id_list *output_dims, isl_set *pset);
69+
```
70+
71+
72+
73+
#### Notes
74+
75+
- Currently instead of isl::aff, we always need to use isl::pw_aff, as
76+
isl::aff does not allow for parameter auto-alignment. This should be
77+
changed, but will require more work. We should likely write the
78+
documentation in terms of isl::pw_aff for now.
79+
80+
#### Choices
81+
82+
83+
##### Return type of the comparision operator
84+
85+
There have been concerns that the return type of the `le_set` expression
86+
should not be a set, but rather a constraint.
87+
88+
```
89+
// [N, M, i, j] -> { : 2 * M + 3 * N <= 2 * i + j + 10 }
90+
isl::constraint PSet = LHS.le_set(RHS);
91+
```
92+
93+
##### How to introduce parameters
94+
95+
We can either use a constructor (in the proposal):
96+
97+
```
98+
isl::set PSet("[N, M, i, j] -> { : 2 * M + 3 * N <= 2 * i + j + 10 }")
99+
100+
// { [N, M] -> { [i,j] : 2 * M + 3 * N <= 2 * i + j + 10 }
101+
isl::set Set({i,j}, PSet);
102+
// { [N, M] -> { [i]->[j] : 2 * M + 3 * N <= 2 * i + j + 10 }
103+
isl::map Map({i}, {j}, PSet);
104+
```
105+
106+
or a set of member functions.
107+
108+
```
109+
isl::set PSet("[N, M, i, j] -> { : 2 * M + 3 * N <= 2 * i + j + 10 }")
110+
111+
// { [N, M] -> { [i,j] : 2 * M + 3 * N <= 2 * i + j + 10 }
112+
isl::set PSet.inputs(i,j);
113+
// { [N, M] -> { [i]->[j] : 2 * M + 3 * N <= 2 * i + j + 10 }
114+
isl::map PSet.inputs(i).outputs(j);
115+
```
116+
117+
### Streamlined interface
118+
119+
In certain use cases a more streamlined interface might be useful. Here is
120+
an example which includes:
121+
122+
- operator overloading of all operators
123+
- automatic conversion from isl::id to isl::aff
124+
- automatic conversion from int to isl::aff
125+
- a default context
126+
127+
```
128+
isl::id N("N"), M("M"), i("i"), j("j');
129+
130+
isl::aff LHS = 2 * M + 3 * N; // natural precedence works
131+
isl::aff RHS = 2 * i + j + 10;
132+
133+
// { [N, M] -> { [i,j] : 2 * M + 3 * N <= 2 * i + j + 10 }
134+
isl::set Set({i,j}, LHS <= RHS);
135+
136+
// { [N, M] -> { [i]->[j] : 2 * M + 3 * N <= 2 * i + j + 10 }
137+
isl::map Map({i}, {j}, LHS <= RHS);
138+
```
139+
140+
#### Choices
141+
142+
#### More efficient construction of parameter isl::aff's
143+
144+
When constructing an affine expression for a parameter, the explicit interface
145+
requires two steps. First the construction of an isl::id and then its conversion
146+
to a isl::aff. It would be nice if just one step would be needed. There
147+
are two options:
148+
149+
1) Construction of isl::aff's from strings.
150+
151+
```
152+
isl::aff A = ...
153+
154+
// [N] -> { [(N)] }
155+
isl::aff N(ctx, "N");
156+
157+
isl::aff X = A.add(N);
158+
```
159+
160+
2) Automatic conversion from isl::id to aff
161+
162+
```
163+
isl::aff A = ...
164+
165+
// [N] -> { [(N)] }
166+
isl::id N(ctx, "N");
167+
168+
isl::aff X = A.add(N);
169+
```
170+
171+
172+
##### Use of a thread-local context
173+
174+
Instead of always providing a ctx object, the bindings could provide a thread
175+
local ctx.
176+
177+
178+
Explicit context:
179+
```
180+
isl::id N(ctx, "N");
181+
```
182+
183+
Implicit context:
184+
```
185+
isl::id N("N");
186+
```
187+
188+
##### Overloading of operators
189+
190+
Instead of explicit calling the explicit
191+
192+
Without overloading:
193+
```
194+
isl::pw_aff = A.add(B).add(Three.mul(C));
195+
```
196+
197+
With overloading
198+
```
199+
isl::pw_aff = A + B + 3 * C;
200+
```
201+
202+
*Warning*: Overloading of the comparision operators may cause confusion as the
203+
result is not a boolean expression.
204+
205+
206+

0 commit comments

Comments
 (0)