Skip to content

Commit 18d5e58

Browse files
committed
Example
1 parent d1824d6 commit 18d5e58

1 file changed

Lines changed: 212 additions & 1 deletion

File tree

README.md

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

0 commit comments

Comments
 (0)