packed_simd 0.3.9

Portable Packed SIMD vectors
Documentation
//! Minimal API of signed integer, unsigned integer, and floating-point
//! vectors.

macro_rules! impl_minimal_iuf {
    ([$elem_ty:ident; $elem_count:expr]: $id:ident | $ielem_ty:ident |
     $test_tt:tt | $($elem_name:ident),+ | $(#[$doc:meta])*) => {

        $(#[$doc])*
        pub type $id = Simd<[$elem_ty; $elem_count]>;

        impl sealed::Simd for $id {
            type Element = $elem_ty;
            const LANES: usize = $elem_count;
            type LanesType = [u32; $elem_count];
        }

        impl $id {
            /// Creates a new instance with each vector elements initialized
            /// with the provided values.
            #[inline]
            #[allow(clippy::too_many_arguments)]
            pub const fn new($($elem_name: $elem_ty),*) -> Self {
                Simd(codegen::$id($($elem_name as $ielem_ty),*))
            }

            /// Returns the number of vector lanes.
            #[inline]
            pub const fn lanes() -> usize {
                $elem_count
            }

            /// Constructs a new instance with each element initialized to
            /// `value`.
            #[inline]
            pub const fn splat(value: $elem_ty) -> Self {
                Simd(codegen::$id($({
                    #[allow(non_camel_case_types, dead_code)]
                    struct $elem_name;
                    value as $ielem_ty
                }),*))
            }

            /// Extracts the value at `index`.
            ///
            /// # Panics
            ///
            /// If `index >= Self::lanes()`.
            #[inline]
            pub fn extract(self, index: usize) -> $elem_ty {
                assert!(index < $elem_count);
                unsafe { self.extract_unchecked(index) }
            }

            /// Extracts the value at `index`.
            ///
            /// # Safety
            ///
            /// If `index >= Self::lanes()` the behavior is undefined.
            #[inline]
            pub unsafe fn extract_unchecked(self, index: usize) -> $elem_ty {
                use crate::llvm::simd_extract;
                let e: $ielem_ty = simd_extract(self.0, index as u32);
                e as $elem_ty
            }

            /// Returns a new vector where the value at `index` is replaced by `new_value`.
            ///
            /// # Panics
            ///
            /// If `index >= Self::lanes()`.
            #[inline]
            #[must_use = "replace does not modify the original value - \
                          it returns a new vector with the value at `index` \
                          replaced by `new_value`d"
            ]
            pub fn replace(self, index: usize, new_value: $elem_ty) -> Self {
                assert!(index < $elem_count);
                unsafe { self.replace_unchecked(index, new_value) }
            }

            /// Returns a new vector where the value at `index` is replaced by `new_value`.
            ///
            /// # Safety
            ///
            /// If `index >= Self::lanes()` the behavior is undefined.
            #[inline]
            #[must_use = "replace_unchecked does not modify the original value - \
                          it returns a new vector with the value at `index` \
                          replaced by `new_value`d"
            ]
            pub unsafe fn replace_unchecked(
                self,
                index: usize,
                new_value: $elem_ty,
            ) -> Self {
                use crate::llvm::simd_insert;
                Simd(simd_insert(self.0, index as u32, new_value as $ielem_ty))
            }
        }

        test_if!{
            $test_tt:
            paste::item! {
                // Comparisons use integer casts within mantissa^1 range.
                #[allow(clippy::float_cmp)]
                pub mod [<$id _minimal>] {
                    use super::*;
                    #[cfg_attr(not(target_arch = "wasm32"), test)]
                    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
                    fn minimal() {
                        // lanes:
                        assert_eq!($elem_count, $id::lanes());

                        // splat and extract / extract_unchecked:
                        const VAL: $elem_ty = 7 as $elem_ty;
                        const VEC: $id = $id::splat(VAL);
                        for i in 0..$id::lanes() {
                            assert_eq!(VAL, VEC.extract(i));
                            assert_eq!(
                                VAL, unsafe { VEC.extract_unchecked(i) }
                            );
                        }

                        // replace / replace_unchecked
                        let new_vec = VEC.replace(0, 42 as $elem_ty);
                        for i in 0..$id::lanes() {
                            if i == 0 {
                                assert_eq!(42 as $elem_ty, new_vec.extract(i));
                            } else {
                                assert_eq!(VAL, new_vec.extract(i));
                            }
                        }
                        let new_vec = unsafe {
                            VEC.replace_unchecked(0, 42 as $elem_ty)
                        };
                        for i in 0..$id::lanes() {
                            if i == 0 {
                                assert_eq!(42 as $elem_ty, new_vec.extract(i));
                            } else {
                                assert_eq!(VAL, new_vec.extract(i));
                            }
                        }
                    }

                    // FIXME: wasm-bindgen-test does not support #[should_panic]
                    // #[cfg_attr(not(target_arch = "wasm32"), test)] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
                    #[cfg(not(target_arch = "wasm32"))]
                    #[test]
                    #[should_panic]
                    fn extract_panic_oob() {
                        const VAL: $elem_ty = 7 as $elem_ty;
                        const VEC: $id = $id::splat(VAL);
                        let _ = VEC.extract($id::lanes());
                    }
                    // FIXME: wasm-bindgen-test does not support #[should_panic]
                    // #[cfg_attr(not(target_arch = "wasm32"), test)] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
                    #[cfg(not(target_arch = "wasm32"))]
                    #[test]
                    #[should_panic]
                    fn replace_panic_oob() {
                        const VAL: $elem_ty = 7 as $elem_ty;
                        const VEC: $id = $id::splat(VAL);
                        let _ = VEC.replace($id::lanes(), 42 as $elem_ty);
                    }
                }
            }
        }
    }
}