Documentation
use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Rem, RemAssign, Sub, SubAssign};

macro_rules! create_ops {
    ($($Trait:ident $func:ident),*) => ($(
        #[inline]
        pub fn $func<'out, T>(out: &'out mut [T; 4], a: &[T; 4], b: &[T; 4]) -> &'out mut [T; 4]
        where
            for<'a, 'b> &'a T: $Trait<&'b T, Output = T>,
        {
            out[0] = $Trait::$func(&a[0], &b[0]);
            out[1] = $Trait::$func(&a[1], &b[1]);
            out[2] = $Trait::$func(&a[2], &b[2]);
            out[3] = $Trait::$func(&a[3], &b[3]);
            out
        }
    )*);
}
create_ops!(Add add, Div div, Mul mul, Rem rem, Sub sub);

macro_rules! create_ops_mut {
    ($($Trait:ident $func:ident $name:ident),*) => ($(
        #[inline]
        pub fn $name<'out, T>(a: &'out mut [T; 4], b: &[T; 4]) -> &'out mut [T; 4]
        where
            for<'a> T: $Trait<&'a T>,
        {
            $Trait::$func(&mut a[0], &b[0]);
            $Trait::$func(&mut a[1], &b[1]);
            $Trait::$func(&mut a[2], &b[2]);
            $Trait::$func(&mut a[3], &b[3]);
            a
        }
    )*);
}
create_ops_mut!(
    AddAssign add_assign add_mut, 
    DivAssign div_assign div_mut, 
    MulAssign mul_assign mul_mut, 
    RemAssign rem_assign rem_mut, 
    SubAssign sub_assign sub_mut
);

macro_rules! create_ops_scalar {
    ($($Trait:ident $func:ident $name:ident),*) => ($(
        #[inline]
        pub fn $name<'out, T>(out: &'out mut [T; 4], a: &[T; 4], s: &T) -> &'out mut [T; 4]
        where
            for<'a, 'b> &'a T: $Trait<&'b T, Output = T>,
        {
            out[0] = $Trait::$func(&a[0], s);
            out[1] = $Trait::$func(&a[1], s);
            out[2] = $Trait::$func(&a[2], s);
            out[3] = $Trait::$func(&a[3], s);
            out
        }
    )*);
}
create_ops_scalar!(Add add sadd, Div div sdiv, Mul mul smul, Rem rem srem, Sub sub ssub);

macro_rules! create_ops_scalar_mut {
    ($($Trait:ident $func:ident $name:ident),*) => ($(
        #[inline]
        pub fn $name<'out, T>(out: &'out mut [T; 4], s: &T) -> &'out mut [T; 4]
        where
            for<'a> T: $Trait<&'a T>,
        {
            $Trait::$func(&mut out[0], s);
            $Trait::$func(&mut out[1], s);
            $Trait::$func(&mut out[2], s);
            $Trait::$func(&mut out[3], s);
            out
        }
    )*);
}
create_ops_scalar_mut!(
    AddAssign add_assign sadd_mut, 
    DivAssign div_assign sdiv_mut, 
    MulAssign mul_assign smul_mut, 
    RemAssign rem_assign srem_mut, 
    SubAssign sub_assign ssub_mut
);