strided_basic/execution.rs
1//! Execution contract for operation-family implementations.
2//!
3//! This module is the shared kernel-extension interface, not a public mirror
4//! of implementation modules. Prevalidated entries require the caller to prove
5//! the exact destination geometry and every omitted shape check. A layout marker
6//! alone does not prove those obligations. Ordinary callers should use the
7//! checked APIs at the crate root. Every family that can fan out takes the same
8//! [`Exec`] placement token as its last parameter.
9//!
10//! # Examples
11//!
12//! ```
13//! use strided_basic::{Exec, StridedArray, execution::*};
14//! let src = StridedArray::<f64>::col_major(&[2]);
15//! let mut dst = StridedArray::<f64>::col_major(&[2]);
16//! let marker = validate_destination_layout_without_alloc(&[2], &[1]).unwrap();
17//! // SAFETY: both arrays have shape [2], distinct storage, and the checked layout.
18//! unsafe { map_into_validated(&mut dst.view_mut(), &src.view(), |x| x, marker, Exec::serial()) }.unwrap();
19//! ```
20//!
21//! A marker alone does not make the prevalidated entry safe to call:
22//!
23//! ```compile_fail,E0133
24//! use strided_basic::{Exec, StridedArray, execution::*};
25//! let src = StridedArray::<f64>::col_major(&[2]);
26//! let mut dst = StridedArray::<f64>::col_major(&[2]);
27//! let marker = validate_destination_layout_without_alloc(&[2], &[1]).unwrap();
28//! map_into_validated(&mut dst.view_mut(), &src.view(), |x| x, marker, Exec::serial()).unwrap();
29//! ```
30pub use crate::erased_common::{
31 check_dtype, check_static_indexing_dtype, erased_view, validate_uninit_no_overlap,
32};
33pub use crate::kernel::{ensure_same_shape, KernelPlan, SMALL_TENSOR_THRESHOLD};
34pub use crate::layout_check::is_injective_layout;
35pub use crate::map_view::{
36 validate_destination_layout, validate_destination_layout_without_alloc,
37 ValidatedDestinationLayout,
38};
39pub use crate::threading::{
40 parallel_map_reduce, parallel_threads_for_len, SendPtr, MINTHREADLENGTH,
41};
42
43use crate::{ElementOp, Exec, InlineVec, OperandVec, Result, StridedView, StridedViewMut};
44
45/// Prevalidated build plan fused for kernel-family implementations.
46///
47/// # Safety
48/// All rank-indexed arrays must have matching lengths and a valid destination
49/// index (when present). Shape products, stride magnitudes, cost arithmetic,
50/// and every intermediate offset used by planning/iteration must be representable.
51/// Iteration blocks must be positive and offsets must correspond to the supplied
52/// layouts; threaded partitioning additionally requires positive
53/// costs. Callback memory accesses must be valid for each generated
54/// block, with disjoint mutable regions when partitions execute concurrently.
55///
56/// # Examples
57///
58/// ```
59/// use strided_basic::execution::*;
60/// // SAFETY: the example supplies matching bounded layouts and disjoint storage.
61/// let (dims, _, plan) = unsafe { build_plan_fused(&[2, 3], &[&[1, 2]], Some(0), 8) };
62/// assert_eq!(dims.iter().product::<usize>(), 6);
63/// assert_eq!(plan.block.len(), dims.len());
64/// ```
65#[inline]
66pub unsafe fn build_plan_fused(
67 dims: &[usize],
68 strides_list: &[&[isize]],
69 dest_index: Option<usize>,
70 elem_size: usize,
71) -> (InlineVec<usize>, OperandVec<InlineVec<isize>>, KernelPlan) {
72 // SAFETY: the caller supplies the same invariants as the owning checked entry.
73 crate::kernel::build_plan_fused(dims, strides_list, dest_index, elem_size)
74}
75
76/// Prevalidated build plan fused small for kernel-family implementations.
77///
78/// # Safety
79/// All rank-indexed arrays must have matching lengths and a valid destination
80/// index (when present). Shape products, stride magnitudes, cost arithmetic,
81/// and every intermediate offset used by planning/iteration must be representable.
82/// Iteration blocks must be positive and offsets must correspond to the supplied
83/// layouts; threaded partitioning additionally requires positive
84/// costs. Callback memory accesses must be valid for each generated
85/// block, with disjoint mutable regions when partitions execute concurrently.
86///
87/// # Examples
88///
89/// ```
90/// use strided_basic::execution::*;
91/// // SAFETY: the example supplies matching bounded layouts and disjoint storage.
92/// let (dims, _, _) = unsafe { build_plan_fused_small(&[2, 3], &[&[1, 2]]) };
93/// assert_eq!(dims.iter().product::<usize>(), 6);
94/// ```
95#[inline]
96pub unsafe fn build_plan_fused_small(
97 dims: &[usize],
98 strides_list: &[&[isize]],
99) -> (InlineVec<usize>, OperandVec<InlineVec<isize>>, KernelPlan) {
100 // SAFETY: the caller supplies the same invariants as the owning checked entry.
101 crate::kernel::build_plan_fused_small(dims, strides_list)
102}
103
104/// Prevalidated for each inner block preordered for kernel-family implementations.
105///
106/// # Safety
107/// All rank-indexed arrays must have matching lengths and a valid destination
108/// index (when present). Shape products, stride magnitudes, cost arithmetic,
109/// and every intermediate offset used by planning/iteration must be representable.
110/// Iteration blocks must be positive and offsets must correspond to the supplied
111/// layouts; threaded partitioning additionally requires positive
112/// costs. Callback memory accesses must be valid for each generated
113/// block, with disjoint mutable regions when partitions execute concurrently.
114///
115/// # Examples
116///
117/// ```
118/// use strided_basic::execution::*;
119/// // SAFETY: the example supplies matching bounded layouts and disjoint storage.
120/// let mut count = 0;
121/// unsafe { for_each_inner_block_preordered(&[4], &[4], &[vec![1]], &[0], |_, n, _| { count += n; Ok(()) }) }.unwrap();
122/// assert_eq!(count, 4);
123/// ```
124///
125/// # Errors
126/// Forwards errors from the owning kernel or callback; callers must still
127/// satisfy the safety contract before invoking this prevalidated entry.
128#[inline]
129pub unsafe fn for_each_inner_block_preordered<S: AsRef<[isize]>, F>(
130 dims: &[usize],
131 blocks: &[usize],
132 strides: &[S],
133 initial_offsets: &[isize],
134 f: F,
135) -> Result<()>
136where
137 F: FnMut(&[isize], usize, &[isize]) -> Result<()>,
138{
139 // SAFETY: the caller supplies the same invariants as the owning checked entry.
140 crate::kernel::for_each_inner_block_preordered::<S, F>(
141 dims,
142 blocks,
143 strides,
144 initial_offsets,
145 f,
146 )
147}
148
149/// Prevalidated map into validated for kernel-family implementations.
150///
151/// # Safety
152/// All input shapes must match the destination. `validated` must have been
153/// obtained for this destination's current geometry, proving injectivity;
154/// possessing a marker from another layout is not sufficient. View/descriptor
155/// bounds and aliasing contracts must continue to hold throughout replay.
156///
157/// # Examples
158///
159/// ```
160/// use strided_basic::execution::*;
161/// // SAFETY: the example supplies matching bounded layouts and disjoint storage.
162/// use strided_basic::StridedArray;
163/// let src = StridedArray::<f64>::from_parts(vec![2.0; 2], &[2], &[1], 0).unwrap();
164/// let mut dst = StridedArray::<f64>::col_major(&[2]);
165/// let checked = validate_destination_layout_without_alloc(&[2], &[1]).unwrap();
166/// unsafe { map_into_validated(&mut dst.view_mut(), &src.view(), |a| a, checked, strided_basic::Exec::serial()) }.unwrap();
167/// assert_eq!(dst.get(&[1]), 2.0);
168/// ```
169///
170/// # Errors
171/// Forwards errors from the owning kernel or callback; callers must still
172/// satisfy the safety contract before invoking this prevalidated entry.
173#[inline]
174pub unsafe fn map_into_validated<D: Copy + Send + Sync, A: Copy + Send + Sync, Op: ElementOp<A>>(
175 dest: &mut StridedViewMut<D>,
176 src: &StridedView<A, Op>,
177 f: impl Fn(A) -> D + Sync,
178 validated: ValidatedDestinationLayout,
179 exec: Exec<'_>,
180) -> Result<()> {
181 // SAFETY: the caller supplies the same invariants as the owning checked entry.
182 crate::map_view::map_into_validated::<D, A, Op>(dest, src, f, validated, exec)
183}
184
185/// Prevalidated zip map2 into validated for kernel-family implementations.
186///
187/// # Safety
188/// All input shapes must match the destination. `validated` must have been
189/// obtained for this destination's current geometry, proving injectivity;
190/// possessing a marker from another layout is not sufficient. View/descriptor
191/// bounds and aliasing contracts must continue to hold throughout replay.
192///
193/// # Examples
194///
195/// ```
196/// use strided_basic::execution::*;
197/// // SAFETY: the example supplies matching bounded layouts and disjoint storage.
198/// use strided_basic::StridedArray;
199/// let src = StridedArray::<f64>::from_parts(vec![2.0; 2], &[2], &[1], 0).unwrap();
200/// let mut dst = StridedArray::<f64>::col_major(&[2]);
201/// let checked = validate_destination_layout_without_alloc(&[2], &[1]).unwrap();
202/// unsafe { zip_map2_into_validated(&mut dst.view_mut(), &src.view(), &src.view(), |a, b| a + b, checked, strided_basic::Exec::serial()) }.unwrap();
203/// assert_eq!(dst.get(&[1]), 4.0);
204/// ```
205///
206/// # Errors
207/// Forwards errors from the owning kernel or callback; callers must still
208/// satisfy the safety contract before invoking this prevalidated entry.
209#[inline]
210pub unsafe fn zip_map2_into_validated<
211 D: Copy + Send + Sync,
212 A: Copy + Send + Sync,
213 B: Copy + Send + Sync,
214 OpA: ElementOp<A>,
215 OpB: ElementOp<B>,
216>(
217 dest: &mut StridedViewMut<D>,
218 a: &StridedView<A, OpA>,
219 b: &StridedView<B, OpB>,
220 f: impl Fn(A, B) -> D + Sync,
221 validated: ValidatedDestinationLayout,
222 exec: Exec<'_>,
223) -> Result<()> {
224 // SAFETY: the caller supplies the same invariants as the owning checked entry.
225 crate::map_view::zip_map2_into_validated::<D, A, B, OpA, OpB>(dest, a, b, f, validated, exec)
226}
227
228/// Prevalidated zip map3 into validated for kernel-family implementations.
229///
230/// # Safety
231/// All input shapes must match the destination. `validated` must have been
232/// obtained for this destination's current geometry, proving injectivity;
233/// possessing a marker from another layout is not sufficient. View/descriptor
234/// bounds and aliasing contracts must continue to hold throughout replay.
235///
236/// # Examples
237///
238/// ```
239/// use strided_basic::execution::*;
240/// // SAFETY: the example supplies matching bounded layouts and disjoint storage.
241/// use strided_basic::StridedArray;
242/// let src = StridedArray::<f64>::from_parts(vec![2.0; 2], &[2], &[1], 0).unwrap();
243/// let mut dst = StridedArray::<f64>::col_major(&[2]);
244/// let checked = validate_destination_layout_without_alloc(&[2], &[1]).unwrap();
245/// unsafe { zip_map3_into_validated(&mut dst.view_mut(), &src.view(), &src.view(), &src.view(), |a, b, c| a + b + c, checked, strided_basic::Exec::serial()) }.unwrap();
246/// assert_eq!(dst.get(&[1]), 6.0);
247/// ```
248///
249/// # Errors
250/// Forwards errors from the owning kernel or callback; callers must still
251/// satisfy the safety contract before invoking this prevalidated entry.
252#[inline]
253pub unsafe fn zip_map3_into_validated<
254 D: Copy + Send + Sync,
255 A: Copy + Send + Sync,
256 B: Copy + Send + Sync,
257 C: Copy + Send + Sync,
258 OpA: ElementOp<A>,
259 OpB: ElementOp<B>,
260 OpC: ElementOp<C>,
261>(
262 dest: &mut StridedViewMut<D>,
263 a: &StridedView<A, OpA>,
264 b: &StridedView<B, OpB>,
265 c: &StridedView<C, OpC>,
266 f: impl Fn(A, B, C) -> D + Sync,
267 validated: ValidatedDestinationLayout,
268 exec: Exec<'_>,
269) -> Result<()> {
270 // SAFETY: the caller supplies the same invariants as the owning checked entry.
271 crate::map_view::zip_map3_into_validated::<D, A, B, C, OpA, OpB, OpC>(
272 dest, a, b, c, f, validated, exec,
273 )
274}
275
276/// Prevalidated zip map4 into validated for kernel-family implementations.
277///
278/// # Safety
279/// All input shapes must match the destination. `validated` must have been
280/// obtained for this destination's current geometry, proving injectivity;
281/// possessing a marker from another layout is not sufficient. View/descriptor
282/// bounds and aliasing contracts must continue to hold throughout replay.
283///
284/// # Examples
285///
286/// ```
287/// use strided_basic::execution::*;
288/// // SAFETY: the example supplies matching bounded layouts and disjoint storage.
289/// use strided_basic::StridedArray;
290/// let src = StridedArray::<f64>::from_parts(vec![2.0; 2], &[2], &[1], 0).unwrap();
291/// let mut dst = StridedArray::<f64>::col_major(&[2]);
292/// let checked = validate_destination_layout_without_alloc(&[2], &[1]).unwrap();
293/// unsafe { zip_map4_into_validated(&mut dst.view_mut(), &src.view(), &src.view(), &src.view(), &src.view(), |a, b, c, d| a + b + c + d, checked, strided_basic::Exec::serial()) }.unwrap();
294/// assert_eq!(dst.get(&[1]), 8.0);
295/// ```
296///
297/// # Errors
298/// Forwards errors from the owning kernel or callback; callers must still
299/// satisfy the safety contract before invoking this prevalidated entry.
300#[inline]
301#[allow(clippy::too_many_arguments)]
302pub unsafe fn zip_map4_into_validated<
303 D: Copy + Send + Sync,
304 A: Copy + Send + Sync,
305 B: Copy + Send + Sync,
306 C: Copy + Send + Sync,
307 E: Copy + Send + Sync,
308 OpA: ElementOp<A>,
309 OpB: ElementOp<B>,
310 OpC: ElementOp<C>,
311 OpE: ElementOp<E>,
312>(
313 dest: &mut StridedViewMut<D>,
314 a: &StridedView<A, OpA>,
315 b: &StridedView<B, OpB>,
316 c: &StridedView<C, OpC>,
317 e: &StridedView<E, OpE>,
318 f: impl Fn(A, B, C, E) -> D + Sync,
319 validated: ValidatedDestinationLayout,
320 exec: Exec<'_>,
321) -> Result<()> {
322 // SAFETY: the caller supplies the same invariants as the owning checked entry.
323 crate::map_view::zip_map4_into_validated::<D, A, B, C, E, OpA, OpB, OpC, OpE>(
324 dest, a, b, c, e, f, validated, exec,
325 )
326}
327
328/// Prevalidated map raw into validated for kernel-family implementations.
329///
330/// # Safety
331/// All input shapes must match the destination. `validated` must have been
332/// obtained for this destination's current geometry, proving injectivity;
333/// possessing a marker from another layout is not sufficient. View/descriptor
334/// bounds and aliasing contracts must continue to hold throughout replay.
335///
336/// # Examples
337///
338/// ```
339/// use strided_basic::execution::*;
340/// // SAFETY: the example supplies matching bounded layouts and disjoint storage.
341/// use strided_basic::{RawStridedRef, RawStridedMut, Identity};
342/// let values = [2.0_f64; 2];
343/// let src = RawStridedRef::new(&values, &[2], &[1], 0).unwrap();
344/// let mut output = [0.0; 2];
345/// let mut dst = RawStridedMut::new(&mut output, &[2], &[1], 0).unwrap();
346/// let checked = validate_destination_layout_without_alloc(&[2], &[1]).unwrap();
347/// unsafe { map_raw_into_validated::<f64, f64, Identity>(&mut dst, &src, |a| a, checked, strided_basic::Exec::serial()) }.unwrap();
348/// assert_eq!(output, [2.0; 2]);
349/// ```
350///
351/// # Errors
352/// Forwards errors from the owning kernel or callback; callers must still
353/// satisfy the safety contract before invoking this prevalidated entry.
354#[inline]
355pub unsafe fn map_raw_into_validated<
356 D: Copy + Send + Sync,
357 A: Copy + Send + Sync,
358 Op: ElementOp<A>,
359>(
360 dest: &mut crate::RawStridedMut<'_, D>,
361 src: &crate::RawStridedRef<'_, A>,
362 f: impl Fn(A) -> D + Sync,
363 validated: ValidatedDestinationLayout,
364 exec: Exec<'_>,
365) -> Result<()> {
366 // SAFETY: the caller supplies the same invariants as the owning checked entry.
367 crate::map_view::map_raw_into_validated::<D, A, Op>(dest, src, f, validated, exec)
368}
369
370/// Prevalidated zip map2 raw into validated for kernel-family implementations.
371///
372/// # Safety
373/// All input shapes must match the destination. `validated` must have been
374/// obtained for this destination's current geometry, proving injectivity;
375/// possessing a marker from another layout is not sufficient. View/descriptor
376/// bounds and aliasing contracts must continue to hold throughout replay.
377///
378/// # Examples
379///
380/// ```
381/// use strided_basic::execution::*;
382/// // SAFETY: the example supplies matching bounded layouts and disjoint storage.
383/// use strided_basic::{RawStridedRef, RawStridedMut, Identity};
384/// let values = [2.0_f64; 2];
385/// let src = RawStridedRef::new(&values, &[2], &[1], 0).unwrap();
386/// let mut output = [0.0; 2];
387/// let mut dst = RawStridedMut::new(&mut output, &[2], &[1], 0).unwrap();
388/// let checked = validate_destination_layout_without_alloc(&[2], &[1]).unwrap();
389/// unsafe { zip_map2_raw_into_validated::<f64, f64, f64, Identity, Identity>(&mut dst, &src, &src, |a, b| a + b, checked, strided_basic::Exec::serial()) }.unwrap();
390/// assert_eq!(output, [4.0; 2]);
391/// ```
392///
393/// # Errors
394/// Forwards errors from the owning kernel or callback; callers must still
395/// satisfy the safety contract before invoking this prevalidated entry.
396#[inline]
397pub unsafe fn zip_map2_raw_into_validated<
398 D: Copy + Send + Sync,
399 A: Copy + Send + Sync,
400 B: Copy + Send + Sync,
401 OpA: ElementOp<A>,
402 OpB: ElementOp<B>,
403>(
404 dest: &mut crate::RawStridedMut<'_, D>,
405 a: &crate::RawStridedRef<'_, A>,
406 b: &crate::RawStridedRef<'_, B>,
407 f: impl Fn(A, B) -> D + Sync,
408 validated: ValidatedDestinationLayout,
409 exec: Exec<'_>,
410) -> Result<()> {
411 // SAFETY: the caller supplies the same invariants as the owning checked entry.
412 crate::map_view::zip_map2_raw_into_validated::<D, A, B, OpA, OpB>(
413 dest, a, b, f, validated, exec,
414 )
415}
416
417/// Prevalidated compute costs for kernel-family implementations.
418///
419/// # Safety
420/// All rank-indexed arrays must have matching lengths and a valid destination
421/// index (when present). Shape products, stride magnitudes, cost arithmetic,
422/// and every intermediate offset used by planning/iteration must be representable.
423/// Iteration blocks must be positive and offsets must correspond to the supplied
424/// layouts; threaded partitioning additionally requires positive
425/// costs. Callback memory accesses must be valid for each generated
426/// block, with disjoint mutable regions when partitions execute concurrently.
427///
428/// # Examples
429///
430/// ```
431/// use strided_basic::execution::*;
432/// // SAFETY: the example supplies matching bounded layouts and disjoint storage.
433/// let costs = unsafe { compute_costs(&[vec![1, 4], vec![1, 8]]) };
434/// assert_eq!(costs.as_slice(), [2, 8]);
435/// ```
436#[inline]
437pub unsafe fn compute_costs<S: AsRef<[isize]>>(all_strides: &[S]) -> InlineVec<isize> {
438 // SAFETY: the caller supplies the same invariants as the owning checked entry.
439 crate::fuse::compute_costs::<S>(all_strides)
440}
441
442/// Prevalidated mapreduce threaded for kernel-family implementations.
443///
444/// # Safety
445/// All rank-indexed arrays must have matching lengths and a valid destination
446/// index (when present). Shape products, stride magnitudes, cost arithmetic,
447/// and every intermediate offset used by planning/iteration must be representable.
448/// Iteration blocks must be positive and offsets must correspond to the supplied
449/// layouts; threaded partitioning additionally requires positive
450/// costs. Callback memory accesses must be valid for each generated
451/// block, with disjoint mutable regions when partitions execute concurrently.
452///
453/// # Examples
454///
455/// ```
456/// use strided_basic::execution::*;
457/// // SAFETY: the example supplies matching bounded layouts and disjoint storage.
458/// use std::sync::atomic::{AtomicUsize, Ordering};
459/// let count = AtomicUsize::new(0);
460/// unsafe { mapreduce_threaded(&[4], &[4], &[vec![1]], &[0], &[2], strided_basic::Exec::serial(), &|dims, _, _, _| { count.fetch_add(dims.iter().product::<usize>(), Ordering::Relaxed); Ok(()) }) }.unwrap();
461/// assert_eq!(count.load(Ordering::Relaxed), 4);
462/// ```
463///
464/// # Errors
465/// Forwards errors from the owning kernel or callback; callers must still
466/// satisfy the safety contract before invoking this prevalidated entry.
467#[inline]
468pub unsafe fn mapreduce_threaded<S: AsRef<[isize]>, F>(
469 dims: &[usize],
470 blocks: &[usize],
471 strides_list: &[S],
472 offsets: &[isize],
473 costs: &[isize],
474 exec: Exec<'_>,
475 f: &F,
476) -> Result<()>
477where
478 F: Fn(&[usize], &[usize], &[&[isize]], &[isize]) -> Result<()> + Sync,
479{
480 // SAFETY: the caller supplies the same invariants as the owning checked entry.
481 crate::threading::mapreduce_threaded::<S, F>(
482 dims,
483 blocks,
484 strides_list,
485 offsets,
486 costs,
487 exec,
488 f,
489 )
490}
491
492/// Full-overwrite indexed replay for an operation-family adapter.
493///
494/// # Safety
495/// The adapter must reject input/output overlap before creating the input
496/// references. All descriptor allocation and initialization contracts must
497/// remain valid for the call. Output slots may be uninitialized; the owning
498/// plan retains its checked layout/index validation and private initialization
499/// receipt. No initialized reference to the output backing may be formed.
500/// Gather into uninitialized output without exposing an initialization receipt.
501///
502/// # Examples
503///
504/// ```
505/// use strided_basic::{RawStridedRef, RawStridedMut};
506/// use strided_basic::execution::*;
507/// use core::mem::MaybeUninit;
508/// use strided_basic::{GatherPlan, GatherSpec};
509/// let spec = GatherSpec { offset_dims: vec![], collapsed_slice_dims: vec![0], start_index_map: vec![0], index_vector_dim: 1, slice_sizes: vec![1] };
510/// let plan = GatherPlan::compile(&[3], &[1], &[2, 1], &[1, 2], &[2], &[1], spec).unwrap();
511/// let src = RawStridedRef::new(&[1_i32, 2, 3], &[3], &[1], 0).unwrap();
512/// let indices = RawStridedRef::new(&[0_i32, 2], &[2, 1], &[1, 2], 0).unwrap();
513/// let mut values = [MaybeUninit::<i32>::uninit(); 2];
514/// let mut dst = RawStridedMut::new(&mut values, &[2], &[1], 0).unwrap();
515/// // SAFETY: input and output allocations are disjoint and layouts match the plan.
516/// unsafe { gather_into_uninit(&plan, &mut dst, &src, &indices, strided_basic::Exec::serial()) }.unwrap();
517/// assert_eq!(unsafe { values[1].assume_init() }, 3);
518/// ```
519///
520/// # Errors
521/// Forwards the plan layout/index validation errors before successful overwrite.
522#[inline]
523pub unsafe fn gather_into_uninit<T, I>(
524 plan: &crate::GatherPlan,
525 dest: &mut crate::RawStridedMut<'_, core::mem::MaybeUninit<T>>,
526 operand: &crate::RawStridedRef<'_, T>,
527 start_indices: &crate::RawStridedRef<'_, I>,
528 exec: Exec<'_>,
529) -> Result<()>
530where
531 T: Copy + Send + Sync,
532 I: crate::GatherIndex,
533{
534 plan.execute_uninit(dest, operand, start_indices, exec)
535}
536
537/// Full-overwrite indexed replay for an operation-family adapter.
538///
539/// # Safety
540/// The adapter must reject input/output overlap before creating the input
541/// references. All descriptor allocation and initialization contracts must
542/// remain valid for the call. Output slots may be uninitialized; the owning
543/// plan retains its checked layout/index validation and private initialization
544/// receipt. No initialized reference to the output backing may be formed.
545///
546/// # Examples
547///
548/// ```
549/// use strided_basic::execution::*;
550/// // SAFETY: the example supplies matching bounded layouts and disjoint storage.
551/// use strided_basic::{DynamicSlicePlan, RawStridedRef, RawStridedMut};
552/// use core::mem::MaybeUninit;
553/// let plan = DynamicSlicePlan::compile(&[3], &[1], &[1], &[1], &[2], &[1], &[2]).unwrap();
554/// let src = RawStridedRef::new(&[1_i32, 2, 3], &[3], &[1], 0).unwrap();
555/// let starts = RawStridedRef::new(&[1_i32], &[1], &[1], 0).unwrap();
556/// let mut values = [MaybeUninit::<i32>::uninit(); 2];
557/// let mut dst = RawStridedMut::new(&mut values, &[2], &[1], 0).unwrap();
558/// unsafe { dynamic_slice_into_uninit(&plan, &mut dst, &src, &starts, strided_basic::Exec::serial()) }.unwrap();
559/// assert_eq!(unsafe { values[1].assume_init() }, 3);
560/// ```
561///
562/// # Errors
563/// Forwards errors from the owning kernel or callback; callers must still
564/// satisfy the safety contract before invoking this prevalidated entry.
565#[inline]
566pub unsafe fn dynamic_slice_into_uninit<T, I>(
567 plan: &crate::DynamicSlicePlan,
568 dest: &mut crate::RawStridedMut<'_, core::mem::MaybeUninit<T>>,
569 operand: &crate::RawStridedRef<'_, T>,
570 starts: &crate::RawStridedRef<'_, I>,
571 exec: Exec<'_>,
572) -> Result<()>
573where
574 T: Copy + Send + Sync,
575 I: crate::GatherIndex,
576{
577 plan.execute_uninit(dest, operand, starts, exec)
578}
579
580/// Full-overwrite indexed replay for an operation-family adapter.
581///
582/// # Safety
583/// The adapter must reject input/output overlap before creating the input
584/// references. All descriptor allocation and initialization contracts must
585/// remain valid for the call. Output slots may be uninitialized; the owning
586/// plan retains its checked layout/index validation and private initialization
587/// receipt. No initialized reference to the output backing may be formed.
588/// Copy the operand and overwrite its selected window.
589///
590/// # Examples
591///
592/// ```
593/// use strided_basic::{RawStridedRef, RawStridedMut};
594/// use strided_basic::execution::*;
595/// use core::mem::MaybeUninit;
596/// use strided_basic::DynamicUpdateSlicePlan;
597/// let plan = DynamicUpdateSlicePlan::compile(&[3], &[1], &[1], &[1], &[1], &[1], &[3], &[1]).unwrap();
598/// let src = RawStridedRef::new(&[1_i32, 2, 3], &[3], &[1], 0).unwrap();
599/// let update = RawStridedRef::new(&[9_i32], &[1], &[1], 0).unwrap();
600/// let starts = RawStridedRef::new(&[1_i32], &[1], &[1], 0).unwrap();
601/// let mut values = [MaybeUninit::<i32>::uninit(); 3];
602/// let mut dst = RawStridedMut::new(&mut values, &[3], &[1], 0).unwrap();
603/// // SAFETY: all inputs are initialized and disjoint from the matching output.
604/// unsafe { dynamic_update_into_uninit(&plan, &mut dst, &src, &update, &starts, strided_basic::Exec::serial()) }.unwrap();
605/// assert_eq!(unsafe { values[1].assume_init() }, 9);
606/// ```
607///
608/// # Errors
609/// Forwards the plan layout/index validation errors.
610#[inline]
611pub unsafe fn dynamic_update_into_uninit<'a, T, I>(
612 plan: &crate::DynamicUpdateSlicePlan,
613 dest: &'a mut crate::RawStridedMut<'a, core::mem::MaybeUninit<T>>,
614 operand: &crate::RawStridedRef<'_, T>,
615 update: &crate::RawStridedRef<'_, T>,
616 starts: &crate::RawStridedRef<'_, I>,
617 exec: Exec<'_>,
618) -> Result<()>
619where
620 T: Copy + Send + Sync,
621 I: crate::GatherIndex,
622{
623 plan.execute_uninit(dest, operand, update, starts, exec)
624}
625
626/// Full-overwrite indexed replay for an operation-family adapter.
627///
628/// # Safety
629/// The adapter must reject input/output overlap before creating the input
630/// references. All descriptor allocation and initialization contracts must
631/// remain valid for the call. Output slots may be uninitialized; the owning
632/// plan retains its checked layout/index validation and private initialization
633/// receipt. No initialized reference to the output backing may be formed.
634/// Copy the operand before additive scatter into its initialized logical slots.
635///
636/// # Examples
637///
638/// ```
639/// use strided_basic::{RawStridedRef, RawStridedMut};
640/// use strided_basic::execution::*;
641/// use core::mem::MaybeUninit;
642/// use strided_basic::{ScatterPlan, ScatterSpec};
643/// let spec = ScatterSpec { update_window_dims: vec![], inserted_window_dims: vec![0], scatter_dims_to_operand_dims: vec![0], index_vector_dim: 1 };
644/// let plan = ScatterPlan::compile(&[3], &[1], &[1, 1], &[1, 1], &[1], &[1], &[3], &[1], spec).unwrap();
645/// let src = RawStridedRef::new(&[1_i32, 2, 3], &[3], &[1], 0).unwrap();
646/// let update = RawStridedRef::new(&[9_i32], &[1], &[1], 0).unwrap();
647/// let indices = RawStridedRef::new(&[1_i64], &[1, 1], &[1, 1], 0).unwrap();
648/// let mut values = [MaybeUninit::<i32>::uninit(); 3];
649/// let mut dst = RawStridedMut::new(&mut values, &[3], &[1], 0).unwrap();
650/// // SAFETY: all inputs are initialized and disjoint from the matching output.
651/// unsafe { scatter_into_uninit(&plan, &mut dst, &src, &indices, &update, i32::wrapping_add, strided_basic::Exec::serial()) }.unwrap();
652/// assert_eq!(unsafe { values[1].assume_init() }, 11);
653/// ```
654///
655/// # Errors
656/// Forwards the plan layout/index validation errors.
657#[inline]
658pub unsafe fn scatter_into_uninit<'a, T, I>(
659 plan: &crate::ScatterPlan,
660 dest: &'a mut crate::RawStridedMut<'a, core::mem::MaybeUninit<T>>,
661 operand: &crate::RawStridedRef<'_, T>,
662 scatter_indices: &crate::RawStridedRef<'_, I>,
663 updates: &crate::RawStridedRef<'_, T>,
664 combine: fn(T, T) -> T,
665 exec: Exec<'_>,
666) -> Result<()>
667where
668 T: Copy + core::ops::Add<Output = T> + Send + Sync,
669 I: crate::GatherIndex,
670{
671 plan.execute_uninit(dest, operand, scatter_indices, updates, combine, exec)
672}