use crate::activation_simd_avx2;
use crate::activation_simd_avx512;
use core::arch::x86_64::*;
#[target_feature(enable = "avx2")]
pub unsafe fn hard_tanh_slice_avx2(data: &mut [f32]) {
let neg_one = _mm256_set1_ps(-1.0_f32);
let pos_one = _mm256_set1_ps(1.0_f32);
let mut i = 0;
let len = data.len();
unsafe {
activation_simd_avx2!(
i,
len,
{
let x1 = _mm256_loadu_ps(data.as_ptr().add(i));
let x2 = _mm256_loadu_ps(data.as_ptr().add(i + 8));
_mm256_storeu_ps(
data.as_mut_ptr().add(i),
_mm256_min_ps(pos_one, _mm256_max_ps(neg_one, x1)),
);
_mm256_storeu_ps(
data.as_mut_ptr().add(i + 8),
_mm256_min_ps(pos_one, _mm256_max_ps(neg_one, x2)),
);
},
{
let x = _mm256_loadu_ps(data.as_ptr().add(i));
_mm256_storeu_ps(
data.as_mut_ptr().add(i),
_mm256_min_ps(pos_one, _mm256_max_ps(neg_one, x)),
);
}
);
}
for x in data.iter_mut().skip(i) {
*x = x.clamp(-1.0, 1.0);
}
}
#[target_feature(enable = "avx512f,avx512vl")]
pub unsafe fn hard_tanh_slice_avx512(data: &mut [f32]) {
let neg_one = _mm512_set1_ps(-1.0_f32);
let pos_one = _mm512_set1_ps(1.0_f32);
let mut i = 0;
let len = data.len();
unsafe {
activation_simd_avx512!(i, len, {
let x = _mm512_loadu_ps(data.as_ptr().add(i));
_mm512_storeu_ps(
data.as_mut_ptr().add(i),
_mm512_min_ps(pos_one, _mm512_max_ps(neg_one, x)),
);
});
}
for x in data.iter_mut().skip(i) {
*x = x.clamp(-1.0, 1.0);
}
}
#[inline(always)]
pub fn hard_tanh(x: f32) -> f32 {
x.clamp(-1.0, 1.0)
}