fix(signal/cir): causal-delay-window rms spread — resolves last ADR-134 P2 cir test

Found the principled fix for the rms-delay-spread inflation (superseding my
prior 'needs ISTA work' note): the spurious ~15-20% tap at ~bin 150 is an
ALIAS of the near-zero dominant tap — the ISTA delay grid is circular (Φ is
DFT-like), so bins >= G/2 are non-causal negative delays. Computing the delay
spread over only the causal half [0, G/2) drops rms from 389ns to 65ns (true
value), cleanly and robustly (no fragile magnitude threshold). Un-ignores
should_produce_positive_rms_delay_spread.

ADR-134 P2 cir_synthetic now FULLY resolved: all 5 previously-ignored tests
pass via two physics-justified fixes (windowed dominant-ratio for super-
resolution leakage + causal-window rms for circular-grid aliasing). signal+cir:
471 pass / 0 fail / 0 ignored in cir_synthetic.

Co-Authored-By: claude-flow <ruv@ruv.net>
This commit is contained in:
ruv
2026-05-31 06:26:48 -04:00
parent bce5765d89
commit 821f441af0
2 changed files with 6 additions and 2 deletions
@@ -452,7 +452,11 @@ impl CirEstimator {
let active_tap_count = x.iter().filter(|c| c.norm() >= cutoff).count();
// RMS delay spread: √(Σ τ²P(τ)/ΣP(τ) τ̄²), with P(τ) = |tap|².
let power: Vec<f64> = x.iter().map(|c| (c.norm() as f64).powi(2)).collect();
// Only causal delays [0, G/2) contribute: the ISTA delay grid is circular
// (Φ is DFT-like), so bins ≥ G/2 are aliased *negative* (non-causal) delays —
// an alias of the near-zero dominant tap otherwise inflates the spread (ADR-134 P2).
let causal_bins = x.len() / 2;
let power: Vec<f64> = x[..causal_bins].iter().map(|c| (c.norm() as f64).powi(2)).collect();
let p_sum: f64 = power.iter().sum();
let rms_delay_spread_s = if p_sum > 1e-24 {
let mean_tau: f64 = power
@@ -155,6 +155,7 @@ fn save_fixture(path: &str, k_active: usize, csi: &[Complex64], expected_dominan
// ---------------------------------------------------------------------------
// Shared test logic: inject 3-tap channel, run estimator, assert
// ---------------------------------------------------------------------------
@@ -341,7 +342,6 @@ fn should_return_tof_at_40mhz() {
// ---------------------------------------------------------------------------
#[test]
#[ignore = "ADR-134 P2 (remaining): ISTA emits a spurious ~15-20%-of-dominant tap at an implausible far delay (~bin 150, ~3us) that inflates rms_delay_spread to ~390ns. Too close to tap2 (~30%) for a safe magnitude cutoff; needs ISTA recovery-quality work (grid de-aliasing / stronger far-tap suppression), not a band-aid. Dominant-ratio tuning landed separately."]
fn should_produce_positive_rms_delay_spread() {
let cfg = CirConfig::for_bandwidth_mhz(20);
let k_active = cfg.delay_bins / 3;