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: impl FnMut(&Scope, <T as CubeType>::ExpandType)) {
191        self.expand_unroll(scope, func);
192    }
193
194    fn expand_unroll(
195        self,
196        scope: &Scope,
197        mut func: impl FnMut(&Scope, <T as CubeType>::ExpandType),
198    ) {
199        for elem in self {
200            func(scope, elem);
201        }
202    }
203
204    fn const_len(&self) -> Option<usize> {
205        Some(self.values.len())
206    }
207}
208
209impl<T: CubeType> IntoMut for SequenceExpand<T> {
210    fn into_mut(self, scope: &Scope) -> Self {
211        Self {
212            values: self
213                .values
214                .into_iter()
215                .map(|v| IntoMut::into_mut(v, scope))
216                .collect(),
217        }
218    }
219}
220impl<T: CubeType> CubeDebug for SequenceExpand<T> {}
221
222impl<T: CubeType<ExpandType: Clone>> Clone for SequenceExpand<T> {
223    fn clone(&self) -> Self {
224        Self {
225            values: self.values.clone(),
226        }
227    }
228}
229impl<T: CubeType> ExpandTypeClone for SequenceExpand<T> {
230    fn clone_unchecked(&self) -> Self {
231        Self {
232            values: self.values.iter().map(|it| it.clone_unchecked()).collect(),
233        }
234    }
235}
236
237impl<T: CubeType> IntoIterator for Sequence<T> {
238    type Item = T;
239
240    type IntoIter = <Vec<T> as IntoIterator>::IntoIter;
241
242    fn into_iter(self) -> Self::IntoIter {
243        self.values.into_iter()
244    }
245}
246
247impl<T: CubeType> IntoIterator for SequenceExpand<T> {
248    type Item = T::ExpandType;
249
250    type IntoIter = <Vec<T::ExpandType> as IntoIterator>::IntoIter;
251
252    fn into_iter(self) -> Self::IntoIter {
253        self.values.into_iter()
254    }
255}
256
257impl<T: CubeType<ExpandType: Clone>> SequenceExpand<T> {
258    /// Provides an iterator without modifying the sequence
259    pub fn iter_cloned(&self) -> impl Iterator<Item = T::ExpandType> {
260        self.values.clone().into_iter()
261    }
262}
263
264impl<T: CubeType> CubeType for Sequence<T> {
265    type ExpandType = SequenceExpand<T>;
266}
267
268impl<T: CubeType> SequenceExpand<T> {
269    #[allow(clippy::len_without_is_empty)]
270    pub fn len(&self) -> usize {
271        self.values.len()
272    }
273    /// Expand method of [push](Sequence::push).
274    pub fn __expand_push_method(&mut self, _scope: &Scope, value: T::ExpandType) {
275        self.values.push(value);
276    }
277
278    /// Expand method of [insert](Sequence::insert).
279    pub fn __expand_insert_method(&mut self, _scope: &Scope, index: usize, value: T::ExpandType) {
280        if self.values.len() == index {
281            self.values.push(value);
282        } else {
283            self.values[index] = value;
284        }
285    }
286
287    /// Expand method of [index](Sequence::index).
288    pub fn __expand_index_method(
289        &self,
290        _scope: &Scope,
291        index: NativeExpand<usize>,
292    ) -> &T::ExpandType {
293        let index = index.constant().expect("Index must be constant").as_usize();
294        &self.values[index]
295    }
296
297    /// Expand method of [`index_mut`](Sequence::index_mut).
298    pub fn __expand_index_mut_method(
299        &mut self,
300        _scope: &Scope,
301        index: NativeExpand<usize>,
302    ) -> &mut T::ExpandType {
303        let index = index.constant().expect("Index must be constant").as_usize();
304        &mut self.values[index]
305    }
306
307    pub fn __expand_len_method(&self, _scope: &Scope) -> usize {
308        self.values.len()
309    }
310
311    pub fn __expand_reverse_method(&mut self, _scope: &Scope) {
312        self.values.reverse();
313    }
314
315    pub fn __expand_reversed_method(&self, _scope: &Scope) -> Self
316    where
317        T::ExpandType: Clone,
318    {
319        Self {
320            values: self.values.iter().cloned().rev().collect(),
321        }
322    }
323
324    pub fn __expand_clone_method(&self, _scope: &Scope) -> Self
325    where
326        T::ExpandType: Clone,
327    {
328        self.clone()
329    }
330}
331
332#[macro_export]
333macro_rules! seq {
334    ($($value: expr),*) => {
335        $crate::seq![$($value,)*]
336    };
337    ($($value: expr,)*) => {{
338        let mut seq = Sequence::new();
339        $(seq.push($value);)*
340        seq
341    }}
342}
343
344#[macro_export]
345macro_rules! __expand_seq {
346    ($scope: expr, $($value: expr),*) => {
347        $crate::__expand_seq![$scope, $($value,)*]
348    };
349    ($scope: expr, $($value: expr,)*) => {{
350        let mut seq = Sequence::__expand_new($scope);
351        $(seq.__expand_push_method($scope, $value.into());)*
352        seq
353    }}
354}