#![allow(dead_code)]
#[allow(dead_code)]
#[derive(Debug, Clone, PartialEq)]
pub struct ExpressionRandomizerConfig {
pub channel_count: usize,
pub amplitude: f32,
pub sparsity: f32,
}
impl Default for ExpressionRandomizerConfig {
fn default() -> Self {
Self {
channel_count: 8,
amplitude: 0.6,
sparsity: 0.3,
}
}
}
fn pcg32(state: &mut u64) -> u32 {
*state = state
.wrapping_mul(6_364_136_223_846_793_005)
.wrapping_add(1_442_695_040_888_963_407);
let xor = ((*state >> 18) ^ *state) >> 27;
let rot = (*state >> 59) as u32;
((xor.wrapping_shr(rot)) | (xor.wrapping_shl(u64::BITS.wrapping_sub(rot)))) as u32
}
fn pcg_f32(state: &mut u64) -> f32 {
(pcg32(state) >> 8) as f32 / 16_777_216.0
}
#[allow(dead_code)]
pub fn sample_expression(seed: u64, cfg: &ExpressionRandomizerConfig) -> Vec<f32> {
let mut rng = seed ^ 0xDEAD_BEEF_CAFE_1234;
(0..cfg.channel_count)
.map(|_| {
let sparse_val = pcg_f32(&mut rng);
if sparse_val < cfg.sparsity {
0.0
} else {
let v = pcg_f32(&mut rng);
let signed = v * 2.0 - 1.0;
(signed * cfg.amplitude).clamp(-1.0, 1.0)
}
})
.collect()
}
#[allow(dead_code)]
pub fn sample_sparse_expression(seed: u64, cfg: &ExpressionRandomizerConfig) -> Vec<(usize, f32)> {
sample_expression(seed, cfg)
.into_iter()
.enumerate()
.filter(|(_, w)| w.abs() > 1e-6)
.collect()
}
#[allow(dead_code)]
pub fn blend_sampled(a: &[f32], b: &[f32], t: f32) -> Vec<f32> {
let t = t.clamp(0.0, 1.0);
let inv = 1.0 - t;
a.iter()
.zip(b.iter())
.map(|(x, y)| x * inv + y * t)
.collect()
}
#[allow(dead_code)]
pub fn expression_energy(weights: &[f32]) -> f32 {
weights.iter().map(|w| w.abs()).sum()
}
#[allow(dead_code)]
pub fn dominant_channel(weights: &[f32]) -> Option<usize> {
weights
.iter()
.enumerate()
.max_by(|(_, a), (_, b)| {
a.abs()
.partial_cmp(&b.abs())
.unwrap_or(std::cmp::Ordering::Equal)
})
.map(|(i, _)| i)
}
#[allow(dead_code)]
pub fn normalize_expression(weights: &[f32]) -> Vec<f32> {
let l2: f32 = weights.iter().map(|w| w * w).sum::<f32>().sqrt();
if l2 < 1e-8 {
weights.to_vec()
} else {
weights.iter().map(|w| w / l2).collect()
}
}
#[allow(dead_code)]
pub fn expression_to_json(weights: &[f32]) -> String {
let inner: Vec<String> = weights.iter().map(|w| format!("{:.4}", w)).collect();
format!("[{}]", inner.join(","))
}
#[cfg(test)]
mod tests {
use super::*;
fn cfg() -> ExpressionRandomizerConfig {
ExpressionRandomizerConfig::default()
}
#[test]
fn sample_length_matches_config() {
let w = sample_expression(42, &cfg());
assert_eq!(w.len(), cfg().channel_count);
}
#[test]
fn deterministic_same_seed() {
let a = sample_expression(99, &cfg());
let b = sample_expression(99, &cfg());
assert_eq!(a, b);
}
#[test]
fn different_seeds_differ() {
let a = sample_expression(1, &cfg());
let b = sample_expression(2, &cfg());
assert_ne!(a, b);
}
#[test]
fn weights_in_range() {
let w = sample_expression(7, &cfg());
assert!(w.iter().all(|v| (-1.0..=1.0).contains(v)));
}
#[test]
fn sparse_expression_fewer_entries() {
let full = sample_expression(55, &cfg());
let sparse = sample_sparse_expression(55, &cfg());
assert!(sparse.len() <= full.len());
}
#[test]
fn blend_midpoint() {
let a = vec![0.0f32; 4];
let b = vec![1.0f32; 4];
let m = blend_sampled(&a, &b, 0.5);
assert!(m.iter().all(|v| (v - 0.5).abs() < 1e-6));
}
#[test]
fn energy_zero_for_zeros() {
let z = vec![0.0f32; 6];
assert!(expression_energy(&z) < 1e-8);
}
#[test]
fn dominant_channel_found() {
let mut w = vec![0.1f32, 0.9, 0.3];
w[1] = 0.9;
assert_eq!(dominant_channel(&w), Some(1));
}
#[test]
fn normalize_unit_length() {
let w = vec![3.0f32, 4.0];
let n = normalize_expression(&w);
let l2: f32 = n.iter().map(|v| v * v).sum::<f32>().sqrt();
assert!((l2 - 1.0).abs() < 1e-5);
}
#[test]
fn json_array_format() {
let w = vec![0.5f32, -0.5];
let j = expression_to_json(&w);
assert!(j.starts_with('[') && j.ends_with(']'));
}
}