#![expect(
clippy::redundant_pub_crate,
reason = "Keep graph-only activation helpers crate scoped while satisfying unreachable_pub."
)]
#[cfg(all(
feature = "experimental-neon",
target_arch = "aarch64",
target_os = "windows",
target_env = "msvc",
target_feature = "neon"
))]
use fearless_simd::{Neon, f32x4, prelude::*, u32x4};
use crate::{Result, invalid};
pub(super) fn vector_exp(value: f32) -> f32 {
let z = value.mul_add(f32::from_bits(0x3fb8_aa3b), 12_582_912.0);
let n = z - 12_582_912.0;
let remainder = (-n).mul_add(f32::from_bits(0x3f31_7200), value);
let remainder = (-n).mul_add(f32::from_bits(0x35bf_be8e), remainder);
let exponent = z.to_bits().wrapping_shl(23);
let k = f32::from_bits(exponent.wrapping_add(1.0_f32.to_bits()));
let square = remainder * remainder;
let inner = f32::from_bits(0x3c07_2010)
.mul_add(remainder, f32::from_bits(0x3d2b_9f17))
.mul_add(
square,
f32::from_bits(0x3e2a_af33).mul_add(remainder, f32::from_bits(0x3eff_fedb)),
);
let polynomial = inner.mul_add(square, f32::from_bits(0x3f7f_fff6) * remainder);
if n.abs() > 126.0 {
let shift = if n <= 0.0 { 0x8200_0000_u32 } else { 0 };
let s1 = f32::from_bits(shift.wrapping_add(0x7f00_0000));
if n.abs() > 192.0 {
s1 * s1
} else {
let s2 = f32::from_bits(exponent.wrapping_sub(shift));
s2.mul_add(polynomial, s2) * s1
}
} else {
polynomial.mul_add(k, k)
}
}
#[cfg(all(
feature = "experimental-neon",
target_arch = "aarch64",
target_os = "windows",
target_env = "msvc",
target_feature = "neon"
))]
#[inline]
pub(super) fn vector_exp_x4(neon: Neon, value: f32x4<Neon>) -> f32x4<Neon> {
let magic = f32x4::splat(neon, 12_582_912.0);
let z = value.mul_add(f32x4::splat(neon, f32::from_bits(0x3fb8_aa3b)), magic);
let n = z - magic;
let neg_n = -n;
let remainder = neg_n.mul_add(f32x4::splat(neon, f32::from_bits(0x3f31_7200)), value);
let remainder = neg_n.mul_add(f32x4::splat(neon, f32::from_bits(0x35bf_be8e)), remainder);
let exponent = z.bitcast::<u32x4<Neon>>() << 23;
let k = (exponent + u32x4::splat(neon, 1.0_f32.to_bits())).bitcast::<f32x4<Neon>>();
let square = remainder * remainder;
let inner = f32x4::splat(neon, f32::from_bits(0x3c07_2010))
.mul_add(remainder, f32x4::splat(neon, f32::from_bits(0x3d2b_9f17)))
.mul_add(
square,
f32x4::splat(neon, f32::from_bits(0x3e2a_af33))
.mul_add(remainder, f32x4::splat(neon, f32::from_bits(0x3eff_fedb))),
);
let polynomial = inner.mul_add(
square,
f32x4::splat(neon, f32::from_bits(0x3f7f_fff6)) * remainder,
);
let abs_n = n.abs();
let gt_126 = abs_n.simd_gt(f32x4::splat(neon, 126.0));
if gt_126.any_true() {
let shift = n
.simd_le(f32x4::splat(neon, 0.0))
.select(u32x4::splat(neon, 0x8200_0000), u32x4::splat(neon, 0));
let s1 = (shift + u32x4::splat(neon, 0x7f00_0000)).bitcast::<f32x4<Neon>>();
let s2 = (exponent - shift).bitcast::<f32x4<Neon>>();
let scaled = abs_n
.simd_gt(f32x4::splat(neon, 192.0))
.select(s1 * s1, s2.mul_add(polynomial, s2) * s1);
gt_126.select(scaled, polynomial.mul_add(k, k))
} else {
polynomial.mul_add(k, k)
}
}
fn denominator(value: f32, vectorized: bool) -> f32 {
1.0 + if vectorized {
vector_exp(0.0 - value)
} else {
(-value).exp()
}
}
pub(crate) fn silu_in_place(values: &mut [f32]) {
#[cfg(all(
feature = "experimental-neon",
target_arch = "aarch64",
target_os = "windows",
target_env = "msvc",
target_feature = "neon"
))]
if let Some(neon) = fearless_simd::Level::baseline().as_neon() {
let zero = f32x4::splat(neon, 0.0);
let one = f32x4::splat(neon, 1.0);
let (chunks, tail) = values.as_chunks_mut::<4>();
for chunk in chunks {
let v = f32x4::from_slice(neon, chunk);
(v / (one + vector_exp_x4(neon, zero - v))).store_slice(chunk);
}
for value in tail {
*value /= denominator(*value, false);
}
return;
}
let vectorized = values.len() / 4 * 4;
for (index, value) in values.iter_mut().enumerate() {
*value /= denominator(*value, index < vectorized);
}
}
pub(crate) fn swiglu_in_place(gate: &[f32], up: &mut [f32]) -> Result<()> {
if gate.len() != up.len() {
return Err(invalid("pinned SwiGLU requires matching gate and up rows"));
}
#[cfg(all(
feature = "experimental-neon",
target_arch = "aarch64",
target_os = "windows",
target_env = "msvc",
target_feature = "neon"
))]
if let Some(neon) = fearless_simd::Level::baseline().as_neon() {
let zero = f32x4::splat(neon, 0.0);
let one = f32x4::splat(neon, 1.0);
let (gate_chunks, gate_tail) = gate.as_chunks::<4>();
let (up_chunks, up_tail) = up.as_chunks_mut::<4>();
for (g_chunk, u_chunk) in gate_chunks.iter().zip(up_chunks) {
let g = f32x4::from_slice(neon, g_chunk);
let u = f32x4::from_slice(neon, u_chunk);
((g * u) / (one + vector_exp_x4(neon, zero - g))).store_slice(u_chunk);
}
for (&gate, up) in gate_tail.iter().zip(up_tail) {
*up = (gate * *up) / denominator(gate, false);
}
return Ok(());
}
let vectorized = gate.len() / 4 * 4;
for (index, (&gate, up)) in gate.iter().zip(up).enumerate() {
*up = (gate * *up) / denominator(gate, index < vectorized);
}
Ok(())
}
pub(crate) fn swiglu_into(gate: &[f32], up: &[f32], output: &mut [f32]) -> Result<()> {
if gate.len() != up.len() || gate.len() != output.len() {
return Err(invalid(
"pinned SwiGLU requires matching input and output rows",
));
}
#[cfg(all(
feature = "experimental-neon",
target_arch = "aarch64",
target_os = "windows",
target_env = "msvc",
target_feature = "neon"
))]
if let Some(neon) = fearless_simd::Level::baseline().as_neon() {
let zero = f32x4::splat(neon, 0.0);
let one = f32x4::splat(neon, 1.0);
let (gate_chunks, gate_tail) = gate.as_chunks::<4>();
let (up_chunks, up_tail) = up.as_chunks::<4>();
let (out_chunks, out_tail) = output.as_chunks_mut::<4>();
for ((g_chunk, u_chunk), o_chunk) in gate_chunks.iter().zip(up_chunks).zip(out_chunks) {
let g = f32x4::from_slice(neon, g_chunk);
let u = f32x4::from_slice(neon, u_chunk);
((g * u) / (one + vector_exp_x4(neon, zero - g))).store_slice(o_chunk);
}
for ((&gate, &up), output) in gate_tail.iter().zip(up_tail).zip(out_tail) {
*output = (gate * up) / denominator(gate, false);
}
return Ok(());
}
let vectorized = gate.len() / 4 * 4;
for (index, ((&gate, &up), output)) in gate.iter().zip(up).zip(output).enumerate() {
*output = (gate * up) / denominator(gate, index < vectorized);
}
Ok(())
}
#[cfg(test)]
mod tests {
use serde::Deserialize;
use super::{silu_in_place, swiglu_in_place, swiglu_into};
#[derive(Deserialize)]
struct Capture {
runtime_commit: String,
ggml_cpu_sha256: String,
cases: Vec<Case>,
}
#[derive(Deserialize)]
struct Case {
name: String,
input_bits: Vec<u32>,
weight_bits: Vec<u32>,
silu_bits: Vec<u32>,
swiglu_bits: Vec<u32>,
}
fn assert_native(actual: &[f32], expected: &[u32], case: &str) {
assert_eq!(actual.len(), expected.len(), "{case}");
for (index, (&actual, &expected)) in actual.iter().zip(expected).enumerate() {
if f32::from_bits(expected).is_nan() {
assert!(actual.is_nan(), "{case}, element {index}");
} else {
assert_eq!(actual.to_bits(), expected, "{case}, element {index}");
}
}
}
#[test]
fn pinned_activations_match_native_random_tails_and_finite_edges() -> crate::Result<()> {
let capture: Capture = serde_json::from_str(include_str!(
"../../tests/fixtures/swift-activation-parity.json"
))?;
assert_eq!(
capture.runtime_commit,
"73bfe6cc485554822f80c473a3c0c4f25e80f41b"
);
assert_eq!(
capture.ggml_cpu_sha256,
"701b354a38b25e5c6dc57a1559f71cd26b2d0f8d69c1576a0e77a59a4273d2ab"
);
for case in capture.cases {
let gate = case
.input_bits
.into_iter()
.map(f32::from_bits)
.collect::<Vec<_>>();
let up = case
.weight_bits
.into_iter()
.map(f32::from_bits)
.collect::<Vec<_>>();
let mut unary = gate.clone();
silu_in_place(&mut unary);
assert_native(&unary, &case.silu_bits, &case.name);
let mut inplace = up.clone();
swiglu_in_place(&gate, &mut inplace)?;
assert_native(&inplace, &case.swiglu_bits, &case.name);
let mut output = vec![99.0; up.len()];
swiglu_into(&gate, &up, &mut output)?;
assert_native(&output, &case.swiglu_bits, &case.name);
}
Ok(())
}
#[test]
fn pinned_swiglu_rejects_mismatched_rows_before_mutation() {
let mut output = [99.0];
assert!(swiglu_in_place(&[], &mut output).is_err());
assert_eq!(output[0].to_bits(), 99.0_f32.to_bits());
assert!(swiglu_into(&[1.0], &[], &mut output).is_err());
assert_eq!(output[0].to_bits(), 99.0_f32.to_bits());
}
}