carbon-simd 0.1.0

SIMD utilities written with Rust (fularuen project)
Documentation
use crate::*;
use core::arch::x86_64::*;

unsafe impl SimdNumElement for i8 {
    #[inline(always)]
    unsafe fn add(left: Self::Vector, right: Self::Vector) -> Self::Vector {
        unsafe { _mm256_add_epi8(left, right) }
    }

    #[inline(always)]
    unsafe fn sub(left: Self::Vector, right: Self::Vector) -> Self::Vector {
        unsafe { _mm256_sub_epi8(left, right) }
    }

    #[inline(always)]
    unsafe fn mul(left: Self::Vector, right: Self::Vector) -> Self::Vector {
        let mut left_buff = [0i8; Self::VECTOR_LEN];
        let mut right_buff = [0i8; Self::VECTOR_LEN];

        unsafe {
            Self::store(left_buff.as_mut_ptr(), left);
            Self::store(right_buff.as_mut_ptr(), right);

            for i in 0..Self::VECTOR_LEN {
                left_buff[i] *= right_buff[i];
            }

            Self::load(left_buff.as_ptr())
        }
    }

    #[inline(always)]
    unsafe fn div(left: Self::Vector, right: Self::Vector) -> Self::Vector {
        let mut left_buff = [0i8; Self::VECTOR_LEN];
        let mut right_buff = [0i8; Self::VECTOR_LEN];

        unsafe {
            Self::store(left_buff.as_mut_ptr(), left);
            Self::store(right_buff.as_mut_ptr(), right);

            for i in 0..Self::VECTOR_LEN {
                if right_buff[i] != 0 {
                    left_buff[i] /= right_buff[i];
                }
            }

            Self::load(left_buff.as_ptr())
        }
    }
}

unsafe impl SimdNumElement for u8 {
    #[inline(always)]
    unsafe fn add(left: Self::Vector, right: Self::Vector) -> Self::Vector {
        unsafe { _mm256_add_epi8(left, right) }
    }

    #[inline(always)]
    unsafe fn sub(left: Self::Vector, right: Self::Vector) -> Self::Vector {
        unsafe { _mm256_sub_epi8(left, right) }
    }

    #[inline(always)]
    unsafe fn mul(left: Self::Vector, right: Self::Vector) -> Self::Vector {
        let mut left_buff = [0u8; Self::VECTOR_LEN];
        let mut right_buff = [0u8; Self::VECTOR_LEN];

        unsafe {
            Self::store(left_buff.as_mut_ptr(), left);
            Self::store(right_buff.as_mut_ptr(), right);

            for i in 0..Self::VECTOR_LEN {
                left_buff[i] *= right_buff[i];
            }

            Self::load(left_buff.as_ptr())
        }
    }

    #[inline(always)]
    unsafe fn div(left: Self::Vector, right: Self::Vector) -> Self::Vector {
        let mut left_buff = [0u8; Self::VECTOR_LEN];
        let mut right_buff = [0u8; Self::VECTOR_LEN];

        unsafe {
            Self::store(left_buff.as_mut_ptr(), left);
            Self::store(right_buff.as_mut_ptr(), right);

            for i in 0..Self::VECTOR_LEN {
                if right_buff[i] != 0 {
                    left_buff[i] /= right_buff[i];
                }
            }

            Self::load(left_buff.as_ptr())
        }
    }
}

unsafe impl SimdNumElement for i16 {
    #[inline(always)]
    unsafe fn add(left: Self::Vector, right: Self::Vector) -> Self::Vector {
        unsafe { _mm256_add_epi16(left, right) }
    }

    #[inline(always)]
    unsafe fn sub(left: Self::Vector, right: Self::Vector) -> Self::Vector {
        unsafe { _mm256_sub_epi16(left, right) }
    }

    #[inline(always)]
    unsafe fn mul(left: Self::Vector, right: Self::Vector) -> Self::Vector {
        unsafe { _mm256_mullo_epi16(left, right) }
    }

    #[inline(always)]
    unsafe fn div(left: Self::Vector, right: Self::Vector) -> Self::Vector {
        let mut left_buff = [0i16; Self::VECTOR_LEN];
        let mut right_buff = [0i16; Self::VECTOR_LEN];

        unsafe {
            Self::store(left_buff.as_mut_ptr(), left);
            Self::store(right_buff.as_mut_ptr(), right);

            for i in 0..Self::VECTOR_LEN {
                if right_buff[i] != 0 {
                    left_buff[i] /= right_buff[i];
                }
            }

            Self::load(left_buff.as_ptr())
        }
    }
}

