Skip to main content

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