extern crate alloc;
use crate::math;
pub const EPS: f32 = 1e-6;
pub const SINKHORN_ITERS: usize = 20;
#[inline]
pub fn rms_unit(x: &mut [f32]) {
let mean_sq = x.iter().map(|v| v * v).sum::<f32>() / x.len() as f32;
let inv = 1.0 / math::sqrt(mean_sq + EPS);
for v in x.iter_mut() {
*v *= inv;
}
}
#[inline]
pub fn rms_unit_to(x: &[f32], out: &mut [f32]) {
debug_assert_eq!(x.len(), out.len());
let mean_sq = x.iter().map(|v| v * v).sum::<f32>() / x.len() as f32;
let inv = 1.0 / math::sqrt(mean_sq + EPS);
for (o, &v) in out.iter_mut().zip(x.iter()) {
*o = v * inv;
}
}
pub fn sinkhorn(m: &mut [f32], n: usize) {
debug_assert_eq!(m.len(), n * n);
for _ in 0..SINKHORN_ITERS {
for i in 0..n {
let row = &mut m[i * n..(i + 1) * n];
let lse = logsumexp(row);
for v in row.iter_mut() {
*v -= lse;
}
}
for j in 0..n {
let mut max = f32::NEG_INFINITY;
for i in 0..n {
max = max.max(m[i * n + j]);
}
let mut sum = 0.0f32;
for i in 0..n {
sum += math::exp(m[i * n + j] - max);
}
let lse = max + math::ln(sum);
for i in 0..n {
m[i * n + j] -= lse;
}
}
}
for v in m.iter_mut() {
*v = math::exp(*v);
}
}
#[inline]
fn logsumexp(x: &[f32]) -> f32 {
let max = x.iter().copied().fold(f32::NEG_INFINITY, f32::max);
if !max.is_finite() {
return max;
}
let sum: f32 = x.iter().map(|&v| math::exp(v - max)).sum();
max + math::ln(sum)
}