use rand::{Rng, SeedableRng, rngs::StdRng};
fn standard_normal(rng: &mut StdRng) -> f32 {
let u1: f32 = {
let x: f32 = rng.random();
if x <= f32::MIN_POSITIVE {
f32::MIN_POSITIVE
} else {
x
}
};
let u2: f32 = rng.random();
let r = (-2.0_f32 * u1.ln()).sqrt();
let theta = 2.0_f32 * std::f32::consts::PI * u2;
r * theta.cos()
}
pub fn seeded_orthogonal(seed: u64, d_in: usize, d_out: usize, gain: f32) -> Vec<f32> {
let mut rng = StdRng::seed_from_u64(seed);
let (rows, cols, transposed) = if d_in >= d_out {
(d_in, d_out, false)
} else {
(d_out, d_in, true)
};
let mut cols_data: Vec<Vec<f32>> = Vec::with_capacity(cols);
for _ in 0..cols {
let mut col = Vec::with_capacity(rows);
for _ in 0..rows {
col.push(standard_normal(&mut rng));
}
cols_data.push(col);
}
let mut q: Vec<Vec<f32>> = Vec::with_capacity(cols);
for j in 0..cols {
let mut v = cols_data[j].clone();
for qi in q.iter() {
let dot: f32 = (0..rows).map(|r| v[r] * qi[r]).sum();
for r in 0..rows {
v[r] -= dot * qi[r];
}
}
let norm: f32 = v.iter().map(|x| x * x).sum::<f32>().sqrt();
let norm = if norm <= f32::MIN_POSITIVE { 1.0 } else { norm };
for slot in v.iter_mut() {
*slot /= norm;
}
if v[j] < 0.0 {
for slot in v.iter_mut() {
*slot = -*slot;
}
}
q.push(v);
}
let mut out = vec![0.0_f32; d_in * d_out];
for i in 0..d_in {
for j in 0..d_out {
let (r, c) = if transposed { (j, i) } else { (i, j) };
out[i * d_out + j] = gain * q[c][r];
}
}
out
}
pub fn seeded_kaiming_uniform(seed: u64, d_in: usize, d_out: usize, gain: f32) -> Vec<f32> {
let mut rng = StdRng::seed_from_u64(seed);
let fan_in = d_in.max(1) as f32;
let bound = gain * (3.0_f32 / fan_in).sqrt();
let mut out = vec![0.0_f32; d_in * d_out];
for slot in out.iter_mut() {
let u: f32 = rng.random();
*slot = (u * 2.0 - 1.0) * bound;
}
out
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn orthogonal_is_deterministic_in_seed() {
let a = seeded_orthogonal(42, 6, 4, 2.0_f32.sqrt());
let b = seeded_orthogonal(42, 6, 4, 2.0_f32.sqrt());
assert_eq!(a, b, "same seed must be bit-identical");
let c = seeded_orthogonal(43, 6, 4, 2.0_f32.sqrt());
assert_ne!(a, c, "different seed must differ");
assert_eq!(a.len(), 24);
}
#[test]
fn orthogonal_columns_are_orthonormal_tall() {
let d_in = 8;
let d_out = 3;
let gain = 1.0;
let w = seeded_orthogonal(7, d_in, d_out, gain);
for j in 0..d_out {
for k in 0..d_out {
let mut dot = 0.0_f32;
for r in 0..d_in {
dot += w[r * d_out + j] * w[r * d_out + k];
}
let expected = if j == k { 1.0 } else { 0.0 };
assert!(
(dot - expected).abs() < 1e-4,
"col {j}.col {k} = {dot}, expected {expected}"
);
}
}
}
#[test]
fn orthogonal_rows_are_orthonormal_wide() {
let d_in = 3;
let d_out = 8;
let gain = 1.0;
let w = seeded_orthogonal(11, d_in, d_out, gain);
for i in 0..d_in {
for k in 0..d_in {
let mut dot = 0.0_f32;
for c in 0..d_out {
dot += w[i * d_out + c] * w[k * d_out + c];
}
let expected = if i == k { 1.0 } else { 0.0 };
assert!(
(dot - expected).abs() < 1e-4,
"row {i}.row {k} = {dot}, expected {expected}"
);
}
}
}
#[test]
fn orthogonal_gain_scales() {
let w1 = seeded_orthogonal(5, 6, 4, 1.0);
let w2 = seeded_orthogonal(5, 6, 4, 3.0);
for (a, b) in w1.iter().zip(w2.iter()) {
assert!((b - a * 3.0).abs() < 1e-5, "gain should scale: {a} vs {b}");
}
}
#[test]
fn kaiming_is_deterministic_and_bounded() {
let d_in = 16;
let d_out = 8;
let gain = 1.0_f32 / 3.0_f32.sqrt();
let a = seeded_kaiming_uniform(99, d_in, d_out, gain);
let b = seeded_kaiming_uniform(99, d_in, d_out, gain);
assert_eq!(a, b, "same seed must be bit-identical");
let c = seeded_kaiming_uniform(100, d_in, d_out, gain);
assert_ne!(a, c, "different seed must differ");
let bound = gain * (3.0_f32 / d_in as f32).sqrt();
for &x in &a {
assert!(x.abs() <= bound + 1e-6, "{x} exceeds bound {bound}");
}
assert_eq!(a.len(), d_in * d_out);
}
}