use crate::activation_simd_avx2;
use crate::activation_simd_avx512;
use core::arch::x86_64::*;
#[target_feature(enable = "avx2")]
pub unsafe fn simd_relu_avx2(x: __m256) -> __m256 {
_mm256_max_ps(_mm256_setzero_ps(), x)
}
#[target_feature(enable = "avx2")]
pub unsafe fn simd_relu_dual_avx2(x1: __m256, x2: __m256) -> (__m256, __m256) {
let zero = _mm256_setzero_ps();
(_mm256_max_ps(zero, x1), _mm256_max_ps(zero, x2))
}
#[target_feature(enable = "avx512f,avx512vl")]
pub unsafe fn simd_relu_avx512(x: __m512) -> __m512 {
_mm512_max_ps(_mm512_setzero_ps(), x)
}
#[target_feature(enable = "avx2")]
pub unsafe fn relu_slice_avx2(slice: &mut [f32]) {
let mut i = 0;
let len = slice.len();
let zero = _mm256_setzero_ps();
unsafe {
activation_simd_avx2!(
i,
len,
{
let x1 = _mm256_loadu_ps(slice.as_ptr().add(i));
let x2 = _mm256_loadu_ps(slice.as_ptr().add(i + 8));
_mm256_storeu_ps(slice.as_mut_ptr().add(i), _mm256_max_ps(zero, x1));
_mm256_storeu_ps(slice.as_mut_ptr().add(i + 8), _mm256_max_ps(zero, x2));
},
{
let x = _mm256_loadu_ps(slice.as_ptr().add(i));
_mm256_storeu_ps(slice.as_mut_ptr().add(i), _mm256_max_ps(zero, x));
}
);
}
for item in slice.iter_mut().skip(i) {
if *item < 0.0 {
*item = 0.0;
}
}
}
#[target_feature(enable = "avx512f,avx512vl")]
pub unsafe fn relu_slice_avx512(slice: &mut [f32]) {
let mut i = 0;
let len = slice.len();
let zero = _mm512_setzero_ps();
unsafe {
activation_simd_avx512!(i, len, {
let x = _mm512_loadu_ps(slice.as_ptr().add(i));
_mm512_storeu_ps(slice.as_mut_ptr().add(i), _mm512_max_ps(zero, x));
});
}
for item in slice.iter_mut().skip(i) {
if *item < 0.0 {
*item = 0.0;
}
}
}
#[inline(always)]
pub fn relu(x: f32) -> f32 {
if x < 0.0 { 0.0 } else { x }
}