unsafe impl SimdNumElement for u16 {
    #[inline(always)]
    unsafe fn add(left: Self::Vector, right: Self::Vector) -> Self::Vector {
        unsafe { _mm256_add_epi16(left, right) }
    }

    #[inline(always)]
    unsafe fn sub(left: Self::Vector, right: Self::Vector) -> Self::Vector {
        unsafe { _mm256_sub_epi16(left, right) }
    }

    #[inline(always)]
    unsafe fn mul(left: Self::Vector, right: Self::Vector) -> Self::Vector {
        unsafe { _mm256_mullo_epi16(left, right) }
    }

    #[inline(always)]
    unsafe fn div(left: Self::Vector, right: Self::Vector) -> Self::Vector {
        let mut left_buff = [0u16; Self::VECTOR_LEN];
        let mut right_buff = [0u16; Self::VECTOR_LEN];

        unsafe {
            Self::store(left_buff.as_mut_ptr(), left);
            Self::store(right_buff.as_mut_ptr(), right);

            for i in 0..Self::VECTOR_LEN {
                if right_buff[i] != 0 {
                    left_buff[i] /= right_buff[i];
                }
            }

            Self::load(left_buff.as_ptr())
        }
    }
}

unsafe impl SimdNumElement for i32 {
    #[inline(always)]
    unsafe fn add(left: Self::Vector, right: Self::Vector) -> Self::Vector {
        unsafe { _mm256_add_epi32(left, right) }
    }

    #[inline(always)]
    unsafe fn sub(left: Self::Vector, right: Self::Vector) -> Self::Vector {
        unsafe { _mm256_sub_epi32(left, right) }
    }

    #[inline(always)]
    unsafe fn mul(left: Self::Vector, right: Self::Vector) -> Self::Vector {
        unsafe { _mm256_mullo_epi32(left, right) }
    }

    #[inline(always)]
    unsafe fn div(left: Self::Vector, right: Self::Vector) -> Self::Vector {
        let mut left_buff = [0i32; Self::VECTOR_LEN];
        let mut right_buff = [0i32; Self::VECTOR_LEN];

        unsafe {
            Self::store(left_buff.as_mut_ptr(), left);
            Self::store(right_buff.as_mut_ptr(), right);

            for i in 0..Self::VECTOR_LEN {
                if right_buff[i] != 0 {
                    left_buff[i] /= right_buff[i];
                }
            }

            Self::load(left_buff.as_ptr())
        }
    }
}

unsafe impl SimdNumElement for u32 {
    #[inline(always)]
    unsafe fn add(left: Self::Vector, right: Self::Vector) -> Self::Vector {
        unsafe { _mm256_add_epi32(left, right) }
    }

    #[inline(always)]
    unsafe fn sub(left: Self::Vector, right: Self::Vector) -> Self::Vector {
        unsafe { _mm256_sub_epi32(left, right) }
    }

    #[inline(always)]
    unsafe fn mul(left: Self::Vector, right: Self::Vector) -> Self::Vector {
        unsafe { _mm256_mullo_epi32(left, right) }
    }

    #[inline(always)]
    unsafe fn div(left: Self::Vector, right: Self::Vector) -> Self::Vector {
        let mut left_buff = [0u32; Self::VECTOR_LEN];
        let mut right_buff = [0u32; Self::VECTOR_LEN];

        unsafe {
            Self::store(left_buff.as_mut_ptr(), left);
            Self::store(right_buff.as_mut_ptr(), right);

            for i in 0..Self::VECTOR_LEN {
                if right_buff[i] != 0 {
                    left_buff[i] /= right_buff[i];
                }
            }

            Self::load(left_buff.as_ptr())
        }
    }
}

unsafe impl SimdNumElement for i64 {
    #[inline(always)]
    unsafe fn add(left: Self::Vector, right: Self::Vector) -> Self::Vector {
        unsafe { _mm256_add_epi64(left, right) }
    }

    #[inline(always)]
    unsafe fn sub(left: Self::Vector, right: Self::Vector) -> Self::Vector {
        unsafe { _mm256_sub_epi64(left, right) }
    }

