raptorq/src/constraint_matrix.rs

162 lines
4.5 KiB
Rust
Raw Normal View History

2019-03-28 21:13:19 +00:00
use crate::base::intermediate_tuple;
2019-04-06 04:18:25 +00:00
use crate::matrix::{OctetMatrix, DenseOctetMatrix};
2019-03-28 21:13:19 +00:00
use crate::octet::Octet;
2019-03-23 01:25:07 +00:00
use crate::rng::rand;
2019-03-28 21:13:19 +00:00
use crate::systematic_constants::calculate_p1;
2019-03-23 01:25:07 +00:00
use crate::systematic_constants::extended_source_block_symbols;
use crate::systematic_constants::num_hdpc_symbols;
2019-03-28 21:13:19 +00:00
use crate::systematic_constants::num_intermediate_symbols;
2019-03-23 01:25:07 +00:00
use crate::systematic_constants::num_ldpc_symbols;
use crate::systematic_constants::num_lt_symbols;
2019-03-28 21:13:19 +00:00
use crate::systematic_constants::num_pi_symbols;
2019-01-27 05:35:43 +00:00
// Generates the GAMMA matrix
// See section 5.3.3.3
#[allow(non_snake_case)]
2019-04-06 04:18:25 +00:00
fn generate_gamma(Kprime: usize, S: usize) -> DenseOctetMatrix {
2019-01-27 05:35:43 +00:00
let size = Kprime + S;
let mut matrix = DenseOctetMatrix::new(size, size, 0);
2019-01-27 05:35:43 +00:00
for i in 0..size {
for j in 0..=i {
matrix.set(i, j, Octet::alpha((i - j) as u8));
}
}
matrix
}
// Generates the MT matrix
// See section 5.3.3.3
#[allow(non_snake_case)]
2019-04-06 04:18:25 +00:00
fn generate_mt(H: usize, Kprime: usize, S: usize) -> DenseOctetMatrix {
let mut matrix = DenseOctetMatrix::new(H, Kprime + S, 0);
2019-01-27 05:35:43 +00:00
for i in 0..H {
for j in 0..=(Kprime + S - 2) {
if i == rand((j + 1) as u32, 6u32, H as u32) as usize
|| i == ((rand((j + 1) as u32, 6u32, H as u32)
+ rand((j + 1) as u32, 7u32, (H - 1) as u32)
2019-03-28 21:13:19 +00:00
+ 1)
% (H as u32)) as usize
{
2019-02-08 03:06:08 +00:00
matrix.set(i, j, Octet::one());
2019-01-27 05:35:43 +00:00
}
}
matrix.set(i, Kprime + S - 1, Octet::alpha(i as u8));
}
matrix
}
// Simulates Enc[] function to get indices of accessed intermediate symbols, as defined in section 5.3.5.3
2019-03-28 21:13:19 +00:00
pub fn enc_indices(
source_block_symbols: u32,
source_tuple: (u32, u32, u32, u32, u32, u32),
) -> Vec<usize> {
2019-01-27 05:35:43 +00:00
let w = num_lt_symbols(source_block_symbols);
let p = num_pi_symbols(source_block_symbols);
let p1 = calculate_p1(source_block_symbols);
let (d, a, mut b, d1, a1, mut b1) = source_tuple;
assert!(1 <= a && a < w);
assert!(b < w);
assert!(d1 == 2 || d1 == 3);
assert!(1 <= a1 && a < w);
assert!(b1 < w);
let mut indices = Vec::with_capacity((d + d1) as usize);
indices.push(b as usize);
2019-01-27 05:35:43 +00:00
2019-01-27 06:13:26 +00:00
for _ in 1..d {
2019-01-27 05:35:43 +00:00
b = (b + a) % w;
indices.push(b as usize);
2019-01-27 05:35:43 +00:00
}
while b1 >= p {
b1 = (b1 + a1) % p1;
}
indices.push((w + b1) as usize);
2019-01-27 05:35:43 +00:00
2019-01-27 06:13:26 +00:00
for _ in 1..d1 {
2019-01-27 05:35:43 +00:00
b1 = (b1 + a1) % p1;
while b1 >= p {
b1 = (b1 + a1) % p1;
}
indices.push((w + b1) as usize);
2019-01-27 05:35:43 +00:00
}
indices
}
2019-01-27 03:16:07 +00:00
// See section 5.3.3.4.2
#[allow(non_snake_case)]
2019-04-06 04:18:25 +00:00
pub fn generate_constraint_matrix<T: OctetMatrix>(
2019-03-28 21:13:19 +00:00
source_block_symbols: u32,
encoded_symbol_indices: &[u32],
2019-04-06 04:18:25 +00:00
) -> T {
2019-01-27 05:35:43 +00:00
let Kprime = extended_source_block_symbols(source_block_symbols) as usize;
let S = num_ldpc_symbols(source_block_symbols) as usize;
let H = num_hdpc_symbols(source_block_symbols) as usize;
let W = num_lt_symbols(source_block_symbols) as usize;
let B = W - S;
let P = num_pi_symbols(source_block_symbols) as usize;
let L = num_intermediate_symbols(source_block_symbols) as usize;
assert!(S + H + encoded_symbol_indices.len() >= L);
let mut matrix = T::new(S + H + encoded_symbol_indices.len(), L, P);
2019-01-27 05:35:43 +00:00
// G_LDPC,1
// See section 5.3.3.3
for i in 0..B {
let a = 1 + i / S;
let b = i % S;
2019-02-08 03:06:08 +00:00
matrix.set(b, i, Octet::one());
2019-01-27 05:35:43 +00:00
let b = (b + a) % S;
2019-02-08 03:06:08 +00:00
matrix.set(b, i, Octet::one());
2019-01-27 05:35:43 +00:00
let b = (b + a) % S;
2019-02-08 03:06:08 +00:00
matrix.set(b, i, Octet::one());
2019-01-27 05:35:43 +00:00
}
// I_S
for i in 0..S {
2019-02-08 03:06:08 +00:00
matrix.set(i as usize, i + B as usize, Octet::one());
2019-01-27 05:35:43 +00:00
}
// G_LDPC,2
// See section 5.3.3.3
for i in 0..S {
2019-02-08 03:06:08 +00:00
matrix.set(i, (i % P) + W, Octet::one());
matrix.set(i, ((i + 1) % P) + W, Octet::one());
2019-01-27 05:35:43 +00:00
}
// G_HDPC
2019-02-14 05:39:35 +00:00
let g_hdpc = &generate_mt(H, Kprime, S) * &generate_gamma(Kprime, S);
2019-01-27 05:35:43 +00:00
for i in 0..H {
for j in 0..(Kprime + S) {
if g_hdpc.get(i, j) != Octet::zero() {
matrix.set(i + S, j, g_hdpc.get(i, j));
}
2019-01-27 05:35:43 +00:00
}
}
// I_H
for i in 0..H {
2019-02-08 03:06:08 +00:00
matrix.set(i + S as usize, i + (Kprime + S) as usize, Octet::one());
2019-01-27 05:35:43 +00:00
}
// G_ENC
2019-01-29 01:17:05 +00:00
let mut row = 0;
for &i in encoded_symbol_indices.iter() {
2019-01-29 01:17:05 +00:00
// row != i, because i is the ESI
let tuple = intermediate_tuple(Kprime as u32, i);
2019-01-27 05:35:43 +00:00
for j in enc_indices(Kprime as u32, tuple) {
2019-02-08 03:06:08 +00:00
matrix.set(row as usize + S + H, j, Octet::one());
2019-01-27 05:35:43 +00:00
}
2019-01-29 01:17:05 +00:00
row += 1;
2019-01-27 05:35:43 +00:00
}
2019-01-27 03:16:07 +00:00
2019-01-27 05:35:43 +00:00
matrix
2019-01-27 03:16:07 +00:00
}