slices_dispatch_wide/
lib.rs

1#![doc = include_str!("../README.md")]
2
3pub use itertools;
4pub use paste;
5pub use wide;
6
7/// Macro to help dispatch math over slices using the `wide` crate for SIMD operations
8///
9/// Check out the [crate] documentation for details
10#[macro_export]
11macro_rules! slices_dispatch_wide {
12    (
13        $width: expr,
14        |$($src:expr => $name:ident $($mut_ident:ident)?: $type:ty),+|
15        $work:block
16    ) => {
17        // Assert all slices are the same length
18        {
19            let mut slice_length = None;
20            $(
21                if let Some(other_length) = slice_length {
22                    assert_eq!($src.len(), other_length);
23                }
24                slice_length = Some($src.len());
25            )+
26        }
27
28        $(
29            // Matching against an ident is the most convenient way to actually tell
30            // the mut keyword was used for the outer macro, but we need to make sure
31            // you can't just use any random keyword in that spot
32            $($crate::slices_dispatch_wide!(@enforce_mut_ident_value $mut_ident);)?
33        )+
34
35        $crate::paste::paste! {
36            for (
37                $([< original_ $name >]),+
38            ) in $crate::itertools::izip!(
39                $($crate::slices_dispatch_wide!(@get_chunks $($mut_ident)? $src, $width)),+
40            ) {
41                $(
42                    // This try_into and unwrap should be optimized out
43                    let $($mut_ident)? $name =
44                        $crate::wide::[< $type x $width >]::new([< original_ $name >].try_into().unwrap());
45                )+
46
47                { $work }
48
49                $($(
50                    { let $mut_ident _ignore: (); }
51                    [< original_ $name >].copy_from_slice($name.as_array_ref());
52                )?)+
53            }
54
55            for (
56                $([< original_ $name >]),+
57            ) in $crate::itertools::izip!(
58                $($crate::slices_dispatch_wide!(@get_remainder $($mut_ident)? $src, $width)),+
59            ) {
60               $(
61                   let $($mut_ident)? $name = *[< original_ $name >];
62               )+
63
64               { $work }
65
66                $($(
67                    { let $mut_ident _ignore: (); }
68                    *[< original_ $name >] = $name;
69                )?)+
70            }
71        }
72    };
73
74    (@enforce_mut_ident_value mut) => {};
75
76    (@get_chunks mut $src:expr, $width:literal) => {
77        ($src).chunks_exact_mut($width)
78    };
79    (@get_chunks $src:expr, $width:literal) => {
80        ($src).chunks_exact($width)
81    };
82
83    (@get_remainder mut $src:expr, $width:literal) => {
84        $crate::slices_dispatch_wide!(@get_chunks mut $src, $width).into_remainder()
85    };
86    (@get_remainder $src:expr, $width:literal) => {
87        $crate::slices_dispatch_wide!(@get_chunks $src, $width).remainder()
88    };
89}