1use alloc::vec;
2use core::ops::{Deref, DerefMut};
3use pliron::{builtin::ops::FuncOp, r#type::TypeHandle, value::DefiningEntity};
4
5use alloc::boxed::Box;
6
7use crate::{self as cubecl, unexpanded};
8use cubecl::prelude::*;
9use cubecl_ir::{
10 OpInserter, SliceMetadata, VectorSize,
11 attributes::{ATTR_BUFFER_BINDING, BufferBindingAttr, FuncInterface},
12 dialect::{
13 OperationPtrExt, branch::RangeLoopOp, general::ReinterpretCastOp,
14 vector::CompositeConstructOp,
15 },
16 interfaces::{TypedExt, aliasing::PointerExt},
17 pliron::{context::Context, printable::Printable, r#type::Typed, value::Value},
18 types::{ArrayType, PointerType, RuntimeArrayType, VectorType, aggregate::SliceType},
19};
20
21pub type SliceExpand<T> = NativeExpand<[T]>;
22
23#[derive(Clone, Copy)]
24pub struct ReadOnly;
25#[derive(Clone, Copy)]
26pub struct ReadWrite;
27
28pub trait SliceVisibility: Clone + Copy + Send + Sync + 'static {}
29
30impl SliceVisibility for ReadOnly {}
31
32impl SliceVisibility for ReadWrite {}
33
34impl<E: CubePrimitive> SliceExpand<E> {
35 pub fn __extract_list(&self, scope: &Scope) -> Value {
36 scope.extract_field(self.value(scope), SliceMetadata::LIST)
37 }
38
39 pub fn __extract_offset(&self, scope: &Scope) -> NativeExpand<usize> {
40 let field = scope.extract_field(self.value(scope), SliceMetadata::OFFSET);
41 field.into()
42 }
43
44 pub fn __extract_length(&self, scope: &Scope) -> NativeExpand<usize> {
45 let field = scope.extract_field(self.value(scope), SliceMetadata::LENGTH);
46 field.into()
47 }
48}
49
50pub(crate) fn buffer_idx(scope: &Scope, list: Value) -> usize {
51 buffer_binding(scope, list).buffer_pos
52}
53
54pub(crate) fn ext_meta_idx(scope: &Scope, list: Value) -> usize {
55 buffer_binding(scope, list)
56 .ext_meta_pos
57 .expect("Should have ext meta")
58}
59
60fn buffer_binding(scope: &Scope, list: Value) -> BufferBindingAttr {
61 let ctx = scope.ctx();
62 let (entry_block, idx) = match list.defining_entity() {
63 DefiningEntity::Op(_) => {
65 let block = list
66 .get_root_defining_block(ctx)
67 .expect("Should be block arg");
68 let idx = list.find_root_index(ctx);
69 (block, idx)
70 }
71 DefiningEntity::Block(block) => (block, list.find_index(ctx)),
72 };
73 let func = entry_block.deref(ctx).get_parent_op(ctx).unwrap();
74 let func = func.as_op::<FuncOp>(ctx).expect("Should be function");
75 *func
76 .get_arg_attr::<BufferBindingAttr>(scope.ctx(), idx, &ATTR_BUFFER_BINDING)
77 .expect("Should be buffer binding")
78}
79
80pub trait SliceVectorExt<E: Scalar, N: Size> {
81 fn with_vector_size<N2: Size>(&self) -> &[Vector<E, N2>] {
82 unexpanded!()
83 }
84 fn with_vector_size_mut<N2: Size>(&mut self) -> &mut [Vector<E, N2>] {
85 unexpanded!()
86 }
87 fn __expand_with_vector_size<'infer, N2: Size>(
88 scope: &Scope,
89 this: &'infer SliceExpand<Vector<E, N>>,
90 ) -> &'infer SliceExpand<Vector<E, N2>> {
91 this.__expand_with_vector_size_method(scope)
92 }
93 fn __expand_with_vector_size_mut<'infer, N2: Size>(
94 scope: &Scope,
95 this: &'infer mut SliceExpand<Vector<E, N>>,
96 ) -> &'infer mut SliceExpand<Vector<E, N2>> {
97 this.__expand_with_vector_size_mut_method(scope)
98 }
99}
100
101impl<E: Scalar, N: Size> SliceVectorExt<E, N> for [Vector<E, N>] {}
102impl<E: Scalar, N: Size> SliceExpand<Vector<E, N>> {
103 pub fn __expand_with_vector_size_method<'infer, N2: Size>(
104 &'infer self,
105 scope: &Scope,
106 ) -> &'infer SliceExpand<Vector<E, N2>> {
107 let slice = self.with_vector_size_inner::<N2>(scope);
108 scope.create_kernel_ref(slice)
109 }
110
111 pub fn __expand_with_vector_size_mut_method<'infer, N2: Size>(
112 &'infer mut self,
113 scope: &Scope,
114 ) -> &'infer mut SliceExpand<Vector<E, N2>> {
115 let slice = self.with_vector_size_inner::<N2>(scope);
116 scope.create_kernel_ref(slice)
117 }
118}
119
120impl<E: Scalar, N: Size> SliceExpand<Vector<E, N>> {
121 fn with_vector_size_inner<N2: Size>(&self, scope: &Scope) -> SliceExpand<Vector<E, N2>> {
122 let vector_size = N2::__expand_value(scope);
123 let list = self.__extract_list(scope);
124
125 let length = self.__extract_length(scope);
126 let offset = self.__extract_offset(scope);
127
128 let current = list.vector_size(scope.ctx());
129
130 if vector_size == current {
131 return self.expand.into();
132 }
133
134 let new_ptr_ty = change_list_vectorization(scope.ctx_mut(), list, vector_size);
135 let reinterpret = ReinterpretCastOp::new(scope.ctx_mut(), new_ptr_ty, list);
136 let new_ptr = scope.register_with_result(&reinterpret);
137
138 if current < vector_size {
139 let ratio = vector_size / current;
140 let offset = offset.__expand_div_method(scope, ratio.into());
141 let length = length.__expand_div_method(scope, ratio.into());
142 from_raw_parts(scope, new_ptr, offset, length)
143 } else {
144 let ratio = current / vector_size;
145 let offset = offset.__expand_mul_method(scope, ratio.into());
146 let length = length.__expand_mul_method(scope, ratio.into());
147 from_raw_parts(scope, new_ptr, offset, length)
148 }
149 }
150}
151
152fn change_list_vectorization(ctx: &Context, list: Value, new_vec: usize) -> TypeHandle {
154 let current_vec = list.vector_size(ctx);
155 let ty = list.get_type(ctx);
156 let PointerType {
157 inner,
158 address_space,
159 } = {
160 let ty = ty.deref(ctx);
161 *ty.downcast_ref().unwrap()
162 };
163 let (arr, runtime_arr) = {
164 let list_ty = inner.deref(ctx);
165 let arr = list_ty.downcast_ref::<ArrayType>().copied();
166 let runtime_arr = list_ty.downcast_ref::<RuntimeArrayType>().copied();
167 (arr, runtime_arr)
168 };
169 if let Some(ArrayType { inner, length }) = arr {
170 let new_length = length * current_vec / new_vec;
171 let scalar_ty = inner.scalar_ty(ctx);
172 let new_vector_ty = if new_vec > 1 {
173 VectorType::get(ctx, scalar_ty, new_vec).into()
174 } else {
175 scalar_ty
176 };
177 let new_arr_ty = ArrayType::get(ctx, new_vector_ty, new_length).into();
178 let new_ptr_ty = PointerType::get(ctx, new_arr_ty, address_space);
179 return new_ptr_ty.into();
180 }
181 if let Some(RuntimeArrayType { inner }) = runtime_arr {
182 let scalar_ty = inner.scalar_ty(ctx);
183 let new_vector_ty = if new_vec > 1 {
184 VectorType::get(ctx, scalar_ty, new_vec).into()
185 } else {
186 scalar_ty
187 };
188 let new_arr_ty = RuntimeArrayType::get(ctx, new_vector_ty).into();
189 let new_ptr_ty = PointerType::get(ctx, new_arr_ty, address_space);
190 return new_ptr_ty.into();
191 }
192 unreachable!("Should be static or dynamic array")
193}
194
195pub trait SliceExt<E: CubePrimitive> {
196 fn as_vectorized(&self) -> &[Vector<E::Scalar, E::Size>] {
199 unexpanded!()
200 }
201
202 fn as_vectorized_mut(&mut self) -> &mut [Vector<E::Scalar, E::Size>] {
205 unexpanded!()
206 }
207
208 fn downcast<T: CubePrimitive>(&self) -> &[T] {
213 unexpanded!()
214 }
215
216 fn downcast_mut<T: CubePrimitive>(&mut self) -> &mut [T] {
221 unexpanded!()
222 }
223
224 unsafe fn downcast_unchecked<T: CubePrimitive>(&self) -> &[T] {
230 unexpanded!()
231 }
232
233 unsafe fn downcast_mut_unchecked<T: CubePrimitive>(&mut self) -> &mut [T] {
239 unexpanded!()
240 }
241
242 #[allow(clippy::mut_from_ref)]
248 unsafe fn as_mut_unchecked(&self) -> &mut [E] {
249 unexpanded!()
250 }
251
252 unsafe fn as_ptr_unchecked(&self) -> *const E {
257 unexpanded!()
258 }
259
260 unsafe fn as_mut_ptr_unchecked(&mut self) -> *mut E {
265 unexpanded!()
266 }
267
268 unsafe fn as_boxed_unchecked(&self) -> Box<[E]> {
274 unexpanded!()
275 }
276
277 fn __expand_as_vectorized<'infer>(
278 scope: &Scope,
279 this: &'infer SliceExpand<E>,
280 ) -> &'infer SliceExpand<Vector<E::Scalar, E::Size>>;
281
282 fn __expand_as_vectorized_mut<'infer>(
283 scope: &Scope,
284 this: &'infer mut SliceExpand<E>,
285 ) -> &'infer mut SliceExpand<Vector<E::Scalar, E::Size>>;
286
287 fn __expand_downcast<'infer, T: CubePrimitive>(
288 scope: &Scope,
289 this: &'infer SliceExpand<E>,
290 ) -> &'infer SliceExpand<T>;
291
292 fn __expand_downcast_mut<'infer, T: CubePrimitive>(
293 scope: &Scope,
294 this: &'infer mut SliceExpand<E>,
295 ) -> &'infer mut SliceExpand<T>;
296
297 fn __expand_downcast_unchecked<'infer, T: CubePrimitive>(
298 scope: &Scope,
299 this: &'infer SliceExpand<E>,
300 ) -> &'infer SliceExpand<T>;
301
302 fn __expand_downcast_mut_unchecked<'infer, T: CubePrimitive>(
303 scope: &Scope,
304 this: &'infer mut SliceExpand<E>,
305 ) -> &'infer mut SliceExpand<T>;
306
307 fn __expand_as_ptr(scope: &Scope, this: &SliceExpand<E>) -> *const NativeExpand<E>;
308
309 fn __expand_as_mut_ptr(scope: &Scope, this: &mut SliceExpand<E>) -> *mut NativeExpand<E>;
310
311 #[doc(hidden)]
312 unsafe fn __expand_as_ptr_unchecked(
313 scope: &Scope,
314 this: &SliceExpand<E>,
315 ) -> *const NativeExpand<E>;
316
317 #[doc(hidden)]
318 unsafe fn __expand_as_mut_ptr_unchecked(
319 scope: &Scope,
320 this: &mut SliceExpand<E>,
321 ) -> *mut NativeExpand<E>;
322
323 #[allow(clippy::mut_from_ref)]
324 #[doc(hidden)]
325 unsafe fn __expand_as_mut_unchecked<'infer>(
326 scope: &Scope,
327 this: &'infer SliceExpand<E>,
328 ) -> &'infer mut SliceExpand<E>;
329
330 #[doc(hidden)]
331 unsafe fn __expand_as_boxed_unchecked(
332 scope: &Scope,
333 this: &SliceExpand<E>,
334 ) -> NativeExpand<Box<[E]>>;
335}
336
337impl<E: CubePrimitive> SliceExt<E> for [E] {
338 fn __expand_as_vectorized<'infer>(
339 scope: &Scope,
340 this: &'infer SliceExpand<E>,
341 ) -> &'infer SliceExpand<Vector<E::Scalar, E::Size>> {
342 this.__expand_as_vectorized_method(scope)
343 }
344
345 fn __expand_as_vectorized_mut<'infer>(
346 scope: &Scope,
347 this: &'infer mut SliceExpand<E>,
348 ) -> &'infer mut SliceExpand<Vector<E::Scalar, E::Size>> {
349 this.__expand_as_vectorized_mut_method(scope)
350 }
351
352 fn __expand_downcast<'infer, T: CubePrimitive>(
353 scope: &Scope,
354 this: &'infer SliceExpand<E>,
355 ) -> &'infer SliceExpand<T> {
356 this.__expand_downcast_method::<T>(scope)
357 }
358
359 fn __expand_downcast_mut<'infer, T: CubePrimitive>(
360 scope: &Scope,
361 this: &'infer mut SliceExpand<E>,
362 ) -> &'infer mut SliceExpand<T> {
363 this.__expand_downcast_mut_method::<T>(scope)
364 }
365
366 fn __expand_downcast_unchecked<'infer, T: CubePrimitive>(
367 scope: &Scope,
368 this: &'infer SliceExpand<E>,
369 ) -> &'infer SliceExpand<T> {
370 this.__expand_downcast_unchecked_method::<T>(scope)
371 }
372
373 fn __expand_downcast_mut_unchecked<'infer, T: CubePrimitive>(
374 scope: &Scope,
375 this: &'infer mut SliceExpand<E>,
376 ) -> &'infer mut SliceExpand<T> {
377 this.__expand_downcast_mut_unchecked_method::<T>(scope)
378 }
379
380 fn __expand_as_ptr(scope: &Scope, this: &SliceExpand<E>) -> *const NativeExpand<E> {
381 this.__expand_as_ptr_method(scope)
382 }
383
384 fn __expand_as_mut_ptr(scope: &Scope, this: &mut SliceExpand<E>) -> *mut NativeExpand<E> {
385 this.__expand_as_mut_ptr_method(scope)
386 }
387
388 unsafe fn __expand_as_ptr_unchecked(
389 scope: &Scope,
390 this: &SliceExpand<E>,
391 ) -> *const NativeExpand<E> {
392 unsafe { this.__expand_as_ptr_unchecked_method(scope) }
393 }
394
395 unsafe fn __expand_as_mut_ptr_unchecked(
396 scope: &Scope,
397 this: &mut SliceExpand<E>,
398 ) -> *mut NativeExpand<E> {
399 unsafe { this.__expand_as_mut_ptr_unchecked_method(scope) }
400 }
401
402 unsafe fn __expand_as_mut_unchecked<'infer>(
403 scope: &Scope,
404 this: &'infer SliceExpand<E>,
405 ) -> &'infer mut SliceExpand<E> {
406 this.__expand_as_mut_unchecked_method(scope)
407 }
408
409 unsafe fn __expand_as_boxed_unchecked(
410 scope: &Scope,
411 this: &SliceExpand<E>,
412 ) -> NativeExpand<Box<[E]>> {
413 unsafe { this.__expand_as_boxed_unchecked_method(scope) }
414 }
415}
416
417impl<E: CubePrimitive> SliceExpand<E> {
418 pub fn __expand_as_vectorized_method(
419 &self,
420 _: &Scope,
421 ) -> &SliceExpand<Vector<E::Scalar, E::Size>> {
422 unsafe { self.as_type_ref_unchecked() }
423 }
424
425 pub fn __expand_as_vectorized_mut_method(
426 &mut self,
427 _: &Scope,
428 ) -> &mut SliceExpand<Vector<E::Scalar, E::Size>> {
429 unsafe { self.as_type_mut_unchecked() }
430 }
431
432 pub fn __expand_downcast_method<T: CubePrimitive>(&self, scope: &Scope) -> &SliceExpand<T> {
433 let ty_t = T::__expand_as_type(scope);
434 let ty_e = E::__expand_as_type(scope);
435 if ty_t != ty_e && !is_tf32_cast::<E, T>(scope) && !is_flex32_cast::<E, T>(scope) {
436 panic!(
437 "Downcast should only be used to satisfy the Rust type system.
438Expected types to be the same, got [{}, {}]",
439 ty_t.disp(scope.ctx()),
440 ty_e.disp(scope.ctx())
441 )
442 }
443
444 self.__expand_downcast_unchecked_method(scope)
445 }
446
447 pub fn __expand_downcast_mut_method<T: CubePrimitive>(
448 &mut self,
449 scope: &Scope,
450 ) -> &mut SliceExpand<T> {
451 if T::__expand_as_type(scope) != E::__expand_as_type(scope) && !is_tf32_cast::<E, T>(scope)
452 {
453 let ty_t = T::__expand_as_type(scope);
454 let ty_e = E::__expand_as_type(scope);
455 if ty_t != ty_e && !is_tf32_cast::<E, T>(scope) && !is_flex32_cast::<E, T>(scope) {
456 panic!(
457 "Downcast should only be used to satisfy the Rust type system.
458Expected types to be the same, got [{}, {}]",
459 ty_t.disp(scope.ctx()),
460 ty_e.disp(scope.ctx())
461 )
462 }
463 }
464
465 self.__expand_downcast_mut_unchecked_method(scope)
466 }
467
468 #[doc(hidden)]
469 pub fn __expand_downcast_unchecked_method<T: CubePrimitive>(
470 &self,
471 _: &Scope,
472 ) -> &SliceExpand<T> {
473 unsafe { self.as_type_ref_unchecked() }
474 }
475
476 #[doc(hidden)]
477 pub fn __expand_downcast_mut_unchecked_method<T: CubePrimitive>(
478 &mut self,
479 _: &Scope,
480 ) -> &mut SliceExpand<T> {
481 unsafe { self.as_type_mut_unchecked() }
482 }
483
484 pub fn __expand_as_ptr_method(&self, scope: &Scope) -> *const NativeExpand<E> {
485 self.__expand_index_method(scope, NativeExpand::<usize>::from_lit(scope, 0))
486 }
487
488 pub fn __expand_as_mut_ptr_method(&mut self, scope: &Scope) -> *mut NativeExpand<E> {
489 self.__expand_index_mut_method(scope, NativeExpand::<usize>::from_lit(scope, 0))
490 }
491
492 #[doc(hidden)]
493 pub unsafe fn __expand_as_ptr_unchecked_method(&self, scope: &Scope) -> *const NativeExpand<E> {
494 unsafe {
495 self.__expand_get_unchecked_method(scope, NativeExpand::<usize>::from_lit(scope, 0))
496 }
497 }
498
499 #[doc(hidden)]
500 pub unsafe fn __expand_as_mut_ptr_unchecked_method(
501 &mut self,
502 scope: &Scope,
503 ) -> *mut NativeExpand<E> {
504 unsafe {
505 self.__expand_get_unchecked_mut_method(scope, NativeExpand::<usize>::from_lit(scope, 0))
506 }
507 }
508
509 pub fn __expand_as_mut_unchecked_method(&self, scope: &Scope) -> &mut SliceExpand<E> {
510 scope.create_kernel_ref(self.expand.into())
511 }
512
513 #[doc(hidden)]
514 pub unsafe fn __expand_as_boxed_unchecked_method(&self, _: &Scope) -> NativeExpand<Box<[E]>> {
515 self.expand.into()
516 }
517}
518
519pub fn from_raw_parts<E: CubePrimitive>(
520 scope: &Scope,
521 list: Value,
522 offset: NativeExpand<usize>,
523 length: NativeExpand<usize>,
524) -> SliceExpand<E> {
525 let list_ty = list.get_type(scope.ctx());
526 let offset = offset.read_value(scope);
527 let length = length.read_value(scope);
528 let ty = SliceType::get(scope.ctx(), list_ty).to_handle();
529 let op = CompositeConstructOp::new(scope.ctx_mut(), ty, vec![list, offset, length]);
530 scope.register_with_result(&op).into()
531}
532
533impl<E: CubePrimitive> SliceExpand<E> {
534 pub fn __expand_len_method(&self, scope: &Scope) -> NativeExpand<usize> {
536 self.__extract_length(scope)
537 }
538 pub fn is_empty(&self, scope: &Scope) -> NativeExpand<bool> {
540 self.__extract_length(scope)
541 .__expand_eq_method(scope, &0usize.into_expand(scope))
542 }
543}
544
545impl<E: CubePrimitive> CubeType for [E] {
546 type ExpandType = SliceExpand<E>;
547}
548
549impl<E: CubePrimitive> CubeType for Box<[E]> {
550 type ExpandType = NativeExpand<Box<[E]>>;
551}
552
553impl<E> Deref for NativeExpand<Box<[E]>> {
554 type Target = NativeExpand<[E]>;
555
556 fn deref(&self) -> &Self::Target {
557 unsafe { self.as_type_ref_unchecked() }
558 }
559}
560
561impl<E> DerefMut for NativeExpand<Box<[E]>> {
562 fn deref_mut(&mut self) -> &mut Self::Target {
563 unsafe { self.as_type_mut_unchecked() }
564 }
565}
566
567macro_rules! impl_expand_traits {
568 ($generic: ident, $ty: ty) => {
569 impl<$generic: CubePrimitive> AsMutExpand for $ty {
570 fn __expand_ref_mut_method(&mut self, _: &Scope) -> &mut Self {
571 self
572 }
573 }
574
575 impl<$generic: CubePrimitive> IntoMut for $ty {
576 fn into_mut(self, _scope: &Scope) -> Self {
577 self
578 }
579 }
580 };
581}
582
583impl_expand_traits!(E, SliceExpand<E>);
584impl_expand_traits!(E, NativeExpand<Box<[E]>>);
585
586impl<'a, E: CubePrimitive> From<&'a NativeExpand<Box<[E]>>> for &'a NativeExpand<[E]> {
587 fn from(value: &'a NativeExpand<Box<[E]>>) -> Self {
588 unsafe { value.as_type_ref_unchecked() }
589 }
590}
591
592impl<'a, E: CubePrimitive> From<&'a mut NativeExpand<Box<[E]>>> for &'a mut NativeExpand<[E]> {
593 fn from(value: &'a mut NativeExpand<Box<[E]>>) -> Self {
594 unsafe { value.as_type_mut_unchecked() }
595 }
596}
597
598impl<E: CubePrimitive> SizedContainer<usize> for [E] {
599 fn len(&self) -> usize {
600 unexpanded!()
601 }
602}
603
604impl<E: CubePrimitive> SizedContainerExpand<usize> for SliceExpand<E> {
605 fn __expand_len_method(&self, scope: &Scope) -> NativeExpand<usize> {
606 self.__expand_len_method(scope)
607 }
608}
609
610impl<E: CubePrimitive> Iterable for SliceExpand<E> {
611 type Item = E::ExpandType;
612
613 fn expand(self, scope: &Scope, mut body: impl FnMut(&Scope, Self::Item)) {
614 let start = scope.const_usize(0);
615 let end = self.__extract_length(scope).value(scope);
616 let step = scope.const_usize(1);
617
618 let range_loop = RangeLoopOp::new(scope.ctx_mut(), start, end, step);
619 let i = range_loop.iter_var(scope.ctx());
620 let loop_body = range_loop.loop_body(scope.ctx());
621
622 let child = scope.loop_child(OpInserter::new_at_block_end(loop_body));
623
624 let index = NativeExpand::new(i.into());
625 let item = self
626 .__expand_index_method(&child, index)
627 .__expand_deref_method(&child);
628 body(&child, item);
629 child.terminate_yield();
630
631 register_range_loop::<usize>(scope, &range_loop, &child);
632 scope.set_may_return(&[child]);
633 }
634
635 fn expand_unroll(self, _scope: &Scope, _body: impl FnMut(&Scope, Self::Item)) {
636 unimplemented!("Can't unroll slice iterator")
637 }
638}
639
640impl<'a, E: CubePrimitive> Iterable for &'a SliceExpand<E> {
641 type Item = &'a E::ExpandType;
642
643 fn expand(self, scope: &Scope, mut body: impl FnMut(&Scope, Self::Item)) {
644 let start = scope.const_usize(0);
645 let end = self.__extract_length(scope).value(scope);
646 let step = scope.const_usize(1);
647
648 let range_loop = RangeLoopOp::new(scope.ctx_mut(), start, end, step);
649 let i = range_loop.iter_var(scope.ctx());
650 let loop_body = range_loop.loop_body(scope.ctx());
651
652 let child = scope.loop_child(OpInserter::new_at_block_end(loop_body));
653
654 let index = NativeExpand::new(i.into());
655 let item = self.__expand_index_method(&child, index);
656 body(&child, item);
657 child.terminate_yield();
658
659 register_range_loop::<usize>(scope, &range_loop, &child);
660 scope.set_may_return(&[child]);
661 }
662
663 fn expand_unroll(self, _scope: &Scope, _body: impl FnMut(&Scope, Self::Item)) {
664 unimplemented!("Can't unroll slice iterator")
665 }
666}
667
668impl<'a, E: CubePrimitive> Iterable for &'a mut SliceExpand<E> {
669 type Item = &'a mut E::ExpandType;
670
671 fn expand(self, scope: &Scope, mut body: impl FnMut(&Scope, Self::Item)) {
672 let start = scope.const_usize(0);
673 let end = self.__extract_length(scope).value(scope);
674 let step = scope.const_usize(1);
675
676 let range_loop = RangeLoopOp::new(scope.ctx_mut(), start, end, step);
677 let i = range_loop.iter_var(scope.ctx());
678 let loop_body = range_loop.loop_body(scope.ctx());
679
680 let child = scope.loop_child(OpInserter::new_at_block_end(loop_body));
681
682 let index = NativeExpand::new(i.into());
683 let item = self.__expand_index_mut_method(&child, index);
684 body(&child, item);
685 child.terminate_yield();
686
687 register_range_loop::<usize>(scope, &range_loop, &child);
688 scope.set_may_return(&[child]);
689 }
690
691 fn expand_unroll(self, _scope: &Scope, _body: impl FnMut(&Scope, Self::Item)) {
692 unimplemented!("Can't unroll slice iterator")
693 }
694}
695
696impl<E: CubePrimitive> SliceExpand<E> {
697 #[doc(hidden)]
698 pub unsafe fn __expand_get_unchecked_method(
699 &self,
700 scope: &Scope,
701 index: NativeExpand<usize>,
702 ) -> &NativeExpand<E> {
703 read_offset::expand::<E>(scope, self, index, false)
704 }
705
706 #[doc(hidden)]
707 pub unsafe fn __expand_get_unchecked_mut_method(
708 &mut self,
709 scope: &Scope,
710 index: NativeExpand<usize>,
711 ) -> &mut NativeExpand<E> {
712 write_offset::expand::<E>(scope, self, index, false)
713 }
714}
715
716impl<E: CubePrimitive> IndexExpand<NativeExpand<usize>> for SliceExpand<E> {
717 type Output = E::ExpandType;
718
719 fn __expand_index_method(&self, scope: &Scope, index: NativeExpand<usize>) -> &Self::Output {
720 read_offset::expand::<E>(scope, self, index, true)
721 }
722}
723
724impl<E: CubePrimitive> IndexMutExpand<NativeExpand<usize>> for SliceExpand<E> {
725 fn __expand_index_mut_method(
726 &mut self,
727 scope: &Scope,
728 index: NativeExpand<usize>,
729 ) -> &mut Self::Output {
730 write_offset::expand::<E>(scope, self, index, true)
731 }
732}
733
734impl_slice_ranges!(SliceExpand<E>);
735
736impl<E: CubePrimitive> List<E> for [E] {}
737impl<E: CubePrimitive> ListExpand<E> for SliceExpand<E> {
738 fn __expand_len_method(&self, scope: &Scope) -> NativeExpand<usize> {
739 self.__expand_len_method(scope)
740 }
741}
742
743impl<E: CubePrimitive> Vectorized for Box<[E]> {}
744impl<E: CubePrimitive> Vectorized for [E] {}
745impl<E: CubePrimitive> VectorizedExpand for SliceExpand<E> {
746 fn __expand_vector_size_method(&self, scope: &Scope) -> VectorSize {
747 self.__extract_list(scope).vector_size(scope.ctx())
748 }
749}
750impl<E: CubePrimitive> VectorizedExpand for NativeExpand<Box<[E]>> {
751 fn __expand_vector_size_method(&self, scope: &Scope) -> VectorSize {
752 self.__extract_list(scope).vector_size(scope.ctx())
753 }
754}
755
756mod read_offset {
757 use super::*;
758
759 pub fn expand<'a, E: CubePrimitive>(
760 scope: &Scope,
761 slice: &SliceExpand<E>,
762 index: NativeExpand<usize>,
763 checked: bool,
764 ) -> &'a <E as cubecl::prelude::CubeType>::ExpandType {
765 let list = slice.__extract_list(scope);
766 let offset = slice.__extract_offset(scope);
767 let index = offset.__expand_add_method(scope, index);
768
769 expand_index_native(scope, list, index, checked)
770 }
771}
772
773mod write_offset {
774 use super::*;
775
776 pub fn expand<'a, E: CubePrimitive>(
777 scope: &Scope,
778 slice: &SliceExpand<E>,
779 index: <usize as CubeType>::ExpandType,
780 checked: bool,
781 ) -> &'a mut E::ExpandType {
782 let list = slice.__extract_list(scope);
783 let offset = slice.__extract_offset(scope);
784 let index = offset.__expand_add_method(scope, index);
785
786 expand_index_mut_native(scope, list, index, checked)
787 }
788}