Skip to main content

cubecl_core/frontend/container/sequence/
base.rs

1use alloc::vec::Vec;
2use cubecl_ir::Scope;
3use serde::{Deserialize, Serialize};
4
5use crate::prelude::*;
6use core::ops::{Deref, Index, IndexMut};
7
8/// A sequence of [cube types](CubeType) that is inlined during compilation.
9///
10/// In other words, it allows you to group a dynamic amount of variables at compile time.
11///
12/// All methods [push](Sequence::push), [index](Sequence::index) and
13/// [`into_iter`](Sequence::into_iter) are executed _during_ compilation and don't add any overhead
14/// on the generated kernel.
15#[derive(Debug, Clone, Hash, PartialEq, Eq, Serialize, Deserialize, PartialOrd, Ord)]
16pub struct Sequence<T: CubeType> {
17    values: Vec<T>,
18}
19
20impl<T: CubeType> Default for Sequence<T> {
21    fn default() -> Self {
22        Self::new()
23    }
24}
25
26impl<T: CubeType> IntoExpand for SequenceExpand<T> {
27    type Expand = Self;
28
29    fn into_expand(self, _scope: &Scope) -> Self::Expand {
30        self
31    }
32}
33
34impl<T: CubeType> IntoMut for Sequence<T> {
35    fn into_mut(self, _scope: &Scope) -> Self {
36        self
37    }
38}
39impl<T: CubeType> CubeDebug for Sequence<T> {}
40
41impl<T: CubeType<ExpandType: Clone>> DerefExpand for SequenceExpand<T> {
42    type Target = Self;
43
44    fn __expand_deref_method(&self, _: &Scope) -> Self::Target {
45        self.clone()
46    }
47}
48
49impl<T: CubeType> Sequence<T> {
50    pub fn reverse(&mut self) {
51        self.values.reverse();
52    }
53
54    pub fn reversed(&self) -> Sequence<T>
55    where
56        T: Clone,
57    {
58        Self {
59            values: self.values.iter().cloned().rev().collect(),
60        }
61    }
62}
63
64impl<T: CubeType> Sequence<T> {
65    /// Create a new empty sequence.
66    pub fn new() -> Self {
67        Self { values: Vec::new() }
68    }
69
70    /// Push a new value into the sequence.
71    pub fn push(&mut self, value: T) {
72        self.values.push(value);
73    }
74
75    /// Obtain the sequence length.
76    #[allow(clippy::len_without_is_empty)]
77    pub fn len(&self) -> usize {
78        self.values.len()
79    }
80
81    /// Get the value at the given position in the sequence.
82    #[allow(clippy::should_implement_trait)]
83    pub fn index(&self, index: usize) -> &T {
84        self.values.get(index).unwrap()
85    }
86
87    /// Get the value at the given position in the sequence.
88    #[allow(clippy::should_implement_trait)]
89    pub fn index_mut(&mut self, index: usize) -> &mut T {
90        self.values.get_mut(index).unwrap()
91    }
92
93    /// Expand function of [new](Self::new).
94    pub fn __expand_new(_scope: &Scope) -> SequenceExpand<T> {
95        SequenceExpand { values: Vec::new() }
96    }
97
98    /// Insert an item at the given index.
99    #[allow(clippy::should_implement_trait)]
100    pub fn insert(&mut self, index: usize, value: T) {
101        *self.index_mut(index) = value;
102    }
103
104    /// Expand function of [push](Self::push).
105    pub fn __expand_push(scope: &Scope, expand: &mut SequenceExpand<T>, value: T::ExpandType) {
106        expand.__expand_push_method(scope, value)
107    }
108
109    /// Expand function of [index](Self::index).
110    pub fn __expand_index<'a>(
111        scope: &Scope,
112        expand: &'a SequenceExpand<T>,
113        index: NativeExpand<usize>,
114    ) -> &'a T::ExpandType {
115        expand.__expand_index_method(scope, index)
116    }
117
118    /// Expand function of [`index_mut`](Self::index_mut).
119    pub fn __expand_index_mut<'a>(
120        scope: &Scope,
121        expand: &'a mut SequenceExpand<T>,
122        index: NativeExpand<usize>,
123    ) -> &'a mut T::ExpandType {
124        expand.__expand_index_mut_method(scope, index)
125    }
126}
127
128impl<T: CubeType> AsRefExpand for SequenceExpand<T> {
129    fn __expand_ref_method(&self, _: &Scope) -> &Self {
130        self
131    }
132}
133impl<T: CubeType> AsMutExpand for SequenceExpand<T> {
134    fn __expand_ref_mut_method(&mut self, _: &Scope) -> &mut Self {
135        self
136    }
137}
138
139impl<T: CubeType> Index<usize> for Sequence<T> {
140    type Output = T;
141
142    fn index(&self, index: usize) -> &Self::Output {
143        self.values.index(index)
144    }
145}
146
147impl<T: CubeType> IndexMut<usize> for Sequence<T> {
148    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
149        self.values.index_mut(index)
150    }
151}
152
153impl<T: CubeType> Deref for Sequence<T> {
154    type Target = [T];
155
156    fn deref(&self) -> &Self::Target {
157        &self.values
158    }
159}
160
161impl<T: CubeType> IndexExpand<NativeExpand<usize>> for SequenceExpand<T> {
162    type Output = T::ExpandType;
163
164    fn __expand_index_method(&self, scope: &Scope, index: NativeExpand<usize>) -> &Self::Output {
165        self.__expand_index_method(scope, index)
166    }
167}
168
169impl<T: CubeType> IndexMutExpand<NativeExpand<usize>> for SequenceExpand<T> {
170    fn __expand_index_mut_method(
171        &mut self,
172        scope: &Scope,
173        index: NativeExpand<usize>,
174    ) -> &mut T::ExpandType {
175        self.__expand_index_mut_method(scope, index)
176    }
177}
178
179/// Expand type of [Sequence].
180#[derive(Debug)]
181pub struct SequenceExpand<T: CubeType> {
182    // We clone the expand type during the compilation phase, but for register reuse, not for
183    // copying data. To achieve the intended behavior, we have to share the same underlying values.
184    pub(super) values: Vec<T::ExpandType>,
185}
186
187impl<T: CubeType> Iterable for SequenceExpand<T> {
188    type Item = T::ExpandType;
189
190    fn expand(self, scope: &Scope, func: &mut dyn FnMut(&Scope, <T as CubeType>::ExpandType)) {
191        self.expand_unroll(scope, func);
192    }
193
194    fn expand_unroll(
195        self,
196        scope: &Scope,
197        func: &mut dyn FnMut(&Scope, <T as CubeType>::ExpandType),
198    ) {
199        let body = scope.unrolled_loop_child();
200        for elem in self {
201            scope.update_flags_before_unrolled_iteration(&body);
202            func(&body, elem);
203        }
204        scope.finalize_unrolled_loop(&body);
205    }
206
207    fn const_len(&self) -> Option<usize> {
208        Some(self.values.len())
209    }
210}
211
212impl<T: CubeType> IntoMut for SequenceExpand<T> {
213    fn into_mut(self, scope: &Scope) -> Self {
214        Self {
215            values: self
216                .values
217                .into_iter()
218                .map(|v| IntoMut::into_mut(v, scope))
219                .collect(),
220        }
221    }
222}
223impl<T: CubeType> CubeDebug for SequenceExpand<T> {}
224
225impl<T: CubeType<ExpandType: Clone>> Clone for SequenceExpand<T> {
226    fn clone(&self) -> Self {
227        Self {
228            values: self.values.clone(),
229        }
230    }
231}
232impl<T: CubeType> ExpandTypeClone for SequenceExpand<T> {
233    fn clone_unchecked(&self) -> Self {
234        Self {
235            values: self.values.iter().map(|it| it.clone_unchecked()).collect(),
236        }
237    }
238}
239
240impl<T: CubeType> IntoIterator for Sequence<T> {
241    type Item = T;
242
243    type IntoIter = <Vec<T> as IntoIterator>::IntoIter;
244
245    fn into_iter(self) -> Self::IntoIter {
246        self.values.into_iter()
247    }
248}
249
250impl<T: CubeType> IntoIterator for SequenceExpand<T> {
251    type Item = T::ExpandType;
252
253    type IntoIter = <Vec<T::ExpandType> as IntoIterator>::IntoIter;
254
255    fn into_iter(self) -> Self::IntoIter {
256        self.values.into_iter()
257    }
258}
259
260impl<T: CubeType<ExpandType: Clone>> SequenceExpand<T> {
261    /// Provides an iterator without modifying the sequence
262    pub fn iter_cloned(&self) -> impl Iterator<Item = T::ExpandType> {
263        self.values.clone().into_iter()
264    }
265}
266
267impl<T: CubeType> CubeType for Sequence<T> {
268    type ExpandType = SequenceExpand<T>;
269}
270
271impl<T: CubeType> SequenceExpand<T> {
272    #[allow(clippy::len_without_is_empty)]
273    pub fn len(&self) -> usize {
274        self.values.len()
275    }
276    /// Expand method of [push](Sequence::push).
277    pub fn __expand_push_method(&mut self, _scope: &Scope, value: T::ExpandType) {
278        self.values.push(value);
279    }
280
281    /// Expand method of [insert](Sequence::insert).
282    pub fn __expand_insert_method(&mut self, _scope: &Scope, index: usize, value: T::ExpandType) {
283        if self.values.len() == index {
284            self.values.push(value);
285        } else {
286            self.values[index] = value;
287        }
288    }
289
290    /// Expand method of [index](Sequence::index).
291    pub fn __expand_index_method(
292        &self,
293        _scope: &Scope,
294        index: NativeExpand<usize>,
295    ) -> &T::ExpandType {
296        let index = index.constant().expect("Index must be constant").as_usize();
297        &self.values[index]
298    }
299
300    /// Expand method of [`index_mut`](Sequence::index_mut).
301    pub fn __expand_index_mut_method(
302        &mut self,
303        _scope: &Scope,
304        index: NativeExpand<usize>,
305    ) -> &mut T::ExpandType {
306        let index = index.constant().expect("Index must be constant").as_usize();
307        &mut self.values[index]
308    }
309
310    pub fn __expand_len_method(&self, _scope: &Scope) -> usize {
311        self.values.len()
312    }
313
314    pub fn __expand_reverse_method(&mut self, _scope: &Scope) {
315        self.values.reverse();
316    }
317
318    pub fn __expand_reversed_method(&self, _scope: &Scope) -> Self
319    where
320        T::ExpandType: Clone,
321    {
322        Self {
323            values: self.values.iter().cloned().rev().collect(),
324        }
325    }
326
327    pub fn __expand_clone_method(&self, _scope: &Scope) -> Self
328    where
329        T::ExpandType: Clone,
330    {
331        self.clone()
332    }
333}
334
335#[macro_export]
336macro_rules! seq {
337    ($($value: expr),*) => {
338        $crate::seq![$($value,)*]
339    };
340    ($($value: expr,)*) => {{
341        let mut seq = Sequence::new();
342        $(seq.push($value);)*
343        seq
344    }}
345}
346
347#[macro_export]
348macro_rules! __expand_seq {
349    ($scope: expr, $($value: expr),*) => {
350        $crate::__expand_seq![$scope, $($value,)*]
351    };
352    ($scope: expr, $($value: expr,)*) => {{
353        let mut seq = Sequence::__expand_new($scope);
354        $(seq.__expand_push_method($scope, $value.into());)*
355        seq
356    }}
357}