diff --git a/crates/bgz-tensor/src/gamma_calibration.rs b/crates/bgz-tensor/src/gamma_calibration.rs index 0561046e4..aa4fc44fc 100644 --- a/crates/bgz-tensor/src/gamma_calibration.rs +++ b/crates/bgz-tensor/src/gamma_calibration.rs @@ -432,7 +432,7 @@ mod tests { #[test] fn calibration_profile_size() { - assert_eq!(CalibrationProfile::byte_size(), 40); // 28 + 12 + assert_eq!(CalibrationProfile::byte_size(), 48); // RoleGamma 36 + CosineGamma 12 } #[test] diff --git a/crates/bgz-tensor/src/hhtl_cache.rs b/crates/bgz-tensor/src/hhtl_cache.rs index 3c4767ae2..44e2705a8 100644 --- a/crates/bgz-tensor/src/hhtl_cache.rs +++ b/crates/bgz-tensor/src/hhtl_cache.rs @@ -630,8 +630,8 @@ mod tests { cache.serialize(path).expect("serialize"); let size = std::fs::metadata(path).map(|m| m.len()).unwrap_or(0); - // 4 magic + 2 k + 256×34 entries + 256×256×2 distances + 256×256×1 routes + 256×4 radii - let expected = 4 + 2 + 256 * 34 + 256 * 256 * 2 + 256 * 256 + 256 * 4; + // 4 magic + 2 k + 256×34 entries + 256×256×2 distances + 256×256×1 routes + 256×4 radii + 16 gamma_meta + let expected = 4 + 2 + 256 * 34 + 256 * 256 * 2 + 256 * 256 + 256 * 4 + 16; assert_eq!( size, expected as u64, "expected {expected} bytes, got {size}" diff --git a/crates/bgz-tensor/src/hhtl_d.rs b/crates/bgz-tensor/src/hhtl_d.rs index 6a213513c..5480d5231 100644 --- a/crates/bgz-tensor/src/hhtl_d.rs +++ b/crates/bgz-tensor/src/hhtl_d.rs @@ -553,7 +553,7 @@ mod tests { #[test] fn hhtl_d_entry_roundtrip() { - let entry = HhtlDEntry::new(HeelBasin::Gate, 7, 42, true, 0x3C00); // BF16 1.0 + let entry = HhtlDEntry::new(HeelBasin::Gate, 7, 42, true, 0x3F80); // BF16 1.0 (0x3F80, not the F16 0x3C00) let bytes = entry.to_le_bytes(); let decoded = HhtlDEntry::from_le_bytes(&bytes); diff --git a/crates/bgz-tensor/src/matryoshka.rs b/crates/bgz-tensor/src/matryoshka.rs index 6c19bf899..1eea28a06 100644 --- a/crates/bgz-tensor/src/matryoshka.rs +++ b/crates/bgz-tensor/src/matryoshka.rs @@ -466,7 +466,7 @@ pub fn encode_row(row: &[f32], basis: &SvdBasis, profile: &BandProfile) -> Matry for band in &profile.bands { let max_val = band.precision.max_val(); - let band_coeffs = &coeffs[band.start..band.end.min(coeffs.len())]; + let band_coeffs = &coeffs[band.start.min(coeffs.len())..band.end.min(coeffs.len())]; // Find scale for this band let band_max = band_coeffs @@ -552,7 +552,10 @@ pub fn decode_row(encoded: &MatryoshkaRow, basis: &SvdBasis, profile: &BandProfi offset += 2; let inv_scale = band_max / max_val as f32; - let n = band.n_components(); + // Cap to the coeff buffer: the basis rank can be lower than the + // profile's nominal max (e.g. fewer sample rows than requested + // components), so a band may extend past the available coeffs. + let n = band.n_components().min(coeffs.len().saturating_sub(band.start)); match band.precision { BandPrecision::I16 => {