generic-simd 0.1.0

safe and idiomatic zero-cost abstractions for writing explicit cross-platform SIMD operations
Documentation
macro_rules! arithmetic_ops {
    {
        @new $type:ty, $feature:expr, $trait:ident, $func:ident, ()
    } => {
        impl core::ops::$trait<$type> for $type {
            type Output = Self;
            #[allow(unused_unsafe)]
            #[inline]
            fn $func(mut self, rhs: Self) -> Self {
                for (a, b) in self.iter_mut().zip(rhs.iter()) {
                    *a = core::ops::$trait::$func(*a, b);
                }
                self
            }
        }

        impl core::ops::$trait<<$type as $crate::vector::Vector>::Scalar> for $type {
            type Output = Self;
            #[inline]
            fn $func(mut self, rhs: <$type as $crate::vector::Vector>::Scalar) -> Self {
                for a in self.iter_mut() {
                    *a = core::ops::$trait::$func(*a, rhs);
                }
                self
            }
        }
    };
    {
        @assign $type:ty, $feature:expr, $trait:ident, $func:ident, ()
    } => {
        impl core::ops::$trait<$type> for $type {
            #[allow(unused_unsafe)]
            #[inline]
            fn $func(&mut self, rhs: Self) {
                for (a, b) in self.iter_mut().zip(rhs.iter()) {
                    core::ops::$trait::$func(a, b);
                }
            }
        }

        impl core::ops::$trait<<$type as $crate::vector::Vector>::Scalar> for $type {
            #[inline]
            fn $func(&mut self, rhs: <$type as $crate::vector::Vector>::Scalar) {
                for a in self.iter_mut() {
                    core::ops::$trait::$func(a, rhs);
                }
            }
        }
    };
    {
        @new $type:ty, $feature:expr, $trait:ident, $func:ident, ($op:path)
    } => {
        impl core::ops::$trait<$type> for $type {
            type Output = Self;
            #[allow(unused_unsafe)]
            #[inline]
            fn $func(self, rhs: Self) -> Self {
                Self(unsafe { $op(self.0, rhs.0) })
            }
        }

        impl core::ops::$trait<<$type as $crate::vector::Vector>::Scalar> for $type {
            type Output = Self;
            #[inline]
            fn $func(self, rhs: <$type as $crate::vector::Vector>::Scalar) -> Self {
                self.$func(<$type>::splat(unsafe { $feature }, rhs))
            }
        }
    };
    {
        @assign $type:ty, $feature:expr, $trait:ident, $func:ident, ($op:path)
    } => {
        impl core::ops::$trait<$type> for $type {
            #[allow(unused_unsafe)]
            #[inline]
            fn $func(&mut self, rhs: Self) {
                self.0 = unsafe { $op(self.0, rhs.0) };
            }
        }

        impl core::ops::$trait<<$type as $crate::vector::Vector>::Scalar> for $type {
            #[inline]
            fn $func(&mut self, rhs: <$type as $crate::vector::Vector>::Scalar) {
                self.$func(<$type>::splat(unsafe { $feature }, rhs))
            }
        }
    };
    {
        feature: $feature:expr,
        for $type:ty:
            add -> $add_expr:tt,
            sub -> $sub_expr:tt,
            mul -> $mul_expr:tt,
            div -> $div_expr:tt
    } => {
        impl core::iter::Sum<$type> for Option<$type> {
            #[inline]
            fn sum<I>(mut iter: I) -> Self
            where
                I: Iterator<Item = $type>,
            {
                if let Some(mut sum) = iter.next() {
                    while let Some(v) = iter.next() {
                        sum += v;
                    }
                    Some(sum)
                } else {
                    None
                }
            }
        }

        impl core::iter::Sum<$type> for <$type as $crate::vector::Vector>::Scalar {
            #[inline]
            fn sum<I>(iter: I) -> Self
            where
                I: Iterator<Item = $type>,
            {
                if let Some(sums) = iter.sum::<Option<$type>>() {
                    sums.iter().sum()
                } else {
                    Default::default()
                }
            }
        }

        impl core::iter::Product<$type> for Option<$type> {
            #[inline]
            fn product<I>(mut iter: I) -> Self
            where
                I: Iterator<Item = $type>,
            {
                if let Some(mut sum) = iter.next() {
                    while let Some(v) = iter.next() {
                        sum *= v;
                    }
                    Some(sum)
                } else {
                    None
                }
            }
        }

        impl core::iter::Product<$type> for <$type as $crate::vector::Vector>::Scalar {
            #[inline]
            fn product<I>(iter: I) -> Self
            where
                I: Iterator<Item = $type>,
            {
                if let Some(sums) = iter.sum::<Option<$type>>() {
                    sums.iter().product()
                } else {
                    Default::default()
                }
            }
        }

        arithmetic_ops!{@new $type, $feature, Add, add, $add_expr}
        arithmetic_ops!{@new $type, $feature, Sub, sub, $sub_expr}
        arithmetic_ops!{@new $type, $feature, Mul, mul, $mul_expr}
        arithmetic_ops!{@new $type, $feature, Div, div, $div_expr}
        arithmetic_ops!{@assign $type, $feature, AddAssign, add_assign, $add_expr}
        arithmetic_ops!{@assign $type, $feature, SubAssign, sub_assign, $sub_expr}
        arithmetic_ops!{@assign $type, $feature, MulAssign, mul_assign, $mul_expr}
        arithmetic_ops!{@assign $type, $feature, DivAssign, div_assign, $div_expr}
    };
}

macro_rules! as_slice {
    {
        $type:ty
    } => {
        impl AsRef<[<$type as crate::vector::Vector>::Scalar]> for $type {
            #[inline]
            fn as_ref(&self) -> &[<$type as crate::vector::Vector>::Scalar] {
                use crate::vector::Vector;
                self.as_slice()
            }
        }

        impl AsMut<[<$type as crate::vector::Vector>::Scalar]> for $type {
            #[inline]
            fn as_mut(&mut self) -> &mut [<$type as crate::vector::Vector>::Scalar] {
                use crate::vector::Vector;
                self.as_slice_mut()
            }
        }

        impl core::ops::Deref for $type {
            type Target = [<Self as crate::vector::Vector>::Scalar];
            #[inline]
            fn deref(&self) -> &Self::Target {
                self.as_slice()
            }
        }

        impl core::ops::DerefMut for $type {
            #[inline]
            fn deref_mut(&mut self) -> &mut <Self as core::ops::Deref>::Target {
                self.as_slice_mut()
            }
        }
    }
}