    #[inline(always)]
    unsafe fn mul(left: Self::Vector, right: Self::Vector) -> Self::Vector {
        let mut left_buff = [0i64; 4];
        let mut right_buff = [0i64; 4];

        unsafe {
            Self::store(left_buff.as_mut_ptr(), left);
            Self::store(right_buff.as_mut_ptr(), right);

            for i in 0..4 {
                left_buff[i] *= right_buff[i];
            }

            Self::load(left_buff.as_ptr())
        }
    }

    #[inline(always)]
    unsafe fn div(left: Self::Vector, right: Self::Vector) -> Self::Vector {
        let mut left_buff = [0i64; Self::VECTOR_LEN];
        let mut right_buff = [0i64; Self::VECTOR_LEN];

        unsafe {
            Self::store(left_buff.as_mut_ptr(), left);
            Self::store(right_buff.as_mut_ptr(), right);

            for i in 0..Self::VECTOR_LEN {
                if right_buff[i] != 0 {
                    left_buff[i] /= right_buff[i];
                }
            }

            Self::load(left_buff.as_ptr())
        }
    }
}

unsafe impl SimdNumElement for u64 {
    #[inline(always)]
    unsafe fn add(left: Self::Vector, right: Self::Vector) -> Self::Vector {
        unsafe { _mm256_add_epi64(left, right) }
    }

    #[inline(always)]
    unsafe fn sub(left: Self::Vector, right: Self::Vector) -> Self::Vector {
        unsafe { _mm256_sub_epi64(left, right) }
    }

    #[inline(always)]
    unsafe fn mul(left: Self::Vector, right: Self::Vector) -> Self::Vector {
        let mut left_buff = [0u64; 4];
        let mut right_buff = [0u64; 4];

        unsafe {
            Self::store(left_buff.as_mut_ptr(), left);
            Self::store(right_buff.as_mut_ptr(), right);

            for i in 0..4 {
                left_buff[i] *= right_buff[i];
            }

            Self::load(left_buff.as_ptr())
        }
    }

    #[inline(always)]
    unsafe fn div(left: Self::Vector, right: Self::Vector) -> Self::Vector {
        let mut left_buff = [0u64; Self::VECTOR_LEN];
        let mut right_buff = [0u64; Self::VECTOR_LEN];

        unsafe {
            Self::store(left_buff.as_mut_ptr(), left);
            Self::store(right_buff.as_mut_ptr(), right);

            for i in 0..Self::VECTOR_LEN {
                if right_buff[i] != 0 {
                    left_buff[i] /= right_buff[i];
                }
            }

            Self::load(left_buff.as_ptr())
        }
    }
}

unsafe impl SimdNumElement for f32 {
    #[inline(always)]
    unsafe fn add(left: Self::Vector, right: Self::Vector) -> Self::Vector {
        unsafe { _mm256_add_ps(left, right) }
    }

    #[inline(always)]
    unsafe fn sub(left: Self::Vector, right: Self::Vector) -> Self::Vector {
        unsafe { _mm256_sub_ps(left, right) }
    }

    #[inline(always)]
    unsafe fn mul(left: Self::Vector, right: Self::Vector) -> Self::Vector {
        unsafe { _mm256_mul_ps(left, right) }
    }

    #[inline(always)]
    unsafe fn div(left: Self::Vector, right: Self::Vector) -> Self::Vector {
        unsafe { _mm256_div_ps(left, right) }
    }

    #[inline(always)]
    unsafe fn fma(a: Self::Vector, b: Self::Vector, c: Self::Vector) -> Self::Vector {
        unsafe { _mm256_fmadd_ps(a, b, c) }
    }
}

unsafe impl SimdNumElement for f64 {
    #[inline(always)]
    unsafe fn add(left: Self::Vector, right: Self::Vector) -> Self::Vector {
        unsafe { _mm256_add_pd(left, right) }
    }

    #[inline(always)]
    unsafe fn sub(left: Self::Vector, right: Self::Vector) -> Self::Vector {
        unsafe { _mm256_sub_pd(left, right) }
    }

    #[inline(always)]
    unsafe fn mul(left: Self::Vector, right: Self::Vector) -> Self::Vector {
        unsafe { _mm256_mul_pd(left, right) }
    }

    #[inline(always)]
    unsafe fn div(left: Self::Vector, right: Self::Vector) -> Self::Vector {
        unsafe { _mm256_div_pd(left, right) }
    }

    #[inline(always)]
    unsafe fn fma(a: Self::Vector, b: Self::Vector, c: Self::Vector) -> Self::Vector {
        unsafe { _mm256_fmadd_pd(a, b, c) }
    }
}