1use super::{Level, Partitioning, Space};
5use crate::{
6 Axis, ComputeScope, Coords, Coverage, Integer, IntegerExpand, MatrixAxes, Path, Step, Walk,
7};
8use cubecl::{prelude::*, unexpanded};
9
10#[derive(CubeType, Clone)]
13#[expand(derive(Clone))]
14pub struct Region {
15 step_coords: Sequence<Coords<u32>>,
16 sizes: Sequence<usize>,
18 #[cube(comptime)]
19 pub(crate) path: Path,
20}
21
22#[cube]
23impl Region {
24 pub(crate) fn new(
25 step_coords: Sequence<Coords<u32>>,
26 sizes: Sequence<usize>,
27 #[comptime] path: Path,
28 ) -> Region {
29 Region {
30 step_coords,
31 sizes,
32 path,
33 }
34 }
35
36 pub(crate) fn root(partitioning: &Partitioning) -> Region {
38 Region::rooted(
39 &partitioning.space,
40 comptime!(partitioning.levels.clone()),
41 0usize,
42 )
43 }
44
45 pub(crate) fn rooted(
47 space: &Space,
48 #[comptime] levels: Vec<Level>,
49 #[comptime] depth: usize,
50 ) -> Region {
51 Region::new(
52 Sequence::new(),
53 space.sizes.clone(),
54 comptime!(Path::new(
55 depth,
56 Partitioning::new(space.clone(), levels),
57 Vec::new()
58 )),
59 )
60 }
61
62 pub fn walk(&self) -> Walk {
64 Walk::of(&self.child(), comptime!(self.path.next()), self.clone())
65 }
66
67 pub fn leaves(&self) -> Leaves {
70 Leaves {
71 region: self.clone(),
72 }
73 }
74
75 pub fn planes(&self) -> Planes {
79 Planes {
80 region: self.clone(),
81 }
82 }
83
84 pub fn trailing(
87 #[comptime] depth: usize,
88 #[comptime] space: Space,
89 #[comptime] level: Level,
90 c0: usize,
91 c1: usize,
92 ) -> Region {
93 let edges = comptime!(MatrixAxes::edges(&space));
94 Region::cell(depth, space, level, edges, c0, c1)
95 }
96
97 pub(crate) fn cell(
100 #[comptime] depth: usize,
101 #[comptime] space: Space,
102 #[comptime] level: Level,
103 #[comptime] edges: MatrixAxes,
104 c0: usize,
105 c1: usize,
106 ) -> Region {
107 let rank = comptime!(space.rank());
108 let mut coords = Coords::<u32>::new();
109 #[unroll]
110 for p in 0..rank {
111 let c = if comptime!(p == edges.row_split) {
113 c0.cast::<u32>()
114 } else if comptime!(p == edges.col_split) {
115 c1.cast::<u32>()
116 } else {
117 0u32.runtime()
118 };
119 coords.push(c);
120 }
121 let mut step_coords = Sequence::<Coords<u32>>::new();
122 step_coords.push(coords);
123 Region::new(
124 step_coords,
125 Sequence::new(),
126 comptime!(Path::new(
127 depth,
128 Partitioning::new(space.clone(), Vec::new()),
129 vec![level]
130 )),
131 )
132 }
133
134 pub(crate) fn step(&self, #[comptime] i: usize) -> Step {
136 Step::new(
137 self.step_coords.index(i).clone(),
138 comptime!(self.path.space_at(i)),
139 comptime!(self.path.level(i).clone()),
140 comptime!(self.path.depth() - self.path.len() + i),
141 )
142 }
143
144 pub(crate) fn child(&self) -> Space {
146 Space::with_sizes(comptime!(self.path.child()), self.sizes.clone())
147 }
148
149 pub fn coord(&self, #[comptime] axis: Axis) -> usize {
151 let last = comptime!(self.path.len() - 1);
152 self.step(last).coord(axis)
153 }
154
155 pub fn origin(&self, #[comptime] axis: Axis) -> usize {
159 let mut origin = 0usize;
160 #[unroll]
161 for i in 0..comptime!(self.path.len()) {
162 if let Some(tile) = comptime!(self.path.level(i).tile(axis)) {
163 origin += self.step(i).coord(axis) * tile;
164 }
165 }
166 origin
167 }
168
169 pub(crate) fn below(&self, coords: Coords<u32>, #[comptime] level: Level) -> Region {
171 let n = comptime!(self.step_coords.len());
172 let mut step_coords = Sequence::<Coords<u32>>::new();
173 #[unroll]
174 for i in 0..n {
175 step_coords.push(self.step_coords.index(i).clone());
176 }
177 step_coords.push(coords);
178 Region::new(
179 step_coords,
180 self.sizes.clone(),
181 comptime!(self.path.below(level)),
182 )
183 }
184
185 pub fn over(&self, #[comptime] level: &Level) -> Walk {
187 Walk::of(&self.child(), comptime!(level.clone()), self.clone())
188 }
189}
190
191impl IntoIterator for Region {
193 type Item = Region;
194 type IntoIter = std::vec::IntoIter<Region>;
195
196 fn into_iter(self) -> Self::IntoIter {
197 unexpanded!()
198 }
199}
200
201impl IntoIterator for &Region {
202 type Item = Region;
203 type IntoIter = std::vec::IntoIter<Region>;
204
205 fn into_iter(self) -> Self::IntoIter {
206 unexpanded!()
207 }
208}
209
210impl Iterable for RegionExpand {
212 type Item = RegionExpand;
213
214 fn expand(self, scope: &Scope, body: &mut dyn FnMut(&Scope, RegionExpand)) {
215 let walk = self.__expand_walk_method(scope);
216 if walk.const_len() == Some(1) {
217 walk.expand_unroll(scope, body)
218 } else {
219 walk.expand(scope, body)
220 }
221 }
222
223 fn expand_unroll(self, scope: &Scope, body: &mut dyn FnMut(&Scope, RegionExpand)) {
224 self.__expand_walk_method(scope).expand_unroll(scope, body)
225 }
226}
227
228impl Iterable for &RegionExpand {
230 type Item = RegionExpand;
231
232 fn expand(self, scope: &Scope, body: &mut dyn FnMut(&Scope, RegionExpand)) {
233 self.clone().expand(scope, body)
234 }
235
236 fn expand_unroll(self, scope: &Scope, body: &mut dyn FnMut(&Scope, RegionExpand)) {
237 self.clone().expand_unroll(scope, body)
238 }
239}
240
241#[derive(CubeType, Clone)]
243#[expand(derive(Clone))]
244pub struct Leaves {
245 #[allow(dead_code)] region: Region,
247}
248
249impl IntoIterator for Leaves {
251 type Item = Region;
252 type IntoIter = std::vec::IntoIter<Region>;
253
254 fn into_iter(self) -> Self::IntoIter {
255 unexpanded!()
256 }
257}
258
259impl Iterable for LeavesExpand {
261 type Item = RegionExpand;
262
263 fn expand(self, scope: &Scope, body: &mut dyn FnMut(&Scope, RegionExpand)) {
264 self.region.each_leaf(scope, body, false);
265 }
266
267 fn expand_unroll(self, scope: &Scope, body: &mut dyn FnMut(&Scope, RegionExpand)) {
268 self.region.each_leaf(scope, body, true);
269 }
270}
271
272#[derive(CubeType, Clone)]
274#[expand(derive(Clone))]
275pub struct Planes {
276 #[allow(dead_code)] region: Region,
278}
279
280impl IntoIterator for Planes {
282 type Item = Region;
283 type IntoIter = std::vec::IntoIter<Region>;
284
285 fn into_iter(self) -> Self::IntoIter {
286 unexpanded!()
287 }
288}
289
290impl Iterable for PlanesExpand {
292 type Item = RegionExpand;
293
294 fn expand(self, scope: &Scope, body: &mut dyn FnMut(&Scope, RegionExpand)) {
295 self.region.each_plane(scope, body, false);
296 }
297
298 fn expand_unroll(self, scope: &Scope, body: &mut dyn FnMut(&Scope, RegionExpand)) {
299 self.region.each_plane(scope, body, true);
300 }
301}
302
303impl RegionExpand {
304 fn each_plane(self, scope: &Scope, body: &mut dyn FnMut(&Scope, RegionExpand), unroll: bool) {
307 match self.path.next().coverage() {
308 Coverage::Distribute(ComputeScope::Plane) => match unroll {
309 true => self.expand_unroll(scope, body),
310 false => self.expand(scope, body),
311 },
312 Coverage::Walk => {
313 let first = self
314 .__expand_walk_method(scope)
315 .__expand_region_method(scope, 0usize.into_expand(scope));
316 first.each_plane(scope, body, unroll)
317 }
318 Coverage::Distribute(other) => panic!(
319 "Region::planes: a level dealt to each {other:?} lies below this region before any \
320 plane level, so this region has no planes of its own"
321 ),
322 }
323 }
324
325 fn each_leaf(self, scope: &Scope, body: &mut dyn FnMut(&Scope, RegionExpand), unroll: bool) {
327 if self.path.at_bottom() {
328 body(scope, self);
329 return;
330 }
331 let mut below = |scope: &Scope, child: RegionExpand| child.each_leaf(scope, body, unroll);
332 match unroll {
333 true => self.expand_unroll(scope, &mut below),
334 false => self.expand(scope, &mut below),
335 }
336 }
337}