///|
/// IEEE 802.11 LDPC: only n=1944, rate=3/4, z=81. Information bits
/// occupy coordinates 0..1457; parity follows. Not a complete Wi-Fi PHY.
pub struct WifiLdpc1944R34 {
priv code : ParityCheck
} derive(Debug)
///|
/// Matrix transcribed by ishmal/ldpc802-js, cross-checked with tavildar/LDPC.
/// Exact revisions, attribution and limitations: docs/wifi-compatibility.md.
fn wifi_1944_r34_base() -> Array[Array[Int32]] {
[
[
48, 29, 28, 39, 9, 61, -1, -1, -1, 63, 45, 80, -1, -1, -1, 37, 32, 22, 1, 0,
-1, -1, -1, -1,
],
[
4, 49, 42, 48, 11, 30, -1, -1, -1, 49, 17, 41, 37, 15, -1, 54, -1, -1, -1,
0, 0, -1, -1, -1,
],
[
35, 76, 78, 51, 37, 35, 21, -1, 17, 64, -1, -1, -1, 59, 7, -1, -1, 32, -1,
-1, 0, 0, -1, -1,
],
[
9, 65, 44, 9, 54, 56, 73, 34, 42, -1, -1, -1, 35, -1, -1, -1, 46, 39, 0, -1,
-1, 0, 0, -1,
],
[
3, 62, 7, 80, 68, 26, -1, 80, 55, -1, 36, -1, 26, -1, 9, -1, 72, -1, -1, -1,
-1, -1, 0, 0,
],
[
26, 75, 33, 21, 69, 59, 3, 38, -1, -1, -1, 35, -1, 62, 36, 26, -1, -1, 1, -1,
-1, -1, -1, 0,
],
]
}
///|
pub fn WifiLdpc1944R34::new() -> WifiLdpc1944R34 raise CodeError {
{ code: lift_qc(wifi_1944_r34_base(), 81), }
}
///|
pub fn WifiLdpc1944R34::parity_check(self : WifiLdpc1944R34) -> ParityCheck {
self.code
}
///|
/// Solve the fixed parity staircase directly over GF(2), without dense RREF.
/// XORing all six block equations cancels p1..p5 and both shifted p0
/// terms, leaving p0 = XOR of the six information syndromes.
pub fn WifiLdpc1944R34::encode(
self : WifiLdpc1944R34,
information : Array[Int32],
) -> Array[Int32] raise CodeError {
ensure_bits(information, 1458)
let word = Array::make(1944, 0)
for i, bit in information {
word[i] = bit
}
let syndromes = Array::makei(486, fn(r) {
let mut bit = 0
for col in self.code.rows[r] {
if col < 1458 {
bit = bit ^ information[col]
}
}
bit
})
for i in 0..<81 {
let mut bit = 0
for block in 0..<6 {
bit = bit ^ syndromes[block * 81 + i]
}
word[1458 + i] = bit
}
// Each of the first five block rows has one unsolved identity block.
for block in 0..<5 {
for i in 0..<81 {
let row = block * 81 + i
let target = 1458 + (block + 1) * 81 + i
let mut bit = syndromes[row]
for col in self.code.rows[row] {
if col >= 1458 && col != target {
bit = bit ^ word[col]
}
}
word[target] = bit
}
}
if !self.code.is_codeword(word) {
raise Inconsistent("Wi-Fi profile parity construction")
}
word
}
///|
/// Check the full codeword before returning its leading information bits.
pub fn WifiLdpc1944R34::extract(
self : WifiLdpc1944R34,
word : Array[Int32],
) -> Array[Int32] raise CodeError {
if !self.code.is_codeword(word) {
raise Inconsistent("nonzero Wi-Fi syndrome")
}
Array::makei(1458, fn(i) { word[i] })
}
///|
pub extend WifiLdpc1944R34 with @debug.Debug::{to_repr}