use oxideav_core::bits::{BitReader, BitWriter};
use crate::{Error, Result};
pub const HCOD1_NUM_ENTRIES: usize = 81;
pub const HCOD1_MAX_LEN: u32 = 11;
const HCOD1: [(u8, u16); HCOD1_NUM_ENTRIES] = [
(11, 0x7f8), (9, 0x1f1), (11, 0x7fd), (10, 0x3f5), (7, 0x68), (10, 0x3f0), (11, 0x7f7), (9, 0x1ec), (11, 0x7f5), (10, 0x3f1), (7, 0x72), (10, 0x3f4), (7, 0x74), (5, 0x11), (7, 0x76), (9, 0x1eb), (7, 0x6c), (10, 0x3f6), (11, 0x7fc), (9, 0x1e1), (11, 0x7f1), (9, 0x1f0), (7, 0x61), (9, 0x1f6), (11, 0x7f2), (9, 0x1ea), (11, 0x7fb), (9, 0x1f2), (7, 0x69), (9, 0x1ed), (7, 0x77), (5, 0x17), (7, 0x6f), (9, 0x1e6), (7, 0x64), (9, 0x1e5), (7, 0x67), (5, 0x15), (7, 0x62), (5, 0x12), (1, 0x000), (5, 0x14), (7, 0x65), (5, 0x16), (7, 0x6d), (9, 0x1e9), (7, 0x63), (9, 0x1e4), (7, 0x6b), (5, 0x13), (7, 0x71), (9, 0x1e3), (7, 0x70), (9, 0x1f3), (11, 0x7fe), (9, 0x1e7), (11, 0x7f3), (9, 0x1ef), (7, 0x60), (9, 0x1ee), (11, 0x7f0), (9, 0x1e2), (11, 0x7fa), (10, 0x3f3), (7, 0x6a), (9, 0x1e8), (7, 0x75), (5, 0x10), (7, 0x73), (9, 0x1f4), (7, 0x6e), (10, 0x3f7), (11, 0x7f6), (9, 0x1e0), (11, 0x7f9), (10, 0x3f2), (7, 0x66), (9, 0x1f5), (11, 0x7ff), (9, 0x1f7), (11, 0x7f4), ];
pub fn hcod1_encode(idx: u32) -> Result<(u8, u16)> {
let entry = HCOD1
.get(idx as usize)
.ok_or(Error::SpectralCodebookIndexOutOfRange(1))?;
Ok(*entry)
}
pub fn hcod1_decode(reader: &mut BitReader<'_>) -> Result<u32> {
let mut acc: u32 = 0;
for len in 1..=HCOD1_MAX_LEN {
let bit = reader.read_u32(1).map_err(|_| Error::UnexpectedEnd)?;
acc = (acc << 1) | bit;
for (idx, &(entry_len, entry_cw)) in HCOD1.iter().enumerate() {
if u32::from(entry_len) == len && u32::from(entry_cw) == acc {
return Ok(idx as u32);
}
}
}
unreachable!("HCOD1 is a complete 11-bit prefix code; the 11-bit walk must match");
}
pub fn hcod1_write(writer: &mut BitWriter, idx: u32) -> Result<()> {
let (len, cw) = hcod1_encode(idx)?;
writer.write_u32(u32::from(cw), u32::from(len));
Ok(())
}
pub const HCOD2_NUM_ENTRIES: usize = 81;
pub const HCOD2_MAX_LEN: u32 = 9;
const HCOD2: [(u8, u16); HCOD2_NUM_ENTRIES] = [
(9, 0x1f3), (7, 0x6f), (9, 0x1fd), (8, 0xeb), (6, 0x23), (8, 0xea), (9, 0x1f7), (8, 0xe8), (9, 0x1fa), (8, 0xf2), (6, 0x2d), (7, 0x70), (6, 0x20), (5, 0x06), (6, 0x2b), (7, 0x6e), (6, 0x28), (8, 0xe9), (9, 0x1f9), (7, 0x66), (8, 0xf8), (8, 0xe7), (6, 0x1b), (8, 0xf1), (9, 0x1f4), (7, 0x6b), (9, 0x1f5), (8, 0xec), (6, 0x2a), (7, 0x6c), (6, 0x2c), (5, 0x0a), (6, 0x27), (7, 0x67), (6, 0x1a), (8, 0xf5), (6, 0x24), (5, 0x08), (6, 0x1f), (5, 0x09), (3, 0x000), (5, 0x07), (6, 0x1d), (5, 0x0b), (6, 0x30), (8, 0xef), (6, 0x1c), (7, 0x64), (6, 0x1e), (5, 0x0c), (6, 0x29), (8, 0xf3), (6, 0x2f), (8, 0xf0), (9, 0x1fc), (7, 0x71), (9, 0x1f2), (8, 0xf4), (6, 0x21), (8, 0xe6), (8, 0xf7), (7, 0x68), (9, 0x1f8), (8, 0xee), (6, 0x22), (7, 0x65), (6, 0x31), (4, 0x02), (6, 0x26), (8, 0xed), (6, 0x25), (7, 0x6a), (9, 0x1fb), (7, 0x72), (9, 0x1fe), (7, 0x69), (6, 0x2e), (8, 0xf6), (9, 0x1ff), (7, 0x6d), (9, 0x1f6), ];
pub fn hcod2_encode(idx: u32) -> Result<(u8, u16)> {
let entry = HCOD2
.get(idx as usize)
.ok_or(Error::SpectralCodebookIndexOutOfRange(2))?;
Ok(*entry)
}
pub fn hcod2_decode(reader: &mut BitReader<'_>) -> Result<u32> {
let mut acc: u32 = 0;
for len in 1..=HCOD2_MAX_LEN {
let bit = reader.read_u32(1).map_err(|_| Error::UnexpectedEnd)?;
acc = (acc << 1) | bit;
for (idx, &(entry_len, entry_cw)) in HCOD2.iter().enumerate() {
if u32::from(entry_len) == len && u32::from(entry_cw) == acc {
return Ok(idx as u32);
}
}
}
unreachable!("HCOD2 is a complete 9-bit prefix code; the 9-bit walk must match");
}
pub fn hcod2_write(writer: &mut BitWriter, idx: u32) -> Result<()> {
let (len, cw) = hcod2_encode(idx)?;
writer.write_u32(u32::from(cw), u32::from(len));
Ok(())
}
pub const HCOD3_NUM_ENTRIES: usize = 81;
pub const HCOD3_MAX_LEN: u32 = 16;
const HCOD3: [(u8, u16); HCOD3_NUM_ENTRIES] = [
(1, 0x0000), (4, 0x0009), (8, 0x00ef), (4, 0x000b), (5, 0x0019), (8, 0x00f0), (9, 0x01eb), (9, 0x01e6), (10, 0x03f2), (4, 0x000a), (6, 0x0035), (9, 0x01ef), (6, 0x0034), (6, 0x0037), (9, 0x01e9), (9, 0x01ed), (9, 0x01e7), (10, 0x03f3), (9, 0x01ee), (10, 0x03ed), (13, 0x1ffa), (9, 0x01ec), (9, 0x01f2), (11, 0x07f9), (11, 0x07f8), (10, 0x03f8), (12, 0x0ff8), (4, 0x0008), (6, 0x0038), (10, 0x03f6), (6, 0x0036), (7, 0x0075), (10, 0x03f1), (10, 0x03eb), (10, 0x03ec), (12, 0x0ff4), (5, 0x0018), (7, 0x0076), (11, 0x07f4), (6, 0x0039), (7, 0x0074), (10, 0x03ef), (9, 0x01f3), (9, 0x01f4), (11, 0x07f6), (9, 0x01e8), (10, 0x03ea), (13, 0x1ffc), (8, 0x00f2), (9, 0x01f1), (12, 0x0ffb), (10, 0x03f5), (11, 0x07f3), (12, 0x0ffc), (8, 0x00ee), (10, 0x03f7), (15, 0x7ffe), (9, 0x01f0), (11, 0x07f5), (15, 0x7ffd), (13, 0x1ffb), (14, 0x3ffa), (16, 0xffff), (8, 0x00f1), (10, 0x03f0), (14, 0x3ffc), (9, 0x01ea), (10, 0x03ee), (14, 0x3ffb), (12, 0x0ff6), (12, 0x0ffa), (15, 0x7ffc), (11, 0x07f2), (12, 0x0ff5), (16, 0xfffe), (10, 0x03f4), (11, 0x07f7), (15, 0x7ffb), (12, 0x0ff7), (12, 0x0ff9), (15, 0x7ffa), ];
pub fn hcod3_encode(idx: u32) -> Result<(u8, u16)> {
let entry = HCOD3
.get(idx as usize)
.ok_or(Error::SpectralCodebookIndexOutOfRange(3))?;
Ok(*entry)
}
pub fn hcod3_decode(reader: &mut BitReader<'_>) -> Result<u32> {
let mut acc: u32 = 0;
for len in 1..=HCOD3_MAX_LEN {
let bit = reader.read_u32(1).map_err(|_| Error::UnexpectedEnd)?;
acc = (acc << 1) | bit;
for (idx, &(entry_len, entry_cw)) in HCOD3.iter().enumerate() {
if u32::from(entry_len) == len && u32::from(entry_cw) == acc {
return Ok(idx as u32);
}
}
}
unreachable!("HCOD3 is a complete 16-bit prefix code; the 16-bit walk must match");
}
pub fn hcod3_write(writer: &mut BitWriter, idx: u32) -> Result<()> {
let (len, cw) = hcod3_encode(idx)?;
writer.write_u32(u32::from(cw), u32::from(len));
Ok(())
}
pub const HCOD4_NUM_ENTRIES: usize = 81;
pub const HCOD4_MAX_LEN: u32 = 12;
const HCOD4: [(u8, u16); HCOD4_NUM_ENTRIES] = [
(4, 0x007), (5, 0x016), (8, 0x0f6), (5, 0x018), (4, 0x008), (8, 0x0ef), (9, 0x1ef), (8, 0x0f3), (11, 0x7f8), (5, 0x019), (5, 0x017), (8, 0x0ed), (5, 0x015), (4, 0x001), (8, 0x0e2), (8, 0x0f0), (7, 0x070), (10, 0x3f0), (9, 0x1ee), (8, 0x0f1), (11, 0x7fa), (8, 0x0ee), (8, 0x0e4), (10, 0x3f2), (11, 0x7f6), (10, 0x3ef), (11, 0x7fd), (4, 0x005), (5, 0x014), (8, 0x0f2), (4, 0x009), (4, 0x004), (8, 0x0e5), (8, 0x0f4), (8, 0x0e8), (10, 0x3f4), (4, 0x006), (4, 0x002), (8, 0x0e7), (4, 0x003), (4, 0x000), (7, 0x06b), (8, 0x0e3), (7, 0x069), (9, 0x1f3), (8, 0x0eb), (8, 0x0e6), (10, 0x3f6), (7, 0x06e), (7, 0x06a), (9, 0x1f4), (10, 0x3ec), (9, 0x1f0), (10, 0x3f9), (8, 0x0f5), (8, 0x0ec), (11, 0x7fb), (8, 0x0ea), (7, 0x06f), (10, 0x3f7), (11, 0x7f9), (10, 0x3f3), (12, 0xfff), (8, 0x0e9), (7, 0x06d), (10, 0x3f8), (7, 0x06c), (7, 0x068), (9, 0x1f5), (10, 0x3ee), (9, 0x1f2), (11, 0x7f4), (11, 0x7f7), (10, 0x3f1), (12, 0xffe), (10, 0x3ed), (9, 0x1f1), (11, 0x7f5), (11, 0x7fe), (10, 0x3f5), (11, 0x7fc), ];
pub fn hcod4_encode(idx: u32) -> Result<(u8, u16)> {
let entry = HCOD4
.get(idx as usize)
.ok_or(Error::SpectralCodebookIndexOutOfRange(4))?;
Ok(*entry)
}
pub fn hcod4_decode(reader: &mut BitReader<'_>) -> Result<u32> {
let mut acc: u32 = 0;
for len in 1..=HCOD4_MAX_LEN {
let bit = reader.read_u32(1).map_err(|_| Error::UnexpectedEnd)?;
acc = (acc << 1) | bit;
for (idx, &(entry_len, entry_cw)) in HCOD4.iter().enumerate() {
if u32::from(entry_len) == len && u32::from(entry_cw) == acc {
return Ok(idx as u32);
}
}
}
unreachable!("HCOD4 is a complete 12-bit prefix code; the 12-bit walk must match");
}
pub fn hcod4_write(writer: &mut BitWriter, idx: u32) -> Result<()> {
let (len, cw) = hcod4_encode(idx)?;
writer.write_u32(u32::from(cw), u32::from(len));
Ok(())
}
pub const HCOD5_NUM_ENTRIES: usize = 81;
pub const HCOD5_MAX_LEN: u32 = 13;
const HCOD5: [(u8, u16); HCOD5_NUM_ENTRIES] = [
(13, 0x1fff), (12, 0xff7), (11, 0x7f4), (11, 0x7e8), (10, 0x3f1), (11, 0x7ee), (11, 0x7f9), (12, 0xff8), (13, 0x1ffd), (12, 0xffd), (11, 0x7f1), (10, 0x3e8), (9, 0x1e8), (8, 0xf0), (9, 0x1ec), (10, 0x3ee), (11, 0x7f2), (12, 0xffa), (12, 0xff4), (10, 0x3ef), (9, 0x1f2), (8, 0xe8), (7, 0x70), (8, 0xec), (9, 0x1f0), (10, 0x3ea), (11, 0x7f3), (11, 0x7eb), (9, 0x1eb), (8, 0xea), (5, 0x1a), (4, 0x8), (5, 0x19), (8, 0xee), (9, 0x1ef), (11, 0x7ed), (10, 0x3f0), (8, 0xf2), (7, 0x73), (4, 0xb), (1, 0x0), (4, 0xa), (7, 0x71), (8, 0xf3), (11, 0x7e9), (11, 0x7ef), (9, 0x1ee), (8, 0xef), (5, 0x18), (4, 0x9), (5, 0x1b), (8, 0xeb), (9, 0x1e9), (11, 0x7ec), (11, 0x7f6), (10, 0x3eb), (9, 0x1f3), (8, 0xed), (7, 0x72), (8, 0xe9), (9, 0x1f1), (10, 0x3ed), (11, 0x7f7), (12, 0xff6), (11, 0x7f0), (10, 0x3e9), (9, 0x1ed), (8, 0xf1), (9, 0x1ea), (10, 0x3ec), (11, 0x7f8), (12, 0xff9), (13, 0x1ffc), (12, 0xffc), (12, 0xff5), (11, 0x7ea), (10, 0x3f3), (10, 0x3f2), (11, 0x7f5), (12, 0xffb), (13, 0x1ffe), ];
pub fn hcod5_encode(idx: u32) -> Result<(u8, u16)> {
let entry = HCOD5
.get(idx as usize)
.ok_or(Error::SpectralCodebookIndexOutOfRange(5))?;
Ok(*entry)
}
pub fn hcod5_decode(reader: &mut BitReader<'_>) -> Result<u32> {
let mut acc: u32 = 0;
for len in 1..=HCOD5_MAX_LEN {
let bit = reader.read_u32(1).map_err(|_| Error::UnexpectedEnd)?;
acc = (acc << 1) | bit;
for (idx, &(entry_len, entry_cw)) in HCOD5.iter().enumerate() {
if u32::from(entry_len) == len && u32::from(entry_cw) == acc {
return Ok(idx as u32);
}
}
}
unreachable!("HCOD5 is a complete 13-bit prefix code; the 13-bit walk must match");
}
pub fn hcod5_write(writer: &mut BitWriter, idx: u32) -> Result<()> {
let (len, cw) = hcod5_encode(idx)?;
writer.write_u32(u32::from(cw), u32::from(len));
Ok(())
}
pub const HCOD6_NUM_ENTRIES: usize = 81;
pub const HCOD6_MAX_LEN: u32 = 11;
const HCOD6: [(u8, u16); HCOD6_NUM_ENTRIES] = [
(11, 0x7fe), (10, 0x3fd), (9, 0x1f1), (9, 0x1eb), (9, 0x1f4), (9, 0x1ea), (9, 0x1f0), (10, 0x3fc), (11, 0x7fd), (10, 0x3f6), (9, 0x1e5), (8, 0xea), (7, 0x6c), (7, 0x71), (7, 0x68), (8, 0xf0), (9, 0x1e6), (10, 0x3f7), (9, 0x1f3), (8, 0xef), (6, 0x32), (6, 0x27), (6, 0x28), (6, 0x26), (6, 0x31), (8, 0xeb), (9, 0x1f7), (9, 0x1e8), (7, 0x6f), (6, 0x2e), (4, 0x8), (4, 0x4), (4, 0x6), (6, 0x29), (7, 0x6b), (9, 0x1ee), (9, 0x1ef), (7, 0x72), (6, 0x2d), (4, 0x2), (4, 0x0), (4, 0x3), (6, 0x2f), (7, 0x73), (9, 0x1fa), (9, 0x1e7), (7, 0x6e), (6, 0x2b), (4, 0x7), (4, 0x1), (4, 0x5), (6, 0x2c), (7, 0x6d), (9, 0x1ec), (9, 0x1f9), (8, 0xee), (6, 0x30), (6, 0x24), (6, 0x2a), (6, 0x25), (6, 0x33), (8, 0xec), (9, 0x1f2), (10, 0x3f8), (9, 0x1e4), (8, 0xed), (7, 0x6a), (7, 0x70), (7, 0x69), (7, 0x74), (8, 0xf1), (10, 0x3fa), (11, 0x7ff), (10, 0x3f9), (9, 0x1f6), (9, 0x1ed), (9, 0x1f8), (9, 0x1e9), (9, 0x1f5), (10, 0x3fb), (11, 0x7fc), ];
pub fn hcod6_encode(idx: u32) -> Result<(u8, u16)> {
let entry = HCOD6
.get(idx as usize)
.ok_or(Error::SpectralCodebookIndexOutOfRange(6))?;
Ok(*entry)
}
pub fn hcod6_decode(reader: &mut BitReader<'_>) -> Result<u32> {
let mut acc: u32 = 0;
for len in 1..=HCOD6_MAX_LEN {
let bit = reader.read_u32(1).map_err(|_| Error::UnexpectedEnd)?;
acc = (acc << 1) | bit;
for (idx, &(entry_len, entry_cw)) in HCOD6.iter().enumerate() {
if u32::from(entry_len) == len && u32::from(entry_cw) == acc {
return Ok(idx as u32);
}
}
}
unreachable!("HCOD6 is a complete 11-bit prefix code; the 11-bit walk must match");
}
pub fn hcod6_write(writer: &mut BitWriter, idx: u32) -> Result<()> {
let (len, cw) = hcod6_encode(idx)?;
writer.write_u32(u32::from(cw), u32::from(len));
Ok(())
}
pub const HCOD7_NUM_ENTRIES: usize = 64;
pub const HCOD7_MAX_LEN: u32 = 12;
const HCOD7: [(u8, u16); HCOD7_NUM_ENTRIES] = [
(1, 0x000), (3, 0x005), (6, 0x037), (7, 0x074), (8, 0x0f2), (9, 0x1eb), (10, 0x3ed), (11, 0x7f7), (3, 0x004), (4, 0x00c), (6, 0x035), (7, 0x071), (8, 0x0ec), (8, 0x0ee), (9, 0x1ee), (9, 0x1f5), (6, 0x036), (6, 0x034), (7, 0x072), (8, 0x0ea), (8, 0x0f1), (9, 0x1e9), (9, 0x1f3), (10, 0x3f5), (7, 0x073), (7, 0x070), (8, 0x0eb), (8, 0x0f0), (9, 0x1f1), (9, 0x1f0), (10, 0x3ec), (10, 0x3fa), (8, 0x0f3), (8, 0x0ed), (9, 0x1e8), (9, 0x1ef), (10, 0x3ef), (10, 0x3f1), (10, 0x3f9), (11, 0x7fb), (9, 0x1ed), (8, 0x0ef), (9, 0x1ea), (9, 0x1f2), (10, 0x3f3), (10, 0x3f8), (11, 0x7f9), (11, 0x7fc), (10, 0x3ee), (9, 0x1ec), (9, 0x1f4), (10, 0x3f4), (10, 0x3f7), (11, 0x7f8), (12, 0xffd), (12, 0xffe), (11, 0x7f6), (10, 0x3f0), (10, 0x3f2), (10, 0x3f6), (11, 0x7fa), (11, 0x7fd), (12, 0xffc), (12, 0xfff), ];
pub fn hcod7_encode(idx: u32) -> Result<(u8, u16)> {
let entry = HCOD7
.get(idx as usize)
.ok_or(Error::SpectralCodebookIndexOutOfRange(7))?;
Ok(*entry)
}
pub fn hcod7_decode(reader: &mut BitReader<'_>) -> Result<u32> {
let mut acc: u32 = 0;
for len in 1..=HCOD7_MAX_LEN {
let bit = reader.read_u32(1).map_err(|_| Error::UnexpectedEnd)?;
acc = (acc << 1) | bit;
for (idx, &(entry_len, entry_cw)) in HCOD7.iter().enumerate() {
if u32::from(entry_len) == len && u32::from(entry_cw) == acc {
return Ok(idx as u32);
}
}
}
unreachable!("HCOD7 is a complete 12-bit prefix code; the 12-bit walk must match");
}
pub fn hcod7_write(writer: &mut BitWriter, idx: u32) -> Result<()> {
let (len, cw) = hcod7_encode(idx)?;
writer.write_u32(u32::from(cw), u32::from(len));
Ok(())
}
pub const HCOD8_NUM_ENTRIES: usize = 64;
pub const HCOD8_MAX_LEN: u32 = 10;
const HCOD8: [(u8, u16); HCOD8_NUM_ENTRIES] = [
(5, 0x00e), (4, 0x005), (5, 0x010), (6, 0x030), (7, 0x06f), (8, 0x0f1), (9, 0x1fa), (10, 0x3fe), (4, 0x003), (3, 0x000), (4, 0x004), (5, 0x012), (6, 0x02c), (7, 0x06a), (7, 0x075), (8, 0x0f8), (5, 0x00f), (4, 0x002), (4, 0x006), (5, 0x014), (6, 0x02e), (7, 0x069), (7, 0x072), (8, 0x0f5), (6, 0x02f), (5, 0x011), (5, 0x013), (6, 0x02a), (6, 0x032), (7, 0x06c), (8, 0x0ec), (8, 0x0fa), (7, 0x071), (6, 0x02b), (6, 0x02d), (6, 0x031), (7, 0x06d), (7, 0x070), (8, 0x0f2), (9, 0x1f9), (8, 0x0ef), (7, 0x068), (6, 0x033), (7, 0x06b), (7, 0x06e), (8, 0x0ee), (8, 0x0f9), (10, 0x3fc), (9, 0x1f8), (7, 0x074), (7, 0x073), (8, 0x0ed), (8, 0x0f0), (8, 0x0f6), (9, 0x1f6), (9, 0x1fd), (10, 0x3fd), (8, 0x0f3), (8, 0x0f4), (8, 0x0f7), (9, 0x1f7), (9, 0x1fb), (9, 0x1fc), (10, 0x3ff), ];
pub fn hcod8_encode(idx: u32) -> Result<(u8, u16)> {
let entry = HCOD8
.get(idx as usize)
.ok_or(Error::SpectralCodebookIndexOutOfRange(8))?;
Ok(*entry)
}
pub fn hcod8_decode(reader: &mut BitReader<'_>) -> Result<u32> {
let mut acc: u32 = 0;
for len in 1..=HCOD8_MAX_LEN {
let bit = reader.read_u32(1).map_err(|_| Error::UnexpectedEnd)?;
acc = (acc << 1) | bit;
for (idx, &(entry_len, entry_cw)) in HCOD8.iter().enumerate() {
if u32::from(entry_len) == len && u32::from(entry_cw) == acc {
return Ok(idx as u32);
}
}
}
unreachable!("HCOD8 is a complete 10-bit prefix code; the 10-bit walk must match");
}
pub fn hcod8_write(writer: &mut BitWriter, idx: u32) -> Result<()> {
let (len, cw) = hcod8_encode(idx)?;
writer.write_u32(u32::from(cw), u32::from(len));
Ok(())
}
pub const HCOD9_NUM_ENTRIES: usize = 169;
pub const HCOD9_MAX_LEN: u32 = 15;
const HCOD9: [(u8, u16); HCOD9_NUM_ENTRIES] = [
(1, 0x0000), (3, 0x0005), (6, 0x0037), (8, 0x00e7), (9, 0x01de), (10, 0x03ce), (10, 0x03d9), (11, 0x07c8), (11, 0x07cd), (12, 0x0fc8), (12, 0x0fdd), (13, 0x1fe4), (13, 0x1fec), (3, 0x0004), (4, 0x000c), (6, 0x0035), (7, 0x0072), (8, 0x00ea), (8, 0x00ed), (9, 0x01e2), (10, 0x03d1), (10, 0x03d3), (10, 0x03e0), (11, 0x07d8), (12, 0x0fcf), (12, 0x0fd5), (6, 0x0036), (6, 0x0034), (7, 0x0071), (8, 0x00e8), (8, 0x00ec), (9, 0x01e1), (10, 0x03cf), (10, 0x03dd), (10, 0x03db), (11, 0x07d0), (12, 0x0fc7), (12, 0x0fd4), (12, 0x0fe4), (8, 0x00e6), (7, 0x0070), (8, 0x00e9), (9, 0x01dd), (9, 0x01e3), (10, 0x03d2), (10, 0x03dc), (11, 0x07cc), (11, 0x07ca), (11, 0x07de), (12, 0x0fd8), (12, 0x0fea), (13, 0x1fdb), (9, 0x01df), (8, 0x00eb), (9, 0x01dc), (9, 0x01e6), (10, 0x03d5), (10, 0x03de), (11, 0x07cb), (11, 0x07dd), (11, 0x07dc), (12, 0x0fcd), (12, 0x0fe2), (12, 0x0fe7), (13, 0x1fe1), (10, 0x03d0), (9, 0x01e0), (9, 0x01e4), (10, 0x03d6), (11, 0x07c5), (11, 0x07d1), (11, 0x07db), (12, 0x0fd2), (11, 0x07e0), (12, 0x0fd9), (12, 0x0feb), (13, 0x1fe3), (13, 0x1fe9), (11, 0x07c4), (9, 0x01e5), (10, 0x03d7), (11, 0x07c6), (11, 0x07cf), (11, 0x07da), (12, 0x0fcb), (12, 0x0fda), (12, 0x0fe3), (12, 0x0fe9), (13, 0x1fe6), (13, 0x1ff3), (13, 0x1ff7), (11, 0x07d3), (10, 0x03d8), (10, 0x03e1), (11, 0x07d4), (11, 0x07d9), (12, 0x0fd3), (12, 0x0fde), (13, 0x1fdd), (13, 0x1fd9), (13, 0x1fe2), (13, 0x1fea), (13, 0x1ff1), (13, 0x1ff6), (11, 0x07d2), (10, 0x03d4), (10, 0x03da), (11, 0x07c7), (11, 0x07d7), (11, 0x07e2), (12, 0x0fce), (12, 0x0fdb), (13, 0x1fd8), (13, 0x1fee), (14, 0x3ff0), (13, 0x1ff4), (14, 0x3ff2), (11, 0x07e1), (10, 0x03df), (11, 0x07c9), (11, 0x07d6), (12, 0x0fca), (12, 0x0fd0), (12, 0x0fe5), (12, 0x0fe6), (13, 0x1feb), (13, 0x1fef), (14, 0x3ff3), (14, 0x3ff4), (14, 0x3ff5), (12, 0x0fe0), (11, 0x07ce), (11, 0x07d5), (12, 0x0fc6), (12, 0x0fd1), (12, 0x0fe1), (13, 0x1fe0), (13, 0x1fe8), (13, 0x1ff0), (14, 0x3ff1), (14, 0x3ff8), (14, 0x3ff6), (15, 0x7ffc), (12, 0x0fe8), (11, 0x07df), (12, 0x0fc9), (12, 0x0fd7), (12, 0x0fdc), (13, 0x1fdc), (13, 0x1fdf), (13, 0x1fed), (13, 0x1ff5), (14, 0x3ff9), (14, 0x3ffb), (15, 0x7ffd), (15, 0x7ffe), (13, 0x1fe7), (12, 0x0fcc), (12, 0x0fd6), (12, 0x0fdf), (13, 0x1fde), (13, 0x1fda), (13, 0x1fe5), (13, 0x1ff2), (14, 0x3ffa), (14, 0x3ff7), (14, 0x3ffc), (14, 0x3ffd), (15, 0x7fff), ];
pub fn hcod9_encode(idx: u32) -> Result<(u8, u16)> {
let entry = HCOD9
.get(idx as usize)
.ok_or(Error::SpectralCodebookIndexOutOfRange(9))?;
Ok(*entry)
}
pub fn hcod9_decode(reader: &mut BitReader<'_>) -> Result<u32> {
let mut acc: u32 = 0;
for len in 1..=HCOD9_MAX_LEN {
let bit = reader.read_u32(1).map_err(|_| Error::UnexpectedEnd)?;
acc = (acc << 1) | bit;
for (idx, &(entry_len, entry_cw)) in HCOD9.iter().enumerate() {
if u32::from(entry_len) == len && u32::from(entry_cw) == acc {
return Ok(idx as u32);
}
}
}
unreachable!("HCOD9 is a complete 15-bit prefix code; the 15-bit walk must match");
}
pub fn hcod9_write(writer: &mut BitWriter, idx: u32) -> Result<()> {
let (len, cw) = hcod9_encode(idx)?;
writer.write_u32(u32::from(cw), u32::from(len));
Ok(())
}
pub const HCOD10_NUM_ENTRIES: usize = 169;
pub const HCOD10_MAX_LEN: u32 = 12;
const HCOD10: [(u8, u16); HCOD10_NUM_ENTRIES] = [
(6, 0x0022), (5, 0x0008), (6, 0x001d), (6, 0x0026), (7, 0x005f), (8, 0x00d3), (9, 0x01cf), (10, 0x03d0), (10, 0x03d7), (10, 0x03ed), (11, 0x07f0), (11, 0x07f6), (12, 0x0ffd), (5, 0x0007), (4, 0x0000), (4, 0x0001), (5, 0x0009), (6, 0x0020), (7, 0x0054), (7, 0x0060), (8, 0x00d5), (8, 0x00dc), (9, 0x01d4), (10, 0x03cd), (10, 0x03de), (11, 0x07e7), (6, 0x001c), (4, 0x0002), (5, 0x0006), (5, 0x000c), (6, 0x001e), (6, 0x0028), (7, 0x005b), (8, 0x00cd), (8, 0x00d9), (9, 0x01ce), (9, 0x01dc), (10, 0x03d9), (10, 0x03f1), (6, 0x0025), (5, 0x000b), (5, 0x000a), (5, 0x000d), (6, 0x0024), (7, 0x0057), (7, 0x0061), (8, 0x00cc), (8, 0x00dd), (9, 0x01cc), (9, 0x01de), (10, 0x03d3), (10, 0x03e7), (7, 0x005d), (6, 0x0021), (6, 0x001f), (6, 0x0023), (6, 0x0027), (7, 0x0059), (7, 0x0064), (8, 0x00d8), (8, 0x00df), (9, 0x01d2), (9, 0x01e2), (10, 0x03dd), (10, 0x03ee), (8, 0x00d1), (7, 0x0055), (6, 0x0029), (7, 0x0056), (7, 0x0058), (7, 0x0062), (8, 0x00ce), (8, 0x00e0), (8, 0x00e2), (9, 0x01da), (10, 0x03d4), (10, 0x03e3), (11, 0x07eb), (9, 0x01c9), (7, 0x005e), (7, 0x005a), (7, 0x005c), (7, 0x0063), (8, 0x00ca), (8, 0x00da), (9, 0x01c7), (9, 0x01ca), (9, 0x01e0), (10, 0x03db), (10, 0x03e8), (11, 0x07ec), (9, 0x01e3), (8, 0x00d2), (8, 0x00cb), (8, 0x00d0), (8, 0x00d7), (8, 0x00db), (9, 0x01c6), (9, 0x01d5), (9, 0x01d8), (10, 0x03ca), (10, 0x03da), (11, 0x07ea), (11, 0x07f1), (9, 0x01e1), (8, 0x00d4), (8, 0x00cf), (8, 0x00d6), (8, 0x00de), (8, 0x00e1), (9, 0x01d0), (9, 0x01d6), (10, 0x03d1), (10, 0x03d5), (10, 0x03f2), (11, 0x07ee), (11, 0x07fb), (10, 0x03e9), (9, 0x01cd), (9, 0x01c8), (9, 0x01cb), (9, 0x01d1), (9, 0x01d7), (9, 0x01df), (10, 0x03cf), (10, 0x03e0), (10, 0x03ef), (11, 0x07e6), (11, 0x07f8), (12, 0x0ffa), (10, 0x03eb), (9, 0x01dd), (9, 0x01d3), (9, 0x01d9), (9, 0x01db), (10, 0x03d2), (10, 0x03cc), (10, 0x03dc), (10, 0x03ea), (11, 0x07ed), (11, 0x07f3), (11, 0x07f9), (12, 0x0ff9), (11, 0x07f2), (10, 0x03ce), (9, 0x01e4), (10, 0x03cb), (10, 0x03d8), (10, 0x03d6), (10, 0x03e2), (10, 0x03e5), (11, 0x07e8), (11, 0x07f4), (11, 0x07f5), (11, 0x07f7), (12, 0x0ffb), (11, 0x07fa), (10, 0x03ec), (10, 0x03df), (10, 0x03e1), (10, 0x03e4), (10, 0x03e6), (10, 0x03f0), (11, 0x07e9), (11, 0x07ef), (12, 0x0ff8), (12, 0x0ffe), (12, 0x0ffc), (12, 0x0fff), ];
pub fn hcod10_encode(idx: u32) -> Result<(u8, u16)> {
let entry = HCOD10
.get(idx as usize)
.ok_or(Error::SpectralCodebookIndexOutOfRange(10))?;
Ok(*entry)
}
pub fn hcod10_decode(reader: &mut BitReader<'_>) -> Result<u32> {
let mut acc: u32 = 0;
for len in 1..=HCOD10_MAX_LEN {
let bit = reader.read_u32(1).map_err(|_| Error::UnexpectedEnd)?;
acc = (acc << 1) | bit;
for (idx, &(entry_len, entry_cw)) in HCOD10.iter().enumerate() {
if u32::from(entry_len) == len && u32::from(entry_cw) == acc {
return Ok(idx as u32);
}
}
}
unreachable!("HCOD10 is a complete 12-bit prefix code; the 12-bit walk must match");
}
pub fn hcod10_write(writer: &mut BitWriter, idx: u32) -> Result<()> {
let (len, cw) = hcod10_encode(idx)?;
writer.write_u32(u32::from(cw), u32::from(len));
Ok(())
}
pub const HCOD11_NUM_ENTRIES: usize = 289;
pub const HCOD11_MAX_LEN: u32 = 12;
const HCOD11: [(u8, u16); HCOD11_NUM_ENTRIES] = [
(4, 0x0000), (5, 0x0006), (6, 0x0019), (7, 0x003d), (8, 0x009c), (8, 0x00c6), (9, 0x01a7), (10, 0x0390), (10, 0x03c2), (10, 0x03df), (11, 0x07e6), (11, 0x07f3), (12, 0x0ffb), (11, 0x07ec), (12, 0x0ffa), (12, 0x0ffe), (10, 0x038e), (5, 0x0005), (4, 0x0001), (5, 0x0008), (6, 0x0014), (7, 0x0037), (7, 0x0042), (8, 0x0092), (8, 0x00af), (9, 0x0191), (9, 0x01a5), (9, 0x01b5), (10, 0x039e), (10, 0x03c0), (10, 0x03a2), (10, 0x03cd), (11, 0x07d6), (8, 0x00ae), (6, 0x0017), (5, 0x0007), (5, 0x0009), (6, 0x0018), (7, 0x0039), (7, 0x0040), (8, 0x008e), (8, 0x00a3), (8, 0x00b8), (9, 0x0199), (9, 0x01ac), (9, 0x01c1), (10, 0x03b1), (10, 0x0396), (10, 0x03be), (10, 0x03ca), (8, 0x009d), (7, 0x003c), (6, 0x0015), (6, 0x0016), (6, 0x001a), (7, 0x003b), (7, 0x0044), (8, 0x0091), (8, 0x00a5), (8, 0x00be), (9, 0x0196), (9, 0x01ae), (9, 0x01b9), (10, 0x03a1), (10, 0x0391), (10, 0x03a5), (10, 0x03d5), (8, 0x0094), (8, 0x009a), (7, 0x0036), (7, 0x0038), (7, 0x003a), (7, 0x0041), (8, 0x008c), (8, 0x009b), (8, 0x00b0), (8, 0x00c3), (9, 0x019e), (9, 0x01ab), (9, 0x01bc), (10, 0x039f), (10, 0x038f), (10, 0x03a9), (10, 0x03cf), (8, 0x0093), (8, 0x00bf), (7, 0x003e), (7, 0x003f), (7, 0x0043), (7, 0x0045), (8, 0x009e), (8, 0x00a7), (8, 0x00b9), (9, 0x0194), (9, 0x01a2), (9, 0x01ba), (9, 0x01c3), (10, 0x03a6), (10, 0x03a7), (10, 0x03bb), (10, 0x03d4), (8, 0x009f), (9, 0x01a0), (8, 0x008f), (8, 0x008d), (8, 0x0090), (8, 0x0098), (8, 0x00a6), (8, 0x00b6), (8, 0x00c4), (9, 0x019f), (9, 0x01af), (9, 0x01bf), (10, 0x0399), (10, 0x03bf), (10, 0x03b4), (10, 0x03c9), (10, 0x03e7), (8, 0x00a8), (9, 0x01b6), (8, 0x00ab), (8, 0x00a4), (8, 0x00aa), (8, 0x00b2), (8, 0x00c2), (8, 0x00c5), (9, 0x0198), (9, 0x01a4), (9, 0x01b8), (10, 0x038c), (10, 0x03a4), (10, 0x03c4), (10, 0x03c6), (10, 0x03dd), (10, 0x03e8), (8, 0x00ad), (10, 0x03af), (9, 0x0192), (8, 0x00bd), (8, 0x00bc), (9, 0x018e), (9, 0x0197), (9, 0x019a), (9, 0x01a3), (9, 0x01b1), (10, 0x038d), (10, 0x0398), (10, 0x03b7), (10, 0x03d3), (10, 0x03d1), (10, 0x03db), (11, 0x07dd), (8, 0x00b4), (10, 0x03de), (9, 0x01a9), (9, 0x019b), (9, 0x019c), (9, 0x01a1), (9, 0x01aa), (9, 0x01ad), (9, 0x01b3), (10, 0x038b), (10, 0x03b2), (10, 0x03b8), (10, 0x03ce), (10, 0x03e1), (10, 0x03e0), (11, 0x07d2), (11, 0x07e5), (8, 0x00b7), (11, 0x07e3), (9, 0x01bb), (9, 0x01a8), (9, 0x01a6), (9, 0x01b0), (9, 0x01b2), (9, 0x01b7), (10, 0x039b), (10, 0x039a), (10, 0x03ba), (10, 0x03b5), (10, 0x03d6), (11, 0x07d7), (10, 0x03e4), (11, 0x07d8), (11, 0x07ea), (8, 0x00ba), (11, 0x07e8), (10, 0x03a0), (9, 0x01bd), (9, 0x01b4), (10, 0x038a), (9, 0x01c4), (10, 0x0392), (10, 0x03aa), (10, 0x03b0), (10, 0x03bc), (10, 0x03d7), (11, 0x07d4), (11, 0x07dc), (11, 0x07db), (11, 0x07d5), (11, 0x07f0), (8, 0x00c1), (11, 0x07fb), (10, 0x03c8), (10, 0x03a3), (10, 0x0395), (10, 0x039d), (10, 0x03ac), (10, 0x03ae), (10, 0x03c5), (10, 0x03d8), (10, 0x03e2), (10, 0x03e6), (11, 0x07e4), (11, 0x07e7), (11, 0x07e0), (11, 0x07e9), (11, 0x07f7), (9, 0x0190), (11, 0x07f2), (10, 0x0393), (9, 0x01be), (9, 0x01c0), (10, 0x0394), (10, 0x0397), (10, 0x03ad), (10, 0x03c3), (10, 0x03c1), (10, 0x03d2), (11, 0x07da), (11, 0x07d9), (11, 0x07df), (11, 0x07eb), (11, 0x07f4), (11, 0x07fa), (9, 0x0195), (11, 0x07f8), (10, 0x03bd), (10, 0x039c), (10, 0x03ab), (10, 0x03a8), (10, 0x03b3), (10, 0x03b9), (10, 0x03d0), (10, 0x03e3), (10, 0x03e5), (11, 0x07e2), (11, 0x07de), (11, 0x07ed), (11, 0x07f1), (11, 0x07f9), (11, 0x07fc), (9, 0x0193), (12, 0x0ffd), (10, 0x03dc), (10, 0x03b6), (10, 0x03c7), (10, 0x03cc), (10, 0x03cb), (10, 0x03d9), (10, 0x03da), (11, 0x07d3), (11, 0x07e1), (11, 0x07ee), (11, 0x07ef), (11, 0x07f5), (11, 0x07f6), (12, 0x0ffc), (12, 0x0fff), (9, 0x019d), (9, 0x01c2), (8, 0x00b5), (8, 0x00a1), (8, 0x0096), (8, 0x0097), (8, 0x0095), (8, 0x0099), (8, 0x00a0), (8, 0x00a2), (8, 0x00ac), (8, 0x00a9), (8, 0x00b1), (8, 0x00b3), (8, 0x00bb), (8, 0x00c0), (9, 0x018f), (5, 0x0004), ];
pub fn hcod11_encode(idx: u32) -> Result<(u8, u16)> {
let entry = HCOD11
.get(idx as usize)
.ok_or(Error::SpectralCodebookIndexOutOfRange(11))?;
Ok(*entry)
}
pub fn hcod11_decode(reader: &mut BitReader<'_>) -> Result<u32> {
let mut acc: u32 = 0;
for len in 1..=HCOD11_MAX_LEN {
let bit = reader.read_u32(1).map_err(|_| Error::UnexpectedEnd)?;
acc = (acc << 1) | bit;
for (idx, &(entry_len, entry_cw)) in HCOD11.iter().enumerate() {
if u32::from(entry_len) == len && u32::from(entry_cw) == acc {
return Ok(idx as u32);
}
}
}
unreachable!("HCOD11 is a complete 12-bit prefix code; the 12-bit walk must match");
}
pub fn hcod11_write(writer: &mut BitWriter, idx: u32) -> Result<()> {
let (len, cw) = hcod11_encode(idx)?;
writer.write_u32(u32::from(cw), u32::from(len));
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn hcod1_has_exactly_81_entries() {
assert_eq!(HCOD1.len(), HCOD1_NUM_ENTRIES);
assert_eq!(HCOD1_NUM_ENTRIES, 81);
}
#[test]
fn hcod1_max_length_is_11_bits() {
let max = HCOD1.iter().map(|&(len, _)| len).max().unwrap();
assert_eq!(u32::from(max), HCOD1_MAX_LEN);
assert_eq!(HCOD1_MAX_LEN, 11);
}
#[test]
fn hcod1_min_length_is_one_bit_at_index_40() {
for (idx, &(len, cw)) in HCOD1.iter().enumerate() {
if idx == 40 {
assert_eq!(len, 1, "index 40 must be 1-bit");
assert_eq!(cw, 0, "index 40 codeword must be `0`");
} else {
assert!(
len >= 5,
"every non-zero-tuple index must have length >= 5; idx={} len={}",
idx,
len
);
}
}
}
#[test]
fn hcod1_codewords_fit_their_declared_length() {
for (idx, &(len, cw)) in HCOD1.iter().enumerate() {
let max = if len == 0 { 0 } else { (1u32 << len) - 1 };
assert!(
u32::from(cw) <= max,
"idx={}: codeword {:#x} does not fit {} bits",
idx,
cw,
len
);
}
}
#[test]
fn hcod1_kraft_sum_is_two_to_the_eleven() {
let lmax = HCOD1_MAX_LEN;
let mut sum: u64 = 0;
for &(len, _) in &HCOD1 {
sum += 1u64 << (lmax - u32::from(len));
}
assert_eq!(sum, 1u64 << lmax, "Kraft equality failed");
assert_eq!(sum, 2048);
}
#[test]
fn hcod1_is_complete() {
for prefix in 0u32..(1u32 << HCOD1_MAX_LEN) {
let bytes = [(prefix >> 3) as u8, ((prefix & 0x7) << 5) as u8];
let mut br = BitReader::new(&bytes);
let idx = hcod1_decode(&mut br).expect("11-bit prefix must decode");
let (len, cw) = hcod1_encode(idx).expect("decoded index must round-trip");
let lead = prefix >> (HCOD1_MAX_LEN - u32::from(len));
assert_eq!(
u32::from(cw),
lead,
"round-trip prefix={:#05x} idx={} len={} cw={:#x}",
prefix,
idx,
len,
cw
);
}
}
#[test]
fn encode_zero_tuple_is_single_zero_bit() {
let (len, cw) = hcod1_encode(40).unwrap();
assert_eq!(len, 1);
assert_eq!(cw, 0);
}
#[test]
fn encode_first_entry_matches_table() {
let (len, cw) = hcod1_encode(0).unwrap();
assert_eq!(len, 11);
assert_eq!(cw, 0x7f8);
}
#[test]
fn encode_last_entry_matches_table() {
let (len, cw) = hcod1_encode(80).unwrap();
assert_eq!(len, 11);
assert_eq!(cw, 0x7f4);
}
#[test]
fn encode_rejects_out_of_range_index() {
assert!(matches!(
hcod1_encode(81),
Err(Error::SpectralCodebookIndexOutOfRange(1))
));
assert!(matches!(
hcod1_encode(0xffff_ffff),
Err(Error::SpectralCodebookIndexOutOfRange(1))
));
}
#[test]
fn decode_single_zero_bit_yields_index_40() {
let bytes = [0b0111_1111u8];
let mut br = BitReader::new(&bytes);
let idx = hcod1_decode(&mut br).unwrap();
assert_eq!(idx, 40);
assert_eq!(br.bit_position(), 1);
}
#[test]
fn decode_first_entry_round_trip() {
let bytes = [0xff, 0x00];
let mut br = BitReader::new(&bytes);
let idx = hcod1_decode(&mut br).unwrap();
assert_eq!(idx, 0);
assert_eq!(br.bit_position(), 11);
}
#[test]
fn decode_propagates_unexpected_end() {
let bytes: [u8; 0] = [];
let mut br = BitReader::new(&bytes);
assert_eq!(hcod1_decode(&mut br), Err(Error::UnexpectedEnd));
}
#[test]
fn write_then_decode_round_trips_every_index() {
for idx in 0..HCOD1_NUM_ENTRIES as u32 {
let mut w = BitWriter::new();
hcod1_write(&mut w, idx).unwrap();
let (len, _) = hcod1_encode(idx).unwrap();
let mut w2 = w;
let pad = (8 - (u32::from(len) % 8)) % 8;
if pad > 0 {
w2.write_u32(0, pad);
}
let bytes = w2.into_bytes();
let mut br = BitReader::new(&bytes);
let decoded = hcod1_decode(&mut br).unwrap();
assert_eq!(
decoded, idx,
"round-trip mismatch at idx={} (encoded as {} bits)",
idx, len
);
}
}
#[test]
fn write_rejects_out_of_range_index() {
let mut w = BitWriter::new();
assert!(matches!(
hcod1_write(&mut w, 81),
Err(Error::SpectralCodebookIndexOutOfRange(1))
));
}
#[test]
fn hcod2_has_exactly_81_entries() {
assert_eq!(HCOD2.len(), HCOD2_NUM_ENTRIES);
assert_eq!(HCOD2_NUM_ENTRIES, 81);
}
#[test]
fn hcod2_max_length_is_9_bits() {
let max = HCOD2.iter().map(|&(len, _)| len).max().unwrap();
assert_eq!(u32::from(max), HCOD2_MAX_LEN);
assert_eq!(HCOD2_MAX_LEN, 9);
}
#[test]
fn hcod2_min_length_is_three_bits_at_index_40() {
for (idx, &(len, cw)) in HCOD2.iter().enumerate() {
if idx == 40 {
assert_eq!(len, 3, "index 40 must be 3-bit");
assert_eq!(cw, 0, "index 40 codeword must be `0`");
} else {
assert!(
len >= 4,
"every non-zero-tuple index must have length >= 4; idx={} len={}",
idx,
len
);
}
}
}
#[test]
fn hcod2_codewords_fit_their_declared_length() {
for (idx, &(len, cw)) in HCOD2.iter().enumerate() {
let max = if len == 0 { 0 } else { (1u32 << len) - 1 };
assert!(
u32::from(cw) <= max,
"idx={}: codeword {:#x} does not fit {} bits",
idx,
cw,
len
);
}
}
#[test]
fn hcod2_kraft_sum_is_two_to_the_nine() {
let lmax = HCOD2_MAX_LEN;
let mut sum: u64 = 0;
for &(len, _) in &HCOD2 {
sum += 1u64 << (lmax - u32::from(len));
}
assert_eq!(sum, 1u64 << lmax, "Kraft equality failed");
assert_eq!(sum, 512);
}
#[test]
fn hcod2_is_complete() {
for prefix in 0u32..(1u32 << HCOD2_MAX_LEN) {
let bytes = [(prefix >> 1) as u8, ((prefix & 0x1) << 7) as u8];
let mut br = BitReader::new(&bytes);
let idx = hcod2_decode(&mut br).expect("9-bit prefix must decode");
let (len, cw) = hcod2_encode(idx).expect("decoded index must round-trip");
let lead = prefix >> (HCOD2_MAX_LEN - u32::from(len));
assert_eq!(
u32::from(cw),
lead,
"round-trip prefix={:#05x} idx={} len={} cw={:#x}",
prefix,
idx,
len,
cw
);
}
}
#[test]
fn encode_zero_tuple_is_three_zero_bits_in_codebook_2() {
let (len, cw) = hcod2_encode(40).unwrap();
assert_eq!(len, 3);
assert_eq!(cw, 0);
}
#[test]
fn hcod2_encode_first_entry_matches_table() {
let (len, cw) = hcod2_encode(0).unwrap();
assert_eq!(len, 9);
assert_eq!(cw, 0x1f3);
}
#[test]
fn hcod2_encode_last_entry_matches_table() {
let (len, cw) = hcod2_encode(80).unwrap();
assert_eq!(len, 9);
assert_eq!(cw, 0x1f6);
}
#[test]
fn hcod2_encode_rejects_out_of_range_index() {
assert!(matches!(
hcod2_encode(81),
Err(Error::SpectralCodebookIndexOutOfRange(2))
));
assert!(matches!(
hcod2_encode(0xffff_ffff),
Err(Error::SpectralCodebookIndexOutOfRange(2))
));
}
#[test]
fn hcod2_decode_three_zero_bits_yields_index_40() {
let bytes = [0b0001_1111u8];
let mut br = BitReader::new(&bytes);
let idx = hcod2_decode(&mut br).unwrap();
assert_eq!(idx, 40);
assert_eq!(br.bit_position(), 3);
}
#[test]
fn hcod2_decode_first_entry_round_trip() {
let bytes = [0xf9, 0x80];
let mut br = BitReader::new(&bytes);
let idx = hcod2_decode(&mut br).unwrap();
assert_eq!(idx, 0);
assert_eq!(br.bit_position(), 9);
}
#[test]
fn hcod2_decode_propagates_unexpected_end() {
let bytes: [u8; 0] = [];
let mut br = BitReader::new(&bytes);
assert_eq!(hcod2_decode(&mut br), Err(Error::UnexpectedEnd));
}
#[test]
fn hcod2_write_then_decode_round_trips_every_index() {
for idx in 0..HCOD2_NUM_ENTRIES as u32 {
let mut w = BitWriter::new();
hcod2_write(&mut w, idx).unwrap();
let (len, _) = hcod2_encode(idx).unwrap();
let mut w2 = w;
let pad = (8 - (u32::from(len) % 8)) % 8;
if pad > 0 {
w2.write_u32(0, pad);
}
let bytes = w2.into_bytes();
let mut br = BitReader::new(&bytes);
let decoded = hcod2_decode(&mut br).unwrap();
assert_eq!(
decoded, idx,
"round-trip mismatch at idx={} (encoded as {} bits)",
idx, len
);
}
}
#[test]
fn hcod2_write_rejects_out_of_range_index() {
let mut w = BitWriter::new();
assert!(matches!(
hcod2_write(&mut w, 81),
Err(Error::SpectralCodebookIndexOutOfRange(2))
));
}
#[test]
fn codebook_1_and_2_disagree_on_zero_tuple_codeword_length() {
let (l1, _) = hcod1_encode(40).unwrap();
let (l2, _) = hcod2_encode(40).unwrap();
assert_eq!(l1, 1);
assert_eq!(l2, 3);
assert_ne!(l1, l2);
}
#[test]
fn hcod3_has_exactly_81_entries() {
assert_eq!(HCOD3.len(), HCOD3_NUM_ENTRIES);
assert_eq!(HCOD3_NUM_ENTRIES, 81);
}
#[test]
fn hcod3_max_length_is_16_bits() {
let max = HCOD3.iter().map(|&(len, _)| len).max().unwrap();
assert_eq!(u32::from(max), HCOD3_MAX_LEN);
assert_eq!(HCOD3_MAX_LEN, 16);
}
#[test]
fn hcod3_min_length_is_one_bit_at_index_0() {
for (idx, &(len, cw)) in HCOD3.iter().enumerate() {
if idx == 0 {
assert_eq!(len, 1, "index 0 must be 1-bit");
assert_eq!(cw, 0, "index 0 codeword must be `0`");
} else {
assert!(
len >= 4,
"every non-zero-tuple index must have length >= 4; idx={} len={}",
idx,
len
);
}
}
}
#[test]
fn hcod3_codewords_fit_their_declared_length() {
for (idx, &(len, cw)) in HCOD3.iter().enumerate() {
let max = if len == 0 { 0 } else { (1u32 << len) - 1 };
assert!(
u32::from(cw) <= max,
"idx={}: codeword {:#x} does not fit {} bits",
idx,
cw,
len
);
}
}
#[test]
fn hcod3_kraft_sum_is_two_to_the_sixteen() {
let lmax = HCOD3_MAX_LEN;
let mut sum: u64 = 0;
for &(len, _) in &HCOD3 {
sum += 1u64 << (lmax - u32::from(len));
}
assert_eq!(sum, 1u64 << lmax, "Kraft equality failed");
assert_eq!(sum, 65536);
}
#[test]
fn hcod3_is_complete() {
for prefix in 0u32..(1u32 << HCOD3_MAX_LEN) {
let bytes = [(prefix >> 8) as u8, (prefix & 0xff) as u8];
let mut br = BitReader::new(&bytes);
let idx = hcod3_decode(&mut br).expect("16-bit prefix must decode");
let (len, cw) = hcod3_encode(idx).expect("decoded index must round-trip");
let lead = prefix >> (HCOD3_MAX_LEN - u32::from(len));
assert_eq!(
u32::from(cw),
lead,
"round-trip prefix={:#06x} idx={} len={} cw={:#x}",
prefix,
idx,
len,
cw
);
}
}
#[test]
fn hcod3_encode_zero_tuple_is_single_zero_bit() {
let (len, cw) = hcod3_encode(0).unwrap();
assert_eq!(len, 1);
assert_eq!(cw, 0);
}
#[test]
fn hcod3_encode_last_entry_matches_table() {
let (len, cw) = hcod3_encode(80).unwrap();
assert_eq!(len, 15);
assert_eq!(cw, 0x7ffa);
}
#[test]
fn hcod3_encode_index_62_is_the_only_full_16_bit_codeword_0xffff() {
let (len, cw) = hcod3_encode(62).unwrap();
assert_eq!(len, 16);
assert_eq!(cw, 0xffff);
let count_matching = HCOD3.iter().filter(|&&(_, c)| c == 0xffff).count();
assert_eq!(count_matching, 1);
}
#[test]
fn hcod3_encode_rejects_out_of_range_index() {
assert!(matches!(
hcod3_encode(81),
Err(Error::SpectralCodebookIndexOutOfRange(3))
));
assert!(matches!(
hcod3_encode(0xffff_ffff),
Err(Error::SpectralCodebookIndexOutOfRange(3))
));
}
#[test]
fn hcod3_decode_single_zero_bit_yields_index_0() {
let bytes = [0b0111_1111u8];
let mut br = BitReader::new(&bytes);
let idx = hcod3_decode(&mut br).unwrap();
assert_eq!(idx, 0);
assert_eq!(br.bit_position(), 1);
}
#[test]
fn hcod3_decode_full_16_bit_codeword_round_trips() {
let bytes = [0xff, 0xff];
let mut br = BitReader::new(&bytes);
let idx = hcod3_decode(&mut br).unwrap();
assert_eq!(idx, 62);
assert_eq!(br.bit_position(), 16);
}
#[test]
fn hcod3_decode_propagates_unexpected_end() {
let bytes: [u8; 0] = [];
let mut br = BitReader::new(&bytes);
assert_eq!(hcod3_decode(&mut br), Err(Error::UnexpectedEnd));
}
#[test]
fn hcod3_write_then_decode_round_trips_every_index() {
for idx in 0..HCOD3_NUM_ENTRIES as u32 {
let mut w = BitWriter::new();
hcod3_write(&mut w, idx).unwrap();
let (len, _) = hcod3_encode(idx).unwrap();
let mut w2 = w;
let pad = (8 - (u32::from(len) % 8)) % 8;
if pad > 0 {
w2.write_u32(0, pad);
}
let bytes = w2.into_bytes();
let mut br = BitReader::new(&bytes);
let decoded = hcod3_decode(&mut br).unwrap();
assert_eq!(
decoded, idx,
"round-trip mismatch at idx={} (encoded as {} bits)",
idx, len
);
}
}
#[test]
fn hcod3_write_rejects_out_of_range_index() {
let mut w = BitWriter::new();
assert!(matches!(
hcod3_write(&mut w, 81),
Err(Error::SpectralCodebookIndexOutOfRange(3))
));
}
#[test]
fn codebook_3_zero_tuple_lives_at_index_zero_not_forty() {
let (l1, cw1) = hcod1_encode(40).unwrap();
let (l3, cw3) = hcod3_encode(0).unwrap();
assert_eq!(l1, 1);
assert_eq!(cw1, 0);
assert_eq!(l3, 1);
assert_eq!(cw3, 0);
}
#[test]
fn hcod4_has_exactly_81_entries() {
assert_eq!(HCOD4.len(), HCOD4_NUM_ENTRIES);
assert_eq!(HCOD4_NUM_ENTRIES, 81);
}
#[test]
fn hcod4_max_length_is_12_bits() {
let max = HCOD4.iter().map(|&(len, _)| len).max().unwrap();
assert_eq!(u32::from(max), HCOD4_MAX_LEN);
assert_eq!(HCOD4_MAX_LEN, 12);
}
#[test]
fn hcod4_min_length_is_four_bits_at_index_40() {
let (len_40, cw_40) = (HCOD4[40].0, HCOD4[40].1);
assert_eq!(len_40, 4, "index 40 must be 4-bit");
assert_eq!(cw_40, 0, "index 40 codeword must be `0b0000`");
for (idx, &(len, _)) in HCOD4.iter().enumerate() {
assert!(
len >= 4,
"every index must have length >= 4; idx={} len={}",
idx,
len
);
}
}
#[test]
fn hcod4_codewords_fit_their_declared_length() {
for (idx, &(len, cw)) in HCOD4.iter().enumerate() {
let max = if len == 0 { 0 } else { (1u32 << len) - 1 };
assert!(
u32::from(cw) <= max,
"idx={}: codeword {:#x} does not fit {} bits",
idx,
cw,
len
);
}
}
#[test]
fn hcod4_kraft_sum_is_two_to_the_twelve() {
let lmax = HCOD4_MAX_LEN;
let mut sum: u64 = 0;
for &(len, _) in &HCOD4 {
sum += 1u64 << (lmax - u32::from(len));
}
assert_eq!(sum, 1u64 << lmax, "Kraft equality failed");
assert_eq!(sum, 4096);
}
#[test]
fn hcod4_is_complete() {
for prefix in 0u32..(1u32 << HCOD4_MAX_LEN) {
let bytes = [(prefix >> 4) as u8, ((prefix & 0xf) << 4) as u8];
let mut br = BitReader::new(&bytes);
let idx = hcod4_decode(&mut br).expect("12-bit prefix must decode");
let (len, cw) = hcod4_encode(idx).expect("decoded index must round-trip");
let lead = prefix >> (HCOD4_MAX_LEN - u32::from(len));
assert_eq!(
u32::from(cw),
lead,
"round-trip prefix={:#05x} idx={} len={} cw={:#x}",
prefix,
idx,
len,
cw
);
}
}
#[test]
fn hcod4_encode_index_40_is_4_bit_zero_codeword() {
let (len, cw) = hcod4_encode(40).unwrap();
assert_eq!(len, 4);
assert_eq!(cw, 0);
}
#[test]
fn hcod4_encode_first_entry_matches_table() {
let (len, cw) = hcod4_encode(0).unwrap();
assert_eq!(len, 4);
assert_eq!(cw, 0x7);
}
#[test]
fn hcod4_encode_last_entry_matches_table() {
let (len, cw) = hcod4_encode(80).unwrap();
assert_eq!(len, 11);
assert_eq!(cw, 0x7fc);
}
#[test]
fn hcod4_encode_indices_62_and_74_are_the_full_12_bit_codewords() {
let (len_62, cw_62) = hcod4_encode(62).unwrap();
assert_eq!((len_62, cw_62), (12, 0xfff));
let (len_74, cw_74) = hcod4_encode(74).unwrap();
assert_eq!((len_74, cw_74), (12, 0xffe));
let count_12_bit = HCOD4.iter().filter(|&&(l, _)| l == 12).count();
assert_eq!(count_12_bit, 2);
}
#[test]
fn hcod4_encode_rejects_out_of_range_index() {
assert!(matches!(
hcod4_encode(81),
Err(Error::SpectralCodebookIndexOutOfRange(4))
));
assert!(matches!(
hcod4_encode(0xffff_ffff),
Err(Error::SpectralCodebookIndexOutOfRange(4))
));
}
#[test]
fn hcod4_decode_four_zero_bits_yields_index_40() {
let bytes = [0b0000_1111u8];
let mut br = BitReader::new(&bytes);
let idx = hcod4_decode(&mut br).unwrap();
assert_eq!(idx, 40);
assert_eq!(br.bit_position(), 4);
}
#[test]
fn hcod4_decode_full_12_bit_codeword_round_trips_index_62() {
let bytes = [0xff, 0xf0];
let mut br = BitReader::new(&bytes);
let idx = hcod4_decode(&mut br).unwrap();
assert_eq!(idx, 62);
assert_eq!(br.bit_position(), 12);
}
#[test]
fn hcod4_decode_propagates_unexpected_end() {
let bytes: [u8; 0] = [];
let mut br = BitReader::new(&bytes);
assert_eq!(hcod4_decode(&mut br), Err(Error::UnexpectedEnd));
}
#[test]
fn hcod4_write_then_decode_round_trips_every_index() {
for idx in 0..HCOD4_NUM_ENTRIES as u32 {
let mut w = BitWriter::new();
hcod4_write(&mut w, idx).unwrap();
let (len, _) = hcod4_encode(idx).unwrap();
let mut w2 = w;
let pad = (8 - (u32::from(len) % 8)) % 8;
if pad > 0 {
w2.write_u32(0, pad);
}
let bytes = w2.into_bytes();
let mut br = BitReader::new(&bytes);
let decoded = hcod4_decode(&mut br).unwrap();
assert_eq!(
decoded, idx,
"round-trip mismatch at idx={} (encoded as {} bits)",
idx, len
);
}
}
#[test]
fn hcod4_write_rejects_out_of_range_index() {
let mut w = BitWriter::new();
assert!(matches!(
hcod4_write(&mut w, 81),
Err(Error::SpectralCodebookIndexOutOfRange(4))
));
}
#[test]
fn codebook_3_and_4_disagree_on_zero_tuple_codeword() {
let (l3, cw3) = hcod3_encode(0).unwrap();
let (l4, cw4) = hcod4_encode(0).unwrap();
assert_eq!((l3, cw3), (1, 0));
assert_eq!((l4, cw4), (4, 0x7));
let (l40, cw40) = hcod4_encode(40).unwrap();
assert_eq!((l40, cw40), (4, 0));
}
#[test]
fn hcod5_has_exactly_81_entries() {
assert_eq!(HCOD5.len(), HCOD5_NUM_ENTRIES);
assert_eq!(HCOD5_NUM_ENTRIES, 81);
}
#[test]
fn hcod5_max_length_is_13_bits() {
let max = HCOD5.iter().map(|&(len, _)| len).max().unwrap();
assert_eq!(u32::from(max), HCOD5_MAX_LEN);
assert_eq!(HCOD5_MAX_LEN, 13);
}
#[test]
fn hcod5_min_length_is_one_bit_at_index_40() {
let (len_40, cw_40) = (HCOD5[40].0, HCOD5[40].1);
assert_eq!(len_40, 1, "index 40 must be 1-bit");
assert_eq!(cw_40, 0, "index 40 codeword must be `0`");
let count_1_bit = HCOD5.iter().filter(|&&(l, _)| l == 1).count();
assert_eq!(count_1_bit, 1, "exactly one 1-bit codeword");
}
#[test]
fn hcod5_codewords_fit_their_declared_length() {
for (idx, &(len, cw)) in HCOD5.iter().enumerate() {
let max = if len == 0 { 0 } else { (1u32 << len) - 1 };
assert!(
u32::from(cw) <= max,
"idx={}: codeword {:#x} does not fit {} bits",
idx,
cw,
len
);
}
}
#[test]
fn hcod5_kraft_sum_is_two_to_the_thirteen() {
let lmax = HCOD5_MAX_LEN;
let mut sum: u64 = 0;
for &(len, _) in &HCOD5 {
sum += 1u64 << (lmax - u32::from(len));
}
assert_eq!(sum, 1u64 << lmax, "Kraft equality failed");
assert_eq!(sum, 8192);
}
#[test]
fn hcod5_is_complete() {
for prefix in 0u32..(1u32 << HCOD5_MAX_LEN) {
let bytes = [(prefix >> 5) as u8, ((prefix & 0x1f) << 3) as u8];
let mut br = BitReader::new(&bytes);
let idx = hcod5_decode(&mut br).expect("13-bit prefix must decode");
let (len, cw) = hcod5_encode(idx).expect("decoded index must round-trip");
let lead = prefix >> (HCOD5_MAX_LEN - u32::from(len));
assert_eq!(
u32::from(cw),
lead,
"round-trip prefix={:#06x} idx={} len={} cw={:#x}",
prefix,
idx,
len,
cw
);
}
}
#[test]
fn hcod5_encode_index_40_is_single_zero_bit() {
let (len, cw) = hcod5_encode(40).unwrap();
assert_eq!(len, 1);
assert_eq!(cw, 0);
}
#[test]
fn hcod5_encode_first_entry_matches_table() {
let (len, cw) = hcod5_encode(0).unwrap();
assert_eq!(len, 13);
assert_eq!(cw, 0x1fff);
}
#[test]
fn hcod5_encode_last_entry_matches_table() {
let (len, cw) = hcod5_encode(80).unwrap();
assert_eq!(len, 13);
assert_eq!(cw, 0x1ffe);
}
#[test]
fn hcod5_encode_four_13_bit_rows_are_the_lattice_corners() {
let expected = [
(0u32, 0x1fffu16), (8u32, 0x1ffdu16), (72u32, 0x1ffcu16), (80u32, 0x1ffeu16), ];
let observed: Vec<_> = HCOD5
.iter()
.enumerate()
.filter_map(|(i, &(l, cw))| if l == 13 { Some((i as u32, cw)) } else { None })
.collect();
assert_eq!(observed.len(), 4);
for (e, o) in expected.iter().zip(observed.iter()) {
assert_eq!(*e, *o, "expected {:?} got {:?}", e, o);
}
}
#[test]
fn hcod5_encode_rejects_out_of_range_index() {
assert!(matches!(
hcod5_encode(81),
Err(Error::SpectralCodebookIndexOutOfRange(5))
));
assert!(matches!(
hcod5_encode(0xffff_ffff),
Err(Error::SpectralCodebookIndexOutOfRange(5))
));
}
#[test]
fn hcod5_decode_single_zero_bit_yields_index_40() {
let bytes = [0b0111_1111u8];
let mut br = BitReader::new(&bytes);
let idx = hcod5_decode(&mut br).unwrap();
assert_eq!(idx, 40);
assert_eq!(br.bit_position(), 1);
}
#[test]
fn hcod5_decode_full_13_bit_codeword_round_trips_index_0() {
let bytes = [0xff, 0xf8];
let mut br = BitReader::new(&bytes);
let idx = hcod5_decode(&mut br).unwrap();
assert_eq!(idx, 0);
assert_eq!(br.bit_position(), 13);
}
#[test]
fn hcod5_decode_propagates_unexpected_end() {
let bytes: [u8; 0] = [];
let mut br = BitReader::new(&bytes);
assert_eq!(hcod5_decode(&mut br), Err(Error::UnexpectedEnd));
}
#[test]
fn hcod5_write_then_decode_round_trips_every_index() {
for idx in 0..HCOD5_NUM_ENTRIES as u32 {
let mut w = BitWriter::new();
hcod5_write(&mut w, idx).unwrap();
let (len, _) = hcod5_encode(idx).unwrap();
let mut w2 = w;
let pad = (8 - (u32::from(len) % 8)) % 8;
if pad > 0 {
w2.write_u32(0, pad);
}
let bytes = w2.into_bytes();
let mut br = BitReader::new(&bytes);
let decoded = hcod5_decode(&mut br).unwrap();
assert_eq!(
decoded, idx,
"round-trip mismatch at idx={} (encoded as {} bits)",
idx, len
);
}
}
#[test]
fn hcod5_write_rejects_out_of_range_index() {
let mut w = BitWriter::new();
assert!(matches!(
hcod5_write(&mut w, 81),
Err(Error::SpectralCodebookIndexOutOfRange(5))
));
}
#[test]
fn hcod6_has_exactly_81_entries() {
assert_eq!(HCOD6.len(), HCOD6_NUM_ENTRIES);
assert_eq!(HCOD6_NUM_ENTRIES, 81);
}
#[test]
fn hcod6_max_length_is_11_bits() {
let max = HCOD6.iter().map(|&(len, _)| len).max().unwrap();
assert_eq!(u32::from(max), HCOD6_MAX_LEN);
assert_eq!(HCOD6_MAX_LEN, 11);
}
#[test]
fn hcod6_min_length_is_four_bits_at_index_40() {
let (len_40, cw_40) = (HCOD6[40].0, HCOD6[40].1);
assert_eq!(len_40, 4, "index 40 must be 4-bit");
assert_eq!(cw_40, 0, "index 40 codeword must be `0b0000`");
for (idx, &(len, _)) in HCOD6.iter().enumerate() {
assert!(
len >= 4,
"every index must have length >= 4; idx={} len={}",
idx,
len
);
}
}
#[test]
fn hcod6_codewords_fit_their_declared_length() {
for (idx, &(len, cw)) in HCOD6.iter().enumerate() {
let max = if len == 0 { 0 } else { (1u32 << len) - 1 };
assert!(
u32::from(cw) <= max,
"idx={}: codeword {:#x} does not fit {} bits",
idx,
cw,
len
);
}
}
#[test]
fn hcod6_kraft_sum_is_two_to_the_eleven() {
let lmax = HCOD6_MAX_LEN;
let mut sum: u64 = 0;
for &(len, _) in &HCOD6 {
sum += 1u64 << (lmax - u32::from(len));
}
assert_eq!(sum, 1u64 << lmax, "Kraft equality failed");
assert_eq!(sum, 2048);
}
#[test]
fn hcod6_is_complete() {
for prefix in 0u32..(1u32 << HCOD6_MAX_LEN) {
let bytes = [(prefix >> 3) as u8, ((prefix & 0x7) << 5) as u8];
let mut br = BitReader::new(&bytes);
let idx = hcod6_decode(&mut br).expect("11-bit prefix must decode");
let (len, cw) = hcod6_encode(idx).expect("decoded index must round-trip");
let lead = prefix >> (HCOD6_MAX_LEN - u32::from(len));
assert_eq!(
u32::from(cw),
lead,
"round-trip prefix={:#05x} idx={} len={} cw={:#x}",
prefix,
idx,
len,
cw
);
}
}
#[test]
fn hcod6_encode_index_40_is_4_bit_zero_codeword() {
let (len, cw) = hcod6_encode(40).unwrap();
assert_eq!(len, 4);
assert_eq!(cw, 0);
}
#[test]
fn hcod6_encode_first_entry_matches_table() {
let (len, cw) = hcod6_encode(0).unwrap();
assert_eq!(len, 11);
assert_eq!(cw, 0x7fe);
}
#[test]
fn hcod6_encode_last_entry_matches_table() {
let (len, cw) = hcod6_encode(80).unwrap();
assert_eq!(len, 11);
assert_eq!(cw, 0x7fc);
}
#[test]
fn hcod6_encode_four_11_bit_rows_are_the_lattice_corners() {
let expected = [
(0u32, 0x7feu16), (8u32, 0x7fdu16), (72u32, 0x7ffu16), (80u32, 0x7fcu16), ];
let observed: Vec<_> = HCOD6
.iter()
.enumerate()
.filter_map(|(i, &(l, cw))| if l == 11 { Some((i as u32, cw)) } else { None })
.collect();
assert_eq!(observed.len(), 4);
for (e, o) in expected.iter().zip(observed.iter()) {
assert_eq!(*e, *o, "expected {:?} got {:?}", e, o);
}
}
#[test]
fn hcod6_encode_rejects_out_of_range_index() {
assert!(matches!(
hcod6_encode(81),
Err(Error::SpectralCodebookIndexOutOfRange(6))
));
assert!(matches!(
hcod6_encode(0xffff_ffff),
Err(Error::SpectralCodebookIndexOutOfRange(6))
));
}
#[test]
fn hcod6_decode_four_zero_bits_yields_index_40() {
let bytes = [0b0000_1111u8];
let mut br = BitReader::new(&bytes);
let idx = hcod6_decode(&mut br).unwrap();
assert_eq!(idx, 40);
assert_eq!(br.bit_position(), 4);
}
#[test]
fn hcod6_decode_full_11_bit_codeword_round_trips_index_72() {
let bytes = [0xff, 0xe0];
let mut br = BitReader::new(&bytes);
let idx = hcod6_decode(&mut br).unwrap();
assert_eq!(idx, 72);
assert_eq!(br.bit_position(), 11);
}
#[test]
fn hcod6_decode_propagates_unexpected_end() {
let bytes: [u8; 0] = [];
let mut br = BitReader::new(&bytes);
assert_eq!(hcod6_decode(&mut br), Err(Error::UnexpectedEnd));
}
#[test]
fn hcod6_write_then_decode_round_trips_every_index() {
for idx in 0..HCOD6_NUM_ENTRIES as u32 {
let mut w = BitWriter::new();
hcod6_write(&mut w, idx).unwrap();
let (len, _) = hcod6_encode(idx).unwrap();
let mut w2 = w;
let pad = (8 - (u32::from(len) % 8)) % 8;
if pad > 0 {
w2.write_u32(0, pad);
}
let bytes = w2.into_bytes();
let mut br = BitReader::new(&bytes);
let decoded = hcod6_decode(&mut br).unwrap();
assert_eq!(
decoded, idx,
"round-trip mismatch at idx={} (encoded as {} bits)",
idx, len
);
}
}
#[test]
fn hcod6_write_rejects_out_of_range_index() {
let mut w = BitWriter::new();
assert!(matches!(
hcod6_write(&mut w, 81),
Err(Error::SpectralCodebookIndexOutOfRange(6))
));
}
#[test]
fn codebook_5_and_6_disagree_on_zero_tuple_codeword() {
let (l5, cw5) = hcod5_encode(40).unwrap();
let (l6, cw6) = hcod6_encode(40).unwrap();
assert_eq!((l5, cw5), (1, 0));
assert_eq!((l6, cw6), (4, 0));
}
#[test]
fn codebook_5_and_6_agree_on_lattice_corner_indices() {
let corners: Vec<usize> = [0, 8, 72, 80].to_vec();
let cb5_max_idx: Vec<usize> = HCOD5
.iter()
.enumerate()
.filter_map(|(i, &(l, _))| {
if u32::from(l) == HCOD5_MAX_LEN {
Some(i)
} else {
None
}
})
.collect();
let cb6_max_idx: Vec<usize> = HCOD6
.iter()
.enumerate()
.filter_map(|(i, &(l, _))| {
if u32::from(l) == HCOD6_MAX_LEN {
Some(i)
} else {
None
}
})
.collect();
assert_eq!(cb5_max_idx, corners);
assert_eq!(cb6_max_idx, corners);
}
#[test]
fn hcod7_has_exactly_64_entries() {
assert_eq!(HCOD7.len(), HCOD7_NUM_ENTRIES);
assert_eq!(HCOD7_NUM_ENTRIES, 64);
}
#[test]
fn hcod7_max_length_is_12_bits() {
let max = HCOD7.iter().map(|&(len, _)| len).max().unwrap();
assert_eq!(u32::from(max), HCOD7_MAX_LEN);
assert_eq!(HCOD7_MAX_LEN, 12);
}
#[test]
fn hcod7_min_length_is_one_bit_at_index_0() {
let (len_0, cw_0) = (HCOD7[0].0, HCOD7[0].1);
assert_eq!(len_0, 1, "index 0 must be 1-bit");
assert_eq!(cw_0, 0, "index 0 codeword must be `0`");
let single_bit_entries: usize = HCOD7.iter().filter(|&&(len, _)| len == 1).count();
assert_eq!(single_bit_entries, 1, "exactly one 1-bit codeword");
for (idx, &(len, _)) in HCOD7.iter().enumerate().skip(1) {
assert!(
len >= 3,
"every index > 0 must have length >= 3; idx={} len={}",
idx,
len
);
}
}
#[test]
fn hcod7_codewords_fit_their_declared_length() {
for (idx, &(len, cw)) in HCOD7.iter().enumerate() {
let max = if len == 0 { 0 } else { (1u32 << len) - 1 };
assert!(
u32::from(cw) <= max,
"idx={}: codeword {:#x} does not fit {} bits",
idx,
cw,
len
);
}
}
#[test]
fn hcod7_kraft_sum_is_two_to_the_twelve() {
let lmax = HCOD7_MAX_LEN;
let mut sum: u64 = 0;
for &(len, _) in &HCOD7 {
sum += 1u64 << (lmax - u32::from(len));
}
assert_eq!(sum, 1u64 << lmax, "Kraft equality failed");
assert_eq!(sum, 4096);
}
#[test]
fn hcod7_is_complete() {
for prefix in 0u32..(1u32 << HCOD7_MAX_LEN) {
let bytes = [(prefix >> 4) as u8, ((prefix & 0xf) << 4) as u8];
let mut br = BitReader::new(&bytes);
let idx = hcod7_decode(&mut br).expect("12-bit prefix must decode");
let (len, cw) = hcod7_encode(idx).expect("decoded index must round-trip");
let lead = prefix >> (HCOD7_MAX_LEN - u32::from(len));
assert_eq!(
u32::from(cw),
lead,
"round-trip prefix={:#05x} idx={} len={} cw={:#x}",
prefix,
idx,
len,
cw
);
}
}
#[test]
fn hcod7_encode_index_0_is_1_bit_zero_codeword() {
let (len, cw) = hcod7_encode(0).unwrap();
assert_eq!(len, 1);
assert_eq!(cw, 0);
}
#[test]
fn hcod7_encode_last_entry_matches_table() {
let (len, cw) = hcod7_encode(63).unwrap();
assert_eq!(len, 12);
assert_eq!(cw, 0xfff);
}
#[test]
fn hcod7_encode_four_12_bit_rows_match_table() {
let expected = [
(54u32, 0xffdu16),
(55u32, 0xffeu16),
(62u32, 0xffcu16),
(63u32, 0xfffu16),
];
let observed: Vec<_> = HCOD7
.iter()
.enumerate()
.filter_map(|(i, &(l, cw))| if l == 12 { Some((i as u32, cw)) } else { None })
.collect();
assert_eq!(observed.len(), 4);
for (e, o) in expected.iter().zip(observed.iter()) {
assert_eq!(*e, *o, "expected {:?} got {:?}", e, o);
}
}
#[test]
fn hcod7_encode_index_8_is_first_y1_row() {
let (len, cw) = hcod7_encode(8).unwrap();
assert_eq!(len, 3);
assert_eq!(cw, 4);
}
#[test]
fn hcod7_encode_rejects_out_of_range_index() {
assert!(matches!(
hcod7_encode(64),
Err(Error::SpectralCodebookIndexOutOfRange(7))
));
assert!(matches!(
hcod7_encode(0xffff_ffff),
Err(Error::SpectralCodebookIndexOutOfRange(7))
));
}
#[test]
fn hcod7_decode_single_zero_bit_yields_index_0() {
let bytes = [0b0111_1111u8];
let mut br = BitReader::new(&bytes);
let idx = hcod7_decode(&mut br).unwrap();
assert_eq!(idx, 0);
assert_eq!(br.bit_position(), 1);
}
#[test]
fn hcod7_decode_full_12_bit_codeword_round_trips_index_63() {
let bytes = [0xff, 0xf0];
let mut br = BitReader::new(&bytes);
let idx = hcod7_decode(&mut br).unwrap();
assert_eq!(idx, 63);
assert_eq!(br.bit_position(), 12);
}
#[test]
fn hcod7_decode_propagates_unexpected_end() {
let bytes: [u8; 0] = [];
let mut br = BitReader::new(&bytes);
assert_eq!(hcod7_decode(&mut br), Err(Error::UnexpectedEnd));
}
#[test]
fn hcod7_write_then_decode_round_trips_every_index() {
for idx in 0..HCOD7_NUM_ENTRIES as u32 {
let mut w = BitWriter::new();
hcod7_write(&mut w, idx).unwrap();
let (len, _) = hcod7_encode(idx).unwrap();
let mut w2 = w;
let pad = (8 - (u32::from(len) % 8)) % 8;
if pad > 0 {
w2.write_u32(0, pad);
}
let bytes = w2.into_bytes();
let mut br = BitReader::new(&bytes);
let decoded = hcod7_decode(&mut br).unwrap();
assert_eq!(
decoded, idx,
"round-trip mismatch at idx={} (encoded as {} bits)",
idx, len
);
}
}
#[test]
fn hcod7_write_rejects_out_of_range_index() {
let mut w = BitWriter::new();
assert!(matches!(
hcod7_write(&mut w, 64),
Err(Error::SpectralCodebookIndexOutOfRange(7))
));
}
#[test]
fn codebook_3_and_7_both_park_zero_tuple_at_index_0() {
let (l3, cw3) = hcod3_encode(0).unwrap();
let (l7, cw7) = hcod7_encode(0).unwrap();
assert_eq!((l3, cw3), (1, 0));
assert_eq!((l7, cw7), (1, 0));
}
#[test]
fn codebook_7_entry_count_is_64_vs_81_for_dim4_books() {
assert_eq!(HCOD3.len(), 81);
assert_eq!(HCOD4.len(), 81);
assert_eq!(HCOD7.len(), 64);
}
#[test]
fn hcod8_has_exactly_64_entries() {
assert_eq!(HCOD8.len(), HCOD8_NUM_ENTRIES);
assert_eq!(HCOD8_NUM_ENTRIES, 64);
}
#[test]
fn hcod8_max_length_is_10_bits() {
let max = HCOD8.iter().map(|&(len, _)| len).max().unwrap();
assert_eq!(u32::from(max), HCOD8_MAX_LEN);
assert_eq!(HCOD8_MAX_LEN, 10);
}
#[test]
fn hcod8_min_length_is_three_bits_at_index_9() {
let (len_9, cw_9) = (HCOD8[9].0, HCOD8[9].1);
assert_eq!(len_9, 3, "index 9 must be 3-bit");
assert_eq!(cw_9, 0, "index 9 codeword must be `0`");
let three_bit_entries: usize = HCOD8.iter().filter(|&&(len, _)| len == 3).count();
assert_eq!(three_bit_entries, 1, "exactly one 3-bit codeword");
for (idx, &(len, _)) in HCOD8.iter().enumerate() {
if idx == 9 {
continue;
}
assert!(
len >= 4,
"every index != 9 must have length >= 4; idx={} len={}",
idx,
len
);
}
}
#[test]
fn hcod8_codewords_fit_their_declared_length() {
for (idx, &(len, cw)) in HCOD8.iter().enumerate() {
let max = if len == 0 { 0 } else { (1u32 << len) - 1 };
assert!(
u32::from(cw) <= max,
"idx={}: codeword {:#x} does not fit {} bits",
idx,
cw,
len
);
}
}
#[test]
fn hcod8_kraft_sum_is_two_to_the_ten() {
let lmax = HCOD8_MAX_LEN;
let mut sum: u64 = 0;
for &(len, _) in &HCOD8 {
sum += 1u64 << (lmax - u32::from(len));
}
assert_eq!(sum, 1u64 << lmax, "Kraft equality failed");
assert_eq!(sum, 1024);
}
#[test]
fn hcod8_is_complete() {
for prefix in 0u32..(1u32 << HCOD8_MAX_LEN) {
let bytes = [(prefix >> 2) as u8, ((prefix & 0x3) << 6) as u8];
let mut br = BitReader::new(&bytes);
let idx = hcod8_decode(&mut br).expect("10-bit prefix must decode");
let (len, cw) = hcod8_encode(idx).expect("decoded index must round-trip");
let lead = prefix >> (HCOD8_MAX_LEN - u32::from(len));
assert_eq!(
u32::from(cw),
lead,
"round-trip prefix={:#05x} idx={} len={} cw={:#x}",
prefix,
idx,
len,
cw
);
}
}
#[test]
fn hcod8_encode_index_0_is_5_bit_zero_tuple_codeword() {
let (len, cw) = hcod8_encode(0).unwrap();
assert_eq!(len, 5);
assert_eq!(cw, 0xe);
}
#[test]
fn hcod8_encode_index_9_is_3_bit_zero_codeword() {
let (len, cw) = hcod8_encode(9).unwrap();
assert_eq!(len, 3);
assert_eq!(cw, 0);
}
#[test]
fn hcod8_encode_last_entry_matches_table() {
let (len, cw) = hcod8_encode(63).unwrap();
assert_eq!(len, 10);
assert_eq!(cw, 0x3ff);
}
#[test]
fn hcod8_encode_four_10_bit_rows_match_table() {
let expected = [
(7u32, 0x3feu16),
(47u32, 0x3fcu16),
(56u32, 0x3fdu16),
(63u32, 0x3ffu16),
];
let observed: Vec<_> = HCOD8
.iter()
.enumerate()
.filter_map(|(i, &(l, cw))| if l == 10 { Some((i as u32, cw)) } else { None })
.collect();
assert_eq!(observed.len(), 4);
for (e, o) in expected.iter().zip(observed.iter()) {
assert_eq!(*e, *o, "expected {:?} got {:?}", e, o);
}
}
#[test]
fn hcod8_encode_index_8_is_first_y1_row() {
let (len, cw) = hcod8_encode(8).unwrap();
assert_eq!(len, 4);
assert_eq!(cw, 0x3);
}
#[test]
fn hcod8_encode_rejects_out_of_range_index() {
assert!(matches!(
hcod8_encode(64),
Err(Error::SpectralCodebookIndexOutOfRange(8))
));
assert!(matches!(
hcod8_encode(0xffff_ffff),
Err(Error::SpectralCodebookIndexOutOfRange(8))
));
}
#[test]
fn hcod8_decode_three_zero_bits_yields_index_9() {
let bytes = [0b0001_1111u8];
let mut br = BitReader::new(&bytes);
let idx = hcod8_decode(&mut br).unwrap();
assert_eq!(idx, 9);
assert_eq!(br.bit_position(), 3);
}
#[test]
fn hcod8_decode_full_10_bit_codeword_round_trips_index_63() {
let bytes = [0xff, 0xc0];
let mut br = BitReader::new(&bytes);
let idx = hcod8_decode(&mut br).unwrap();
assert_eq!(idx, 63);
assert_eq!(br.bit_position(), 10);
}
#[test]
fn hcod8_decode_propagates_unexpected_end() {
let bytes: [u8; 0] = [];
let mut br = BitReader::new(&bytes);
assert_eq!(hcod8_decode(&mut br), Err(Error::UnexpectedEnd));
}
#[test]
fn hcod8_write_then_decode_round_trips_every_index() {
for idx in 0..HCOD8_NUM_ENTRIES as u32 {
let mut w = BitWriter::new();
hcod8_write(&mut w, idx).unwrap();
let (len, _) = hcod8_encode(idx).unwrap();
let mut w2 = w;
let pad = (8 - (u32::from(len) % 8)) % 8;
if pad > 0 {
w2.write_u32(0, pad);
}
let bytes = w2.into_bytes();
let mut br = BitReader::new(&bytes);
let decoded = hcod8_decode(&mut br).unwrap();
assert_eq!(
decoded, idx,
"round-trip mismatch at idx={} (encoded as {} bits)",
idx, len
);
}
}
#[test]
fn hcod8_write_rejects_out_of_range_index() {
let mut w = BitWriter::new();
assert!(matches!(
hcod8_write(&mut w, 64),
Err(Error::SpectralCodebookIndexOutOfRange(8))
));
}
#[test]
fn codebook_7_and_8_share_universe_size_but_disagree_on_shortest_slot() {
assert_eq!(HCOD7_NUM_ENTRIES, HCOD8_NUM_ENTRIES);
assert_eq!(HCOD7_NUM_ENTRIES, 64);
let (l7_0, _) = hcod7_encode(0).unwrap();
assert_eq!(l7_0, 1);
let (l8_0, _) = hcod8_encode(0).unwrap();
let (l8_9, cw8_9) = hcod8_encode(9).unwrap();
assert_eq!(l8_0, 5);
assert_eq!((l8_9, cw8_9), (3, 0));
}
#[test]
fn codebook_8_far_corner_matches_codebook_7_far_corner_index() {
let (l7, cw7) = hcod7_encode(63).unwrap();
let (l8, cw8) = hcod8_encode(63).unwrap();
assert_eq!((l7, cw7), (12, 0xfff));
assert_eq!((l8, cw8), (10, 0x3ff));
}
#[test]
fn hcod9_has_exactly_169_entries() {
assert_eq!(HCOD9.len(), HCOD9_NUM_ENTRIES);
assert_eq!(HCOD9_NUM_ENTRIES, 169);
}
#[test]
fn hcod9_max_length_is_15_bits() {
let max = HCOD9.iter().map(|&(len, _)| len).max().unwrap();
assert_eq!(u32::from(max), HCOD9_MAX_LEN);
assert_eq!(HCOD9_MAX_LEN, 15);
}
#[test]
fn hcod9_min_length_is_one_bit_at_index_0() {
for (idx, &(len, cw)) in HCOD9.iter().enumerate() {
if idx == 0 {
assert_eq!(len, 1, "index 0 must be 1-bit");
assert_eq!(cw, 0, "index 0 codeword must be `0`");
} else {
assert!(
len >= 3,
"every non-zero index must have length >= 3; idx={} len={}",
idx,
len
);
}
}
}
#[test]
fn hcod9_codewords_fit_their_declared_length() {
for (idx, &(len, cw)) in HCOD9.iter().enumerate() {
let max = if len == 0 { 0 } else { (1u32 << len) - 1 };
assert!(
u32::from(cw) <= max,
"idx={}: codeword {:#x} does not fit {} bits",
idx,
cw,
len
);
}
}
#[test]
fn hcod9_kraft_sum_is_two_to_the_fifteen() {
let lmax = HCOD9_MAX_LEN;
let mut sum: u64 = 0;
for &(len, _) in &HCOD9 {
sum += 1u64 << (lmax - u32::from(len));
}
assert_eq!(sum, 1u64 << lmax, "Kraft equality failed");
assert_eq!(sum, 32768);
}
#[test]
fn hcod9_is_complete() {
for prefix in 0u32..(1u32 << HCOD9_MAX_LEN) {
let bytes = [(prefix >> 7) as u8, ((prefix & 0x7f) << 1) as u8];
let mut br = BitReader::new(&bytes);
let idx = hcod9_decode(&mut br).expect("15-bit prefix must decode");
let (len, cw) = hcod9_encode(idx).expect("decoded index must round-trip");
let lead = prefix >> (HCOD9_MAX_LEN - u32::from(len));
assert_eq!(
u32::from(cw),
lead,
"round-trip prefix={:#06x} idx={} len={} cw={:#x}",
prefix,
idx,
len,
cw
);
}
}
#[test]
fn hcod9_encode_index_0_is_one_bit_zero_codeword() {
let (len, cw) = hcod9_encode(0).unwrap();
assert_eq!(len, 1);
assert_eq!(cw, 0);
}
#[test]
fn hcod9_encode_first_few_rows_match_spec() {
assert_eq!(hcod9_encode(1).unwrap(), (3, 0x5));
assert_eq!(hcod9_encode(13).unwrap(), (3, 0x4));
assert_eq!(hcod9_encode(14).unwrap(), (4, 0xc));
}
#[test]
fn hcod9_encode_last_entry_matches_table() {
let (len, cw) = hcod9_encode(168).unwrap();
assert_eq!(len, 15);
assert_eq!(cw, 0x7fff);
}
#[test]
fn hcod9_encode_four_15_bit_rows_match_table() {
let expected = [
(142u32, 0x7ffcu16),
(154u32, 0x7ffdu16),
(155u32, 0x7ffeu16),
(168u32, 0x7fffu16),
];
let observed: Vec<_> = HCOD9
.iter()
.enumerate()
.filter_map(|(i, &(l, cw))| if l == 15 { Some((i as u32, cw)) } else { None })
.collect();
assert_eq!(observed.len(), 4);
for (e, o) in expected.iter().zip(observed.iter()) {
assert_eq!(*e, *o, "expected {:?} got {:?}", e, o);
}
}
#[test]
fn hcod9_encode_rejects_out_of_range_index() {
assert!(matches!(
hcod9_encode(169),
Err(Error::SpectralCodebookIndexOutOfRange(9))
));
assert!(matches!(
hcod9_encode(0xffff_ffff),
Err(Error::SpectralCodebookIndexOutOfRange(9))
));
}
#[test]
fn hcod9_decode_single_zero_bit_yields_index_0() {
let bytes = [0b0111_1111u8];
let mut br = BitReader::new(&bytes);
let idx = hcod9_decode(&mut br).unwrap();
assert_eq!(idx, 0);
assert_eq!(br.bit_position(), 1);
}
#[test]
fn hcod9_decode_full_15_bit_codeword_round_trips_index_168() {
let bytes = [0xff, 0xfe];
let mut br = BitReader::new(&bytes);
let idx = hcod9_decode(&mut br).unwrap();
assert_eq!(idx, 168);
assert_eq!(br.bit_position(), 15);
}
#[test]
fn hcod9_decode_propagates_unexpected_end() {
let bytes: [u8; 0] = [];
let mut br = BitReader::new(&bytes);
assert_eq!(hcod9_decode(&mut br), Err(Error::UnexpectedEnd));
}
#[test]
fn hcod9_write_then_decode_round_trips_every_index() {
for idx in 0..HCOD9_NUM_ENTRIES as u32 {
let mut w = BitWriter::new();
hcod9_write(&mut w, idx).unwrap();
let (len, _) = hcod9_encode(idx).unwrap();
let mut w2 = w;
let pad = (8 - (u32::from(len) % 8)) % 8;
if pad > 0 {
w2.write_u32(0, pad);
}
let bytes = w2.into_bytes();
let mut br = BitReader::new(&bytes);
let decoded = hcod9_decode(&mut br).unwrap();
assert_eq!(
decoded, idx,
"round-trip mismatch at idx={} (encoded as {} bits)",
idx, len
);
}
}
#[test]
fn hcod9_write_rejects_out_of_range_index() {
let mut w = BitWriter::new();
assert!(matches!(
hcod9_write(&mut w, 169),
Err(Error::SpectralCodebookIndexOutOfRange(9))
));
}
#[test]
fn codebook_9_universe_size_grows_to_169_from_codebook_8_64() {
assert_eq!(HCOD7_NUM_ENTRIES, 64);
assert_eq!(HCOD8_NUM_ENTRIES, 64);
assert_eq!(HCOD9_NUM_ENTRIES, 169);
const { assert!(HCOD9_NUM_ENTRIES > 2 * HCOD8_NUM_ENTRIES) };
}
#[test]
fn codebook_9_zero_tuple_shares_codebook_7_head_placement() {
let (l7_0, cw7_0) = hcod7_encode(0).unwrap();
let (l9_0, cw9_0) = hcod9_encode(0).unwrap();
assert_eq!((l7_0, cw7_0), (1, 0));
assert_eq!((l9_0, cw9_0), (1, 0));
}
#[test]
fn codebook_9_far_corner_index_matches_lav_12_polynomial() {
let (l9, cw9) = hcod9_encode(168).unwrap();
assert_eq!((l9, cw9), (15, 0x7fff));
let (l8, cw8) = hcod8_encode(63).unwrap();
assert_eq!((l8, cw8), (10, 0x3ff));
assert_eq!(HCOD9_MAX_LEN - HCOD8_MAX_LEN, 5);
}
#[test]
fn hcod10_has_exactly_169_entries() {
assert_eq!(HCOD10.len(), HCOD10_NUM_ENTRIES);
assert_eq!(HCOD10_NUM_ENTRIES, 169);
}
#[test]
fn hcod10_max_length_is_12_bits() {
let max = HCOD10.iter().map(|&(len, _)| len).max().unwrap();
assert_eq!(u32::from(max), HCOD10_MAX_LEN);
assert_eq!(HCOD10_MAX_LEN, 12);
}
#[test]
fn hcod10_min_length_is_four_bits_at_interior_tuple_index_14() {
let mut four_bit_indices = Vec::new();
for (idx, &(len, _)) in HCOD10.iter().enumerate() {
if len == 4 {
four_bit_indices.push(idx);
}
assert!(
len >= 4,
"every row must have length >= 4; idx={} len={}",
idx,
len
);
}
assert_eq!(four_bit_indices, vec![14, 15, 27]);
}
#[test]
fn hcod10_zero_tuple_lives_at_index_0_with_six_bit_codeword() {
let (len, cw) = HCOD10[0];
assert_eq!(len, 6);
assert_eq!(cw, 0x22);
}
#[test]
fn hcod10_codewords_fit_their_declared_length() {
for (idx, &(len, cw)) in HCOD10.iter().enumerate() {
let max = if len == 0 { 0 } else { (1u32 << len) - 1 };
assert!(
u32::from(cw) <= max,
"idx={}: codeword {:#x} does not fit {} bits",
idx,
cw,
len
);
}
}
#[test]
fn hcod10_kraft_sum_is_two_to_the_twelve() {
let lmax = HCOD10_MAX_LEN;
let mut sum: u64 = 0;
for &(len, _) in &HCOD10 {
sum += 1u64 << (lmax - u32::from(len));
}
assert_eq!(sum, 1u64 << lmax, "Kraft equality failed");
assert_eq!(sum, 4096);
}
#[test]
fn hcod10_is_complete() {
for prefix in 0u32..(1u32 << HCOD10_MAX_LEN) {
let bytes = [(prefix >> 4) as u8, ((prefix & 0xf) << 4) as u8];
let mut br = BitReader::new(&bytes);
let idx = hcod10_decode(&mut br).expect("12-bit prefix must decode");
let (len, cw) = hcod10_encode(idx).expect("decoded index must round-trip");
let lead = prefix >> (HCOD10_MAX_LEN - u32::from(len));
assert_eq!(
u32::from(cw),
lead,
"round-trip prefix={:#05x} idx={} len={} cw={:#x}",
prefix,
idx,
len,
cw
);
}
}
#[test]
fn hcod10_encode_index_0_is_six_bit_codeword_0x22() {
let (len, cw) = hcod10_encode(0).unwrap();
assert_eq!(len, 6);
assert_eq!(cw, 0x22);
}
#[test]
fn hcod10_encode_shortest_codewords_match_spec() {
assert_eq!(hcod10_encode(14).unwrap(), (4, 0x0));
assert_eq!(hcod10_encode(15).unwrap(), (4, 0x1));
assert_eq!(hcod10_encode(27).unwrap(), (4, 0x2));
}
#[test]
fn hcod10_encode_last_entry_matches_table() {
let (len, cw) = hcod10_encode(168).unwrap();
assert_eq!(len, 12);
assert_eq!(cw, 0xfff);
}
#[test]
fn hcod10_encode_eight_12_bit_rows_match_table() {
let expected = [
(12u32, 0x0ffdu16),
(129u32, 0x0ffau16),
(142u32, 0x0ff9u16),
(155u32, 0x0ffbu16),
(165u32, 0x0ff8u16),
(166u32, 0x0ffeu16),
(167u32, 0x0ffcu16),
(168u32, 0x0fffu16),
];
let observed: Vec<_> = HCOD10
.iter()
.enumerate()
.filter_map(|(i, &(l, cw))| if l == 12 { Some((i as u32, cw)) } else { None })
.collect();
assert_eq!(observed.len(), 8);
for (e, o) in expected.iter().zip(observed.iter()) {
assert_eq!(*e, *o, "expected {:?} got {:?}", e, o);
}
}
#[test]
fn hcod10_encode_rejects_out_of_range_index() {
assert!(matches!(
hcod10_encode(169),
Err(Error::SpectralCodebookIndexOutOfRange(10))
));
assert!(matches!(
hcod10_encode(0xffff_ffff),
Err(Error::SpectralCodebookIndexOutOfRange(10))
));
}
#[test]
fn hcod10_decode_four_bit_zero_codeword_yields_index_14() {
let bytes = [0b0000_1111u8];
let mut br = BitReader::new(&bytes);
let idx = hcod10_decode(&mut br).unwrap();
assert_eq!(idx, 14);
assert_eq!(br.bit_position(), 4);
}
#[test]
fn hcod10_decode_full_12_bit_codeword_round_trips_index_168() {
let bytes = [0xff, 0xf0];
let mut br = BitReader::new(&bytes);
let idx = hcod10_decode(&mut br).unwrap();
assert_eq!(idx, 168);
assert_eq!(br.bit_position(), 12);
}
#[test]
fn hcod10_decode_propagates_unexpected_end() {
let bytes: [u8; 0] = [];
let mut br = BitReader::new(&bytes);
assert_eq!(hcod10_decode(&mut br), Err(Error::UnexpectedEnd));
}
#[test]
fn hcod10_write_then_decode_round_trips_every_index() {
for idx in 0..HCOD10_NUM_ENTRIES as u32 {
let mut w = BitWriter::new();
hcod10_write(&mut w, idx).unwrap();
let (len, _) = hcod10_encode(idx).unwrap();
let mut w2 = w;
let pad = (8 - (u32::from(len) % 8)) % 8;
if pad > 0 {
w2.write_u32(0, pad);
}
let bytes = w2.into_bytes();
let mut br = BitReader::new(&bytes);
let decoded = hcod10_decode(&mut br).unwrap();
assert_eq!(
decoded, idx,
"round-trip mismatch at idx={} (encoded as {} bits)",
idx, len
);
}
}
#[test]
fn hcod10_write_rejects_out_of_range_index() {
let mut w = BitWriter::new();
assert!(matches!(
hcod10_write(&mut w, 169),
Err(Error::SpectralCodebookIndexOutOfRange(10))
));
}
#[test]
fn codebook_10_matches_codebook_9_universe_size() {
assert_eq!(HCOD9_NUM_ENTRIES, 169);
assert_eq!(HCOD10_NUM_ENTRIES, 169);
}
#[test]
fn codebook_10_ceiling_is_3_bits_below_codebook_9() {
assert_eq!(HCOD9_MAX_LEN, 15);
assert_eq!(HCOD10_MAX_LEN, 12);
assert_eq!(HCOD9_MAX_LEN - HCOD10_MAX_LEN, 3);
}
#[test]
fn codebook_10_lifts_zero_tuple_off_codebook_9_head_placement() {
let (l9_0, cw9_0) = hcod9_encode(0).unwrap();
let (l10_0, cw10_0) = hcod10_encode(0).unwrap();
let (l10_14, cw10_14) = hcod10_encode(14).unwrap();
assert_eq!((l9_0, cw9_0), (1, 0));
assert_eq!((l10_0, cw10_0), (6, 0x22));
assert_eq!((l10_14, cw10_14), (4, 0));
}
#[test]
fn codebook_10_far_corner_matches_codebook_9_far_corner_index() {
let (l9, cw9) = hcod9_encode(168).unwrap();
let (l10, cw10) = hcod10_encode(168).unwrap();
assert_eq!((l9, cw9), (15, 0x7fff));
assert_eq!((l10, cw10), (12, 0xfff));
}
#[test]
fn hcod11_has_exactly_289_entries() {
assert_eq!(HCOD11.len(), HCOD11_NUM_ENTRIES);
assert_eq!(HCOD11_NUM_ENTRIES, 289);
}
#[test]
fn hcod11_max_length_is_12_bits() {
let max = HCOD11.iter().map(|&(len, _)| len).max().unwrap();
assert_eq!(u32::from(max), HCOD11_MAX_LEN);
assert_eq!(HCOD11_MAX_LEN, 12);
}
#[test]
fn hcod11_min_length_is_four_bits_at_zero_tuple_and_interior_pair() {
let mut min: u32 = u32::MAX;
let mut min_indices: Vec<usize> = Vec::new();
for (idx, &(len, _)) in HCOD11.iter().enumerate() {
let l = u32::from(len);
if l < min {
min = l;
min_indices.clear();
min_indices.push(idx);
} else if l == min {
min_indices.push(idx);
}
}
assert_eq!(min, 4);
assert_eq!(min_indices, vec![0, 18]);
}
#[test]
fn hcod11_zero_tuple_lives_at_index_0_with_four_bit_codeword() {
let (len, cw) = HCOD11[0];
assert_eq!(len, 4);
assert_eq!(cw, 0x0000);
}
#[test]
fn hcod11_interior_one_one_tuple_lives_at_index_18_with_four_bit_codeword() {
let (len, cw) = HCOD11[18];
assert_eq!(len, 4);
assert_eq!(cw, 0x0001);
}
#[test]
fn hcod11_far_corner_lives_at_index_288_with_five_bit_codeword() {
let (len, cw) = HCOD11[288];
assert_eq!(len, 5);
assert_eq!(cw, 0x0004);
}
#[test]
fn hcod11_codewords_fit_their_declared_length() {
for (idx, &(len, cw)) in HCOD11.iter().enumerate() {
assert!(
u32::from(cw) < (1u32 << u32::from(len)),
"row {idx}: codeword 0x{cw:x} >= 2^{len}",
);
}
}
#[test]
fn hcod11_kraft_sum_is_two_to_the_twelve() {
let lmax = HCOD11_MAX_LEN;
let mut sum: u32 = 0;
for &(len, _) in &HCOD11 {
sum += 1u32 << (lmax - u32::from(len));
}
assert_eq!(sum, 1u32 << lmax);
assert_eq!(sum, 4096);
}
#[test]
fn hcod11_is_complete() {
for prefix in 0u32..(1u32 << HCOD11_MAX_LEN) {
let bytes = [((prefix >> 4) & 0xff) as u8, ((prefix & 0xf) << 4) as u8];
let mut br = BitReader::new(&bytes);
let idx = hcod11_decode(&mut br).expect("12-bit prefix must decode");
let (len, cw) = hcod11_encode(idx).expect("decoded index must round-trip");
let lead = prefix >> (HCOD11_MAX_LEN - u32::from(len));
assert_eq!(
lead,
u32::from(cw),
"prefix 0b{prefix:012b} decoded idx={idx} → codeword ({len}, 0x{cw:x})",
);
}
}
#[test]
fn hcod11_twelve_bit_ceiling_hits_exactly_six_indices() {
let ceiling: Vec<usize> = HCOD11
.iter()
.enumerate()
.filter_map(|(i, &(len, _))| if len == 12 { Some(i) } else { None })
.collect();
assert_eq!(ceiling, vec![12, 14, 15, 255, 269, 270]);
assert_eq!(HCOD11[12], (12, 0x0ffb));
assert_eq!(HCOD11[14], (12, 0x0ffa));
assert_eq!(HCOD11[15], (12, 0x0ffe));
assert_eq!(HCOD11[255], (12, 0x0ffd));
assert_eq!(HCOD11[269], (12, 0x0ffc));
assert_eq!(HCOD11[270], (12, 0x0fff));
}
#[test]
fn hcod11_half_esc_rows_match_spec() {
assert_eq!(HCOD11[16], (10, 0x038e));
assert_eq!(HCOD11[272], (9, 0x01c2));
}
#[test]
fn hcod11_encode_rejects_out_of_range_indices() {
for bad in [289u32, 290, 300, 1000, u32::MAX] {
assert!(matches!(
hcod11_encode(bad),
Err(Error::SpectralCodebookIndexOutOfRange(11))
));
}
}
#[test]
fn hcod11_write_rejects_out_of_range_indices() {
let mut w = BitWriter::new();
for bad in [289u32, 1000, u32::MAX] {
assert!(matches!(
hcod11_write(&mut w, bad),
Err(Error::SpectralCodebookIndexOutOfRange(11))
));
}
}
#[test]
fn hcod11_decode_index_0_zero_bits() {
let bytes = [0x00u8];
let mut br = BitReader::new(&bytes);
let idx = hcod11_decode(&mut br).unwrap();
assert_eq!(idx, 0);
assert_eq!(br.bit_position(), 4u64);
}
#[test]
fn hcod11_decode_index_270_full_12_bit_far_codeword() {
let bytes = [0xffu8, 0xf0];
let mut br = BitReader::new(&bytes);
let idx = hcod11_decode(&mut br).unwrap();
assert_eq!(idx, 270);
assert_eq!(br.bit_position(), 12u64);
}
#[test]
fn hcod11_writer_round_trip_pins_every_index() {
for idx in 0..HCOD11_NUM_ENTRIES as u32 {
let mut w = BitWriter::new();
hcod11_write(&mut w, idx).unwrap();
let (len, _) = hcod11_encode(idx).unwrap();
let pad = (8 - (u32::from(len) % 8)) % 8;
let mut w2 = w;
if pad > 0 {
w2.write_u32(0, pad);
}
let bytes = w2.into_bytes();
let mut br = BitReader::new(&bytes);
let got = hcod11_decode(&mut br).unwrap();
assert_eq!(got, idx, "round-trip mismatch at idx={idx}");
assert_eq!(
br.bit_position(),
u64::from(len),
"bit consumption mismatch at idx={idx}",
);
}
}
#[test]
fn hcod11_decoder_returns_unexpected_end_on_truncation() {
let bytes: [u8; 0] = [];
let mut br = BitReader::new(&bytes);
let err = hcod11_decode(&mut br).unwrap_err();
assert_eq!(err, Error::UnexpectedEnd);
}
#[test]
fn hcod11_max_len_constant_matches_table_data() {
let mut observed_max = 0u32;
for idx in 0..HCOD11_NUM_ENTRIES as u32 {
let (len, _) = hcod11_encode(idx).unwrap();
observed_max = observed_max.max(u32::from(len));
}
assert_eq!(observed_max, HCOD11_MAX_LEN);
}
#[test]
fn hcod11_ceiling_matches_codebook_10_ceiling() {
assert_eq!(HCOD10_MAX_LEN, HCOD11_MAX_LEN);
assert_eq!(HCOD11_MAX_LEN, 12);
}
#[test]
fn hcod11_universe_is_69_entries_wider_than_codebook_10() {
assert_eq!(HCOD11_NUM_ENTRIES - HCOD10_NUM_ENTRIES, 120);
assert_eq!(HCOD11_NUM_ENTRIES, 289);
assert_eq!(HCOD10_NUM_ENTRIES, 169);
}
}