#[derive(Clone, Copy, Debug, Default)]
struct C {
re: f32,
im: f32,
}
impl C {
#[inline]
fn mul(self, o: C) -> Self {
C { re: self.re * o.re - self.im * o.im, im: self.re * o.im + self.im * o.re }
}
#[inline]
fn add(self, o: C) -> Self {
C { re: self.re + o.re, im: self.im + o.im }
}
#[inline]
fn sub(self, o: C) -> Self {
C { re: self.re - o.re, im: self.im - o.im }
}
#[inline]
fn scale(self, k: f32) -> Self {
C { re: self.re * k, im: self.im * k }
}
#[inline]
fn dot(self, o: C) -> f32 {
self.re * o.re + self.im * o.im
}
#[inline]
fn polar(mag: f32, ang: f32) -> Self {
C { re: mag * ang.cos(), im: mag * ang.sin() }
}
#[inline]
fn power(self) -> f32 {
self.re * self.re + self.im * self.im
}
#[inline]
fn phase(self) -> f32 {
self.im.atan2(self.re)
}
}
#[derive(Clone, Debug, Default)]
pub struct Spectrum {
pub periods: Vec<u16>,
pub power: Vec<f32>,
pub phase: Vec<f32>,
pub group_delay: Vec<f32>,
}
impl Spectrum {
#[must_use]
pub fn dominant(&self) -> Option<u16> {
let (i, p) = self
.power
.iter()
.enumerate()
.max_by(|a, b| a.1.partial_cmp(b.1).unwrap_or(std::cmp::Ordering::Equal))?;
(*p > 0.0).then(|| self.periods[i])
}
#[must_use]
pub fn power_at(&self, period: u16) -> f32 {
self.periods
.iter()
.position(|&p| p == period)
.map_or(0.0, |i| self.power[i])
}
#[must_use]
pub fn phase_at(&self, period: u16) -> f32 {
self.periods
.iter()
.position(|&p| p == period)
.map_or(0.0, |i| self.phase[i])
}
#[must_use]
pub fn group_delay_at(&self, period: u16) -> f32 {
self.periods
.iter()
.position(|&p| p == period)
.map_or(0.0, |i| self.group_delay[i])
}
}
pub const DEFAULT_R: f32 = 0.98;
#[must_use]
pub fn default_periods(max: u16) -> Vec<u16> {
(2..=max.max(2)).collect()
}
fn block_len(r: f32) -> usize {
let decay = -r.clamp(f32::EPSILON, 1.0 - f32::EPSILON).ln();
((4.6 / decay) as usize).clamp(16, 4096)
}
#[must_use]
pub fn analyze_symbols(symbols: &[u32], alphabet: usize, periods: &[u16], r: f32) -> Spectrum {
let np = periods.len();
if np == 0 || alphabet == 0 {
return Spectrum::default();
}
let thetas: Vec<f32> = periods
.iter()
.map(|&p| std::f32::consts::TAU / f32::from(p.max(1)))
.collect();
let w: Vec<C> = thetas.iter().map(|&t| C::polar(r, t)).collect();
let winv: Vec<C> = thetas.iter().map(|&t| C::polar(1.0 / r, -t)).collect();
let dc = 1.0 / alphabet as f32;
let block = block_len(r);
let wblock: Vec<C> = thetas.iter().map(|&t| C::polar(r.powi(block as i32), t * block as f32)).collect();
let mut acc = vec![C::default(); alphabet * np];
let mut phasor = vec![C { re: 1.0, im: 0.0 }; np];
let mut shared = vec![C::default(); np];
let mut off = 0usize;
let mut ramp = vec![C::default(); alphabet * np];
let mut shared2 = vec![C::default(); np];
for &s in symbols {
let c = s as usize;
if c >= alphabet {
continue;
}
if off == block {
for cls in 0..alphabet {
let base = cls * np;
for k in 0..np {
let flat = acc[base + k];
ramp[base + k] =
wblock[k].mul(ramp[base + k].sub(flat.scale(block as f32)));
acc[base + k] = flat.mul(wblock[k]);
}
}
phasor.fill(C { re: 1.0, im: 0.0 });
off = 0;
}
let base = c * np;
let o = off as f32;
for k in 0..np {
shared[k] = shared[k].mul(w[k]).add(C { re: dc, im: 0.0 });
shared2[k] = shared2[k].mul(w[k]).add(shared[k]);
acc[base + k] = acc[base + k].add(phasor[k]);
ramp[base + k] = ramp[base + k].add(phasor[k].scale(o));
phasor[k] = phasor[k].mul(winv[k]);
}
off += 1;
}
let live = off.saturating_sub(1) as f32;
let rot: Vec<C> = thetas
.iter()
.map(|&t| C::polar(r.powf(live), t * live))
.collect();
let mut state = vec![C::default(); alphabet * np];
let mut state_ramp = vec![C::default(); alphabet * np];
for cls in 0..alphabet {
let base = cls * np;
for k in 0..np {
state[base + k] = acc[base + k].mul(rot[k]).sub(shared[k]);
let ramped = acc[base + k].scale(live + 1.0).sub(ramp[base + k]);
state_ramp[base + k] = ramped.mul(rot[k]).sub(shared2[k]);
}
}
let gain = (1.0 - r).max(f32::EPSILON);
let n = (symbols.len().max(1)) as f32;
let scale = (gain * gain) / n;
let mut power = vec![0.0f32; np];
let mut phase = vec![0.0f32; np];
let mut group_delay = vec![0.0f32; np];
for k in 0..np {
let mut acc = 0.0f32;
let mut strongest = C::default();
let mut weighted = 0.0f32;
for c in 0..alphabet {
let z = state[c * np + k];
let e = z.power();
acc += e;
if e > strongest.power() {
strongest = z;
}
weighted += state_ramp[c * np + k].sub(z).dot(z);
}
power[k] = acc * scale;
phase[k] = strongest.phase();
group_delay[k] = if acc > f32::EPSILON { weighted / acc } else { 0.0 };
}
Spectrum { periods: periods.to_vec(), power, phase, group_delay }
}
#[must_use]
pub fn over_bytes(bytes: &[u8], max_period: u16) -> Spectrum {
let symbols: Vec<u32> = bytes.iter().map(|&b| crate::spectral::classify(b) as u32).collect();
analyze_symbols(&symbols, crate::spectral::N_CLASSES, &default_periods(max_period), DEFAULT_R)
}
#[must_use]
pub fn over_byte_values(bytes: &[u8], max_period: u16) -> Spectrum {
let symbols: Vec<u32> = bytes.iter().map(|&b| u32::from(b)).collect();
analyze_symbols(&symbols, 256, &default_periods(max_period), DEFAULT_R)
}
#[must_use]
pub fn over_tokens(toks: &[crate::token::Token], max_period: u16) -> Spectrum {
let symbols: Vec<u32> = toks
.iter()
.filter(|t| t.is_significant())
.map(|t| t.kind.code())
.collect();
let alphabet = symbols.iter().copied().max().map_or(1, |m| m as usize + 1);
analyze_symbols(&symbols, alphabet, &default_periods(max_period), DEFAULT_R)
}
#[must_use]
pub fn over_supertokens(units: &[crate::supertoken::SuperToken], max_period: u16) -> Spectrum {
let symbols: Vec<u32> = units.iter().map(|u| u.role.code()).collect();
let alphabet = symbols.iter().copied().max().map_or(1, |m| m as usize + 1);
analyze_symbols(&symbols, alphabet, &default_periods(max_period), DEFAULT_R)
}
#[derive(Clone, Debug)]
pub struct Bank {
alphabet: usize,
poles: Vec<C>,
dc: f32,
z: Vec<C>,
z2: Vec<C>,
}
impl Bank {
#[must_use]
pub fn new(alphabet: usize, periods: &[u16], r: f32) -> Self {
let poles: Vec<C> = periods
.iter()
.map(|&p| C::polar(r, std::f32::consts::TAU / f32::from(p.max(1))))
.collect();
let states = alphabet * poles.len();
Bank {
alphabet,
dc: if alphabet == 0 { 0.0 } else { 1.0 / alphabet as f32 },
z: vec![C::default(); states],
z2: vec![C::default(); states],
poles,
}
}
pub fn push(&mut self, symbol: u32) {
let s = symbol as usize;
if s >= self.alphabet {
return;
}
let np = self.poles.len();
for cls in 0..self.alphabet {
let x = C { re: if cls == s { 1.0 - self.dc } else { -self.dc }, im: 0.0 };
let base = cls * np;
for (k, &pole) in self.poles.iter().enumerate() {
let i = base + k;
self.z[i] = self.z[i].mul(pole).add(x);
self.z2[i] = self.z2[i].mul(pole).add(self.z[i]);
}
}
}
pub fn read_into(&self, group_delay: &mut [f32], power: &mut [f32]) {
let np = self.poles.len();
assert_eq!(group_delay.len(), np, "one group delay a period");
assert_eq!(power.len(), np, "one power a period");
for (k, (gd, pw)) in group_delay.iter_mut().zip(power.iter_mut()).enumerate() {
let mut num = 0.0f32;
let mut den = 0.0f32;
for c in 0..self.alphabet {
let i = c * np + k;
num += self.z2[i].sub(self.z[i]).dot(self.z[i]);
den += self.z[i].power();
}
*pw = den;
*gd = if den > f32::EPSILON { num / den } else { 0.0 };
}
}
}
#[cfg(test)]
mod tests {
use super::*;
fn reference(symbols: &[u32], alphabet: usize, periods: &[u16], r: f32) -> Vec<f32> {
let np = periods.len();
let dc = 1.0 / alphabet as f32;
let mut st = vec![C::default(); alphabet * np];
for &s in symbols {
let c = s as usize;
if c >= alphabet {
continue;
}
for cls in 0..alphabet {
let x = if cls == c { 1.0 - dc } else { -dc };
for k in 0..np {
let theta = std::f32::consts::TAU / f32::from(periods[k].max(1));
let z = st[cls * np + k];
st[cls * np + k] = C {
re: r * (z.re * theta.cos() - z.im * theta.sin()) + x,
im: r * (z.re * theta.sin() + z.im * theta.cos()),
};
}
}
}
let gain = (1.0 - r).max(f32::EPSILON);
let scale = (gain * gain) / (symbols.len().max(1)) as f32;
(0..np)
.map(|k| (0..alphabet).map(|c| st[c * np + k].power()).sum::<f32>() * scale)
.collect()
}
fn b64(data: &[u8]) -> Vec<u8> {
const A: &[u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
let mut out = Vec::new();
for ch in data.chunks(3) {
let b = [ch[0], *ch.get(1).unwrap_or(&0), *ch.get(2).unwrap_or(&0)];
let n = (u32::from(b[0]) << 16) | (u32::from(b[1]) << 8) | u32::from(b[2]);
for k in 0..4 {
out.push(A[((n >> (18 - 6 * k)) & 63) as usize]);
}
}
out
}
fn peak_ratio(sp: &Spectrum, period: u16) -> f32 {
let mean = sp.power.iter().sum::<f32>() / sp.power.len() as f32;
if mean > 0.0 { sp.power_at(period) / mean } else { 0.0 }
}
fn fixed_width(rows: usize) -> Vec<u8> {
let mut s = String::new();
for i in 0..rows {
s.push_str(&format!("{:03},{:03},{:03}\n", i % 1000, (i * 7) % 1000, (i * 13) % 1000));
}
s.into_bytes()
}
fn ragged(rows: usize) -> Vec<u8> {
let mut s = String::new();
for i in 0..rows {
s.push_str(&format!("{},{},{}\n", i, i * 7919, (i * 13) % 100));
}
s.into_bytes()
}
#[test]
fn the_bank_reports_the_finest_repeating_unit_not_the_record() {
let sp = over_bytes(&fixed_width(200), 32);
assert_eq!(sp.dominant(), Some(4), "the field is four bytes and repeats most often");
assert!(sp.power_at(12) > 0.0, "the row period carries power as a multiple of it");
assert!(
sp.power_at(4) > sp.power_at(12),
"and less than the field: {} vs {}",
sp.power_at(12),
sp.power_at(4)
);
}
#[test]
fn the_token_grain_finds_the_row_period_a_ragged_table_hides_from_bytes() {
let input = ragged(200);
let toks = crate::lexer::lex(&input);
let tok_sp = over_tokens(&toks, 32);
assert_eq!(tok_sp.dominant(), Some(5), "five tokens per row, width-independent");
let byte_sp = over_bytes(&input, 32);
assert_ne!(byte_sp.dominant(), Some(5), "bytes cannot see the token period");
}
fn reference_group_delay(
symbols: &[u32],
alphabet: usize,
periods: &[u16],
r: f32,
) -> Vec<f32> {
let np = periods.len();
let dc = 1.0 / alphabet as f32;
let mut z = vec![C::default(); alphabet * np];
let mut z2 = vec![C::default(); alphabet * np];
for &s in symbols {
let c = s as usize;
if c >= alphabet {
continue;
}
for cls in 0..alphabet {
let x = if cls == c { 1.0 - dc } else { -dc };
for (k, &period) in periods.iter().enumerate() {
let theta = std::f32::consts::TAU / f32::from(period.max(1));
let a = C::polar(r, theta);
let i = cls * np + k;
z[i] = z[i].mul(a).add(C { re: x, im: 0.0 });
z2[i] = z2[i].mul(a).add(z[i]);
}
}
}
(0..np)
.map(|k| {
let mut num = 0.0f32;
let mut den = 0.0f32;
for c in 0..alphabet {
let i = c * np + k;
num += z2[i].sub(z[i]).dot(z[i]);
den += z[i].power();
}
if den > f32::EPSILON { num / den } else { 0.0 }
})
.collect()
}
#[test]
fn the_folded_ramp_reproduces_the_group_delay_definition() {
let periods = [3u16, 4, 5, 8, 12];
let r = 0.9;
let input = fixed_width(120);
let symbols: Vec<u32> =
input.iter().map(|&b| crate::spectral::classify(b) as u32).collect();
assert!(
symbols.len() > 3 * block_len(r),
"input of {} must span several blocks of {}",
symbols.len(),
block_len(r)
);
let got = analyze_symbols(&symbols, crate::spectral::N_CLASSES, &periods, r);
let want = reference_group_delay(&symbols, crate::spectral::N_CLASSES, &periods, r);
for (k, &p) in periods.iter().enumerate() {
let tol = 0.02 * want[k].abs().max(1.0);
assert!(
(got.group_delay[k] - want[k]).abs() <= tol,
"period {p}: folded {} against direct {}",
got.group_delay[k],
want[k]
);
}
}
#[test]
fn a_bank_read_at_the_end_is_the_whole_stream_reading() {
let periods = [3u16, 4, 5, 8, 12];
let r = 0.9;
let input = fixed_width(120);
let symbols: Vec<u32> =
input.iter().map(|&b| crate::spectral::classify(b) as u32).collect();
let mut bank = Bank::new(crate::spectral::N_CLASSES, &periods, r);
for &s in &symbols {
bank.push(s);
}
let mut gd = vec![0.0f32; periods.len()];
let mut pw = vec![0.0f32; periods.len()];
bank.read_into(&mut gd, &mut pw);
let whole = analyze_symbols(&symbols, crate::spectral::N_CLASSES, &periods, r);
let scale = (1.0 - r) * (1.0 - r) / symbols.len() as f32;
for (k, &p) in periods.iter().enumerate() {
let gd_tol = 0.02 * whole.group_delay[k].abs().max(1.0);
assert!(
(gd[k] - whole.group_delay[k]).abs() <= gd_tol,
"period {p}: bank group delay {} against the fold's {}",
gd[k],
whole.group_delay[k]
);
let pw_tol = 0.02 * whole.power[k].abs().max(f32::EPSILON);
assert!(
(pw[k] * scale - whole.power[k]).abs() <= pw_tol,
"period {p}: bank power {} against the fold's {}",
pw[k] * scale,
whole.power[k]
);
}
}
#[test]
fn every_band_dividing_the_row_carries_power_and_the_peak_is_the_field() {
let sp = over_bytes(&fixed_width(200), 32);
assert_eq!(sp.dominant(), Some(4), "the loudest band is the field");
for divisor in [2u16, 3, 4, 6, 12] {
assert!(sp.power_at(divisor) > 0.0, "the row excites period {divisor}");
}
let least_divisor =
[2u16, 3, 4, 6, 12].iter().map(|&d| sp.power_at(d)).fold(f32::MAX, f32::min);
for stranger in [5u16, 7, 11] {
assert!(
sp.power_at(stranger) < least_divisor,
"period {stranger} divides nothing and must read under the divisors"
);
}
}
#[test]
fn phase_advances_through_the_cycle() {
let full = fixed_width(20);
let a = over_bytes(&full[..120], 32).phase_at(12);
let b = over_bytes(&full[..126], 32).phase_at(12);
let c = over_bytes(&full[..132], 32).phase_at(12);
assert!((a - b).abs() > 0.1, "half a row apart, the phase differs");
let wrapped = (a - c).abs().min(std::f32::consts::TAU - (a - c).abs());
assert!(wrapped < 0.1, "a whole row apart, the phase returns: {a} vs {c}");
}
#[test]
fn an_aperiodic_stream_has_no_dominant_peak() {
let prose = b"the quick brown fox jumps over the lazy dog and then the dog looks up";
let sp = over_bytes(prose, 32);
let max = sp.power.iter().copied().fold(0.0f32, f32::max);
let mean = sp.power.iter().sum::<f32>() / sp.power.len() as f32;
assert!(max < mean * 6.0, "no sharp peak in aperiodic text: {max} vs mean {mean}");
}
#[test]
fn the_supertoken_grain_reads_a_repeating_block() {
let src = "a = 1;\nb = 2;\nc = 3;\nd = 4;\ne = 5;\nf = 6;\n";
let toks = crate::lexer::lex(src.as_bytes());
let units = crate::supertoken::supertokens_from(&toks, src.as_bytes());
let sp = over_supertokens(&units, 8);
assert!(!sp.periods.is_empty());
assert!(sp.power.iter().any(|&p| p > 0.0), "the role stream carries power");
}
#[test]
fn an_out_of_alphabet_symbol_is_ignored_rather_than_folded() {
let inside = analyze_symbols(&[0, 1, 0, 1, 0, 1], 2, &[2, 3], DEFAULT_R);
let with_stray = analyze_symbols(&[0, 1, 0, 1, 0, 1, 9], 2, &[2, 3], DEFAULT_R);
assert!(with_stray.power_at(2) > 0.0);
assert!(
(inside.dominant() == with_stray.dominant()),
"a stray code does not move the dominant period"
);
}
#[test]
fn empty_and_degenerate_inputs_are_safe() {
assert!(analyze_symbols(&[], 4, &[2, 3], DEFAULT_R).dominant().is_none());
assert!(analyze_symbols(&[0, 1], 0, &[2], DEFAULT_R).periods.is_empty());
assert!(analyze_symbols(&[0, 1], 4, &[], DEFAULT_R).periods.is_empty());
assert_eq!(over_bytes(b"", 16).dominant(), None);
}
#[test]
fn the_bank_agrees_with_the_autocorrelation_on_a_byte_period() {
let src = "abc123".repeat(60).into_bytes();
let (ac_period, ac_strength) = crate::spectral::dominant_period(&src, 32);
assert_eq!(ac_period, 6, "autocorrelation finds the period");
assert!(ac_strength > 0.0);
assert_eq!(over_bytes(&src, 32).dominant(), Some(6), "and so does the bank");
}
#[test]
fn a_harmonic_can_outweigh_the_fundamental() {
let src = "a1,bc2".repeat(60).into_bytes();
assert_eq!(over_bytes(&src, 32).dominant(), Some(2), "the harmonic is louder");
assert!(over_bytes(&src, 32).power_at(6) > 0.0, "the fundamental is still present");
assert_eq!(crate::spectral::dominant_period(&src, 32).0, 6);
}
#[test]
fn the_split_accumulator_matches_the_direct_definition() {
let periods = [3u16, 4, 7, 12, 31];
let symbols: Vec<u32> =
(0..4000u32).map(|i| (i.wrapping_mul(2_654_435_761) >> 27) % 5).collect();
assert!(symbols.len() > 4 * block_len(DEFAULT_R), "several blocks are folded");
let got = analyze_symbols(&symbols, 5, &periods, DEFAULT_R).power;
let want = reference(&symbols, 5, &periods, DEFAULT_R);
for (k, (&g, &w)) in got.iter().zip(want.iter()).enumerate() {
let tol = w.abs() * 1e-2 + 1e-9;
assert!((g - w).abs() <= tol, "period {}: {g} vs {w}", periods[k]);
}
}
#[test]
fn a_byte_value_alphabet_finds_the_base64_quantum_that_classes_discard() {
let prose: Vec<u8> = "it was the best of times it was the worst of times it was the age of wisdom it was the age of foolishness it was the epoch of belief "
.bytes()
.cycle()
.take(3000)
.collect();
let enc = b64(&prose);
let found = peak_ratio(&over_byte_values(&enc, 16), 4);
assert!(found > 2.0, "byte values find the quantum: {found}");
let by_class = peak_ratio(&over_bytes(&enc, 16), 4);
assert!(by_class < 1.5, "the five classes do not: {by_class}");
let unencoded = peak_ratio(&over_byte_values(&prose, 16), 4);
assert!(unencoded < 1.5, "and there is no quantum before encoding: {unencoded}");
let noise: Vec<u8> =
(0..3000u32).map(|i| (i.wrapping_mul(2_654_435_761) >> 13) as u8).collect();
let random_payload = peak_ratio(&over_byte_values(&b64(&noise), 16), 4);
assert!(random_payload < 1.5, "a random payload hides it: {random_payload}");
}
}