use core::arch::x86_64::*;
#[target_feature(enable = "avx512f,avx512vl")]
pub unsafe fn gated_activation_and_accumulate_block_avx512(
head_input: &mut [f32],
block: &mut [f32],
ch: usize,
) {
let num_frames = head_input.len() / ch;
for f in 0..num_frames {
let block_offset = f * 2 * ch;
let head_offset = f * ch;
let mut c = 0;
while c + 16 <= ch {
let z1 = _mm512_loadu_ps(block.as_ptr().add(block_offset + c));
let z2 = _mm512_loadu_ps(block.as_ptr().add(block_offset + ch + c));
let (tanh_z1, sig_z2) =
crate::math::activations::simd_tanh_sigmoid_dual_poly_avx512(z1, z2);
let activated = _mm512_mul_ps(tanh_z1, sig_z2);
_mm512_storeu_ps(block.as_mut_ptr().add(block_offset + c), activated);
let vh = _mm512_loadu_ps(head_input.as_ptr().add(head_offset + c));
_mm512_storeu_ps(
head_input.as_mut_ptr().add(head_offset + c),
_mm512_add_ps(vh, activated),
);
c += 16;
}
while c < ch {
let z1 = block[block_offset + c];
let z2 = block[block_offset + ch + c];
let activated = z1.tanh() * (1.0 / (1.0 + (-z2).exp()));
block[block_offset + c] = activated;
let acc = head_input[head_offset + c] as f64 + activated as f64;
head_input[head_offset + c] = acc as f32;
c += 1;
}
}
}
#[target_feature(enable = "avx512f,avx512vl")]
pub unsafe fn gated_activation_and_overwrite_block_avx512(
head_input: &mut [f32],
block: &mut [f32],
ch: usize,
) {
let num_frames = head_input.len() / ch;
for f in 0..num_frames {
let block_offset = f * 2 * ch;
let head_offset = f * ch;
let mut c = 0;
while c + 16 <= ch {
let z1 = _mm512_loadu_ps(block.as_ptr().add(block_offset + c));
let z2 = _mm512_loadu_ps(block.as_ptr().add(block_offset + ch + c));
let (tanh_z1, sig_z2) =
crate::math::activations::simd_tanh_sigmoid_dual_poly_avx512(z1, z2);
let activated = _mm512_mul_ps(tanh_z1, sig_z2);
_mm512_storeu_ps(block.as_mut_ptr().add(block_offset + c), activated);
_mm512_storeu_ps(head_input.as_mut_ptr().add(head_offset + c), activated);
c += 16;
}
while c < ch {
let z1 = block[block_offset + c];
let z2 = block[block_offset + ch + c];
let activated = z1.tanh() * (1.0 / (1.0 + (-z2).exp()));
block[block_offset + c] = activated;
head_input[head_offset + c] = activated;
c += 1;
}
}
}
#[target_feature(enable = "avx512f,avx512vl")]
pub unsafe fn accumulate_head_avx512(dest: &mut [f32], src: &[f32]) {
let len = dest.len();
let mut i = 0;
while i + 16 <= len {
let vs = _mm512_loadu_ps(src.as_ptr().add(i));
let vd = _mm512_loadu_ps(dest.as_ptr().add(i));
_mm512_storeu_ps(dest.as_mut_ptr().add(i), _mm512_add_ps(vd, vs));
i += 16;
}
if i < len {
let mask = _cvtu32_mask16((1u32 << (len - i)) - 1);
let vs = _mm512_maskz_loadu_ps(mask, src.as_ptr().add(i));
let vd = _mm512_maskz_loadu_ps(mask, dest.as_ptr().add(i));
_mm512_mask_storeu_ps(dest.as_mut_ptr().add(i), mask, _mm512_add_ps(vd, vs));
}
}
#[target_feature(enable = "avx512f,avx512vl")]
pub unsafe fn tanh_and_accumulate_block_avx512(head_input: &mut [f32], block: &mut [f32]) {
let len = block.len();
let mut i = 0;
while i + 16 <= len {
let vb = _mm512_loadu_ps(block.as_ptr().add(i));
let vt = crate::math::activations::simd_tanh_poly_avx512(vb);
_mm512_storeu_ps(block.as_mut_ptr().add(i), vt);
let vh = _mm512_loadu_ps(head_input.as_ptr().add(i));
_mm512_storeu_ps(head_input.as_mut_ptr().add(i), _mm512_add_ps(vh, vt));
i += 16;
}
if i < len {
let mask = _cvtu32_mask16((1u32 << (len - i)) - 1);
let vb = _mm512_maskz_loadu_ps(mask, block.as_ptr().add(i));
let vt = crate::math::activations::simd_tanh_poly_avx512(vb);
_mm512_mask_storeu_ps(block.as_mut_ptr().add(i), mask, vt);
let vh = _mm512_maskz_loadu_ps(mask, head_input.as_ptr().add(i));
_mm512_mask_storeu_ps(head_input.as_mut_ptr().add(i), mask, _mm512_add_ps(vh, vt));
}
}
#[target_feature(enable = "avx512f,avx512vl")]
pub unsafe fn tanh_and_overwrite_block_avx512(head_input: &mut [f32], block: &mut [f32]) {
let len = block.len();
let mut i = 0;
while i + 16 <= len {
let vb = _mm512_loadu_ps(block.as_ptr().add(i));
let vt = crate::math::activations::simd_tanh_poly_avx512(vb);
_mm512_storeu_ps(block.as_mut_ptr().add(i), vt);
_mm512_storeu_ps(head_input.as_mut_ptr().add(i), vt);
i += 16;
}
if i < len {
let mask = _cvtu32_mask16((1u32 << (len - i)) - 1);
let vb = _mm512_maskz_loadu_ps(mask, block.as_ptr().add(i));
let vt = crate::math::activations::simd_tanh_poly_avx512(vb);
_mm512_mask_storeu_ps(block.as_mut_ptr().add(i), mask, vt);
_mm512_mask_storeu_ps(head_input.as_mut_ptr().add(i), mask, vt);
}
}
#[target_feature(enable = "avx512f,avx512vl")]
pub unsafe fn tanh_and_accumulate_with_seed_avx512(
head_input: &mut [f32],
block: &mut [f32],
seed: &[f32],
) {
let len = block.len();
let mut i = 0;
while i + 16 <= len {
let vb = _mm512_loadu_ps(block.as_ptr().add(i));
let vt = crate::math::activations::simd_tanh_poly_avx512(vb);
_mm512_storeu_ps(block.as_mut_ptr().add(i), vt);
let vs = _mm512_loadu_ps(seed.as_ptr().add(i));
_mm512_storeu_ps(head_input.as_mut_ptr().add(i), _mm512_add_ps(vs, vt));
i += 16;
}
if i < len {
let mask = _cvtu32_mask16((1u32 << (len - i)) - 1);
let vb = _mm512_maskz_loadu_ps(mask, block.as_ptr().add(i));
let vt = crate::math::activations::simd_tanh_poly_avx512(vb);
_mm512_mask_storeu_ps(block.as_mut_ptr().add(i), mask, vt);
let vs = _mm512_maskz_loadu_ps(mask, seed.as_ptr().add(i));
_mm512_mask_storeu_ps(head_input.as_mut_ptr().add(i), mask, _mm512_add_ps(vs, vt));
}
}