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