Skip to main content

map_into_uninit_with_kernel

Function map_into_uninit_with_kernel 

Source
pub fn map_into_uninit_with_kernel<T>(
    dest: &mut StridedViewMut<'_, MaybeUninit<T>>,
    src: &StridedView<'_, T>,
    kernel: impl Fn(&[T], &mut [MaybeUninit<T>]) -> bool + Sync,
    scalar: impl Fn(T) -> T + MaybeSync,
) -> Result<(), StridedError>
where T: Copy + MaybeSendSync,
Expand description

Apply an element-wise function into a potentially uninitialized destination, handing a vectorized kernel the flat runs it can take.

kernel is offered a flat, unit-stride run whenever this crate has one to give: the whole buffer when the two views share a contiguous layout and the operation runs sequentially, and one block at a time on the parallel path. It must write every element of the run or write nothing — returning false makes that run fall back to scalar, element by element. Runs whose strides are not both 1 never reach it. It is called from whichever threads this crate’s execution policy selected, so it must be Sync.

The point of the entry point is that a caller which owns vector kernels — a SIMD math library, say — reuses this crate’s layout logic and this crate’s threading decision instead of rebuilding either. scalar and kernel must agree up to the caller’s own error bound; this crate only guarantees that every destination element is written exactly once.

§Examples

use std::mem::MaybeUninit;
use strided_basic::{map_into_uninit_with_kernel, StridedView, StridedViewMut};

let src = vec![1.0f64, 2.0, 3.0];
let mut out = vec![MaybeUninit::<f64>::uninit(); 3];
let mut dest = StridedViewMut::new(&mut out, &[3], &[1], 0).unwrap();
let source = StridedView::new(&src, &[3], &[1], 0).unwrap();
let kernel = |src: &[f64], dst: &mut [MaybeUninit<f64>]| {
    for (slot, value) in dst.iter_mut().zip(src) {
        slot.write(value * 2.0);
    }
    true
};
map_into_uninit_with_kernel(&mut dest, &source, kernel, |x| x * 2.0).unwrap();
// SAFETY: the kernel wrote every element.
let values: Vec<f64> = out.into_iter().map(|x| unsafe { x.assume_init() }).collect();
assert_eq!(values, [2.0, 4.0, 6.0]);

§Errors

Returns StridedError::ShapeMismatch when the shapes differ and StridedError::NonInjectiveOutputLayout when the destination layout cannot be proven injective.