slices_dispatch_wide!

Crates.io docs.rs Crates.io Crates.io


A macro to dispatch vectorized math over slices using the wide crate for SIMD operations

This crate iterates over chunks of your slice, converts them to types from the wide crate, and dispatches some math over both those chunks and the remaining scalar elements. This crate will not work for you in every situation, does not do anything special for alignment, and probably won't beat the best possible hand-tuned SIMD code. That being said, if it works for your use case it will make your life easier.

This crate will be most useful if: - You need SIMD math operations (such as sqrt, log, exp, etc.) on stable Rust, today. - You don't want to bring in non-Rust libraries or complicate your build process to do that. - You need to iterate over multiple slices of the same length in lockstep, and modify at least one of them. - You don't want to repeat yourself or write boilerplate. - You don't need variable lane width.

Examples

```rust use slicesdispatchwide::*;

let mut a = [1.0f64, 2.0, 3.0, 4.0, 5.0, 6.0]; let b = [2.0f64, 2.0, 2.0, 2.0, 2.0, 2.0];

// Dispatches using chunks/SIMD types of width 4 slicesdispatchwide!(4, |a => a mut: f64, b => b: f64| { // We can mutate the slices when the mut keyword is specified as it is above a += b; }); // Notice that the number of elements is not a multiple of the SIMD width, the remainder is // taken care of with scalar operations assert_eq!(a, [3.0, 4.0, 5.0, 6.0, 7.0, 8.0]);

// We can also do some fancier math operations in place slicesdispatchwide!(2, |a => a mut: f64| { a = a.powf(2.0); }); assert_eq!(a, [9.0, 16.0, 25.0, 36.0, 49.0, 64.0]);

// You can assign different names to the elements from the slices you use // And you can mutate multiple variables at the same time let mut some_container = ([1.0, 2.0, 3.0, 4.0, 5.0, 6.0], "test", 0); let mut c = [4.0, 2.0, 1.0, 0.0, 1.0, 2.0];

slicesdispatchwide!(4, |somecontainer.0 => sc mut: f64, c => d mut: f64| { sc += d; d += sc; }); asserteq!(somecontainer.0, [5.0, 4.0, 4.0, 4.0, 6.0, 8.0]); asserteq!(c, [9.0, 6.0, 5.0, 4.0, 7.0, 10.0]);

// If you need to get the result in a new array/vector, you can pre-allocate it let mut d = [0.0; 6]; slicesdispatchwide!(4, |somecontainer.0 => sc: f64, d => d mut: f64| { d = 2.0 * sc; }); asserteq!(d, [10.0, 8.0, 8.0, 8.0, 12.0, 16.0]); ```

Note that if the slice lengths don't match, this macro will panic ```should_panic // This example will panic because the lengths are different

use slicesdispatchwide::*;

let a = [0u32]; let b = [0u32, 1]; slicesdispatchwide!(8, |a => a: u32, b => b: u32| {}); ```

And the width must be a literal ```compile_fail // This example will not compile because the width is not a literal

use slicesdispatchwide::*;

let a = [0u32]; let b = [0u32]; slicesdispatchwide!(4 + 4, |a => a: u32, b => b: u32| {}); ```

Caveats

License

Licensed under any of

at your choice.