2019-03-28 21:13:19 +00:00
|
|
|
use crate::base::intermediate_tuple;
|
2019-04-09 01:15:21 +00:00
|
|
|
use crate::matrix::OctetMatrix;
|
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-04-14 20:40:43 +00:00
|
|
|
use crate::systematic_constants::{calculate_p1, systematic_index};
|
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-04-09 01:15:21 +00:00
|
|
|
use crate::octets::{add_assign, fused_addassign_mul_scalar};
|
2019-01-27 05:35:43 +00:00
|
|
|
|
|
|
|
// 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_tuple: (u32, u32, u32, u32, u32, u32),
|
2019-04-14 20:40:43 +00:00
|
|
|
lt_symbols: u32,
|
|
|
|
pi_symbols: u32,
|
|
|
|
p1: u32
|
2019-03-28 21:13:19 +00:00
|
|
|
) -> Vec<usize> {
|
2019-04-14 20:40:43 +00:00
|
|
|
let w = lt_symbols;
|
|
|
|
let p = pi_symbols;
|
2019-01-27 05:35:43 +00:00
|
|
|
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);
|
|
|
|
|
2019-02-15 05:54:23 +00:00
|
|
|
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;
|
2019-02-15 05:54:23 +00:00
|
|
|
indices.push(b as usize);
|
2019-01-27 05:35:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
while b1 >= p {
|
|
|
|
b1 = (b1 + a1) % p1;
|
|
|
|
}
|
|
|
|
|
2019-02-15 05:54:23 +00:00
|
|
|
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;
|
|
|
|
}
|
2019-02-15 05:54:23 +00:00
|
|
|
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;
|
|
|
|
|
2019-02-18 18:34:43 +00:00
|
|
|
assert!(S + H + encoded_symbol_indices.len() >= L);
|
2019-04-07 22:31:00 +00:00
|
|
|
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-04-09 01:15:21 +00:00
|
|
|
|
|
|
|
// Generates the MT matrix
|
|
|
|
// See section 5.3.3.3
|
|
|
|
let mut mt: Vec<Vec<u8>> = vec![vec![0; Kprime + S]; H];
|
2019-01-27 05:35:43 +00:00
|
|
|
for i in 0..H {
|
2019-04-09 01:15:21 +00:00
|
|
|
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)
|
|
|
|
+ 1)
|
|
|
|
% (H as u32)) as usize
|
|
|
|
{
|
|
|
|
mt[i][j] = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
mt[i][Kprime + S - 1] = Octet::alpha(i as u8).byte();
|
|
|
|
}
|
|
|
|
// Multiply by the GAMMA matrix
|
|
|
|
// See section 5.3.3.3
|
|
|
|
let mut gamma_row = vec![0; Kprime + S];
|
|
|
|
// We only create the last row of the GAMMA matrix, as all preceding rows are just a shift left
|
|
|
|
for j in 0..(Kprime + S) {
|
|
|
|
gamma_row[j] = Octet::alpha((Kprime + S - 1 - j) as u8).byte();
|
|
|
|
}
|
|
|
|
for i in 0..H {
|
|
|
|
let mut result_row = vec![0; Kprime + S];
|
|
|
|
for j in 0..(Kprime + S) {
|
|
|
|
let scalar = Octet::new(mt[i][j]);
|
|
|
|
if scalar == Octet::zero() {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if scalar == Octet::one() {
|
|
|
|
add_assign(&mut result_row[0..=j], &gamma_row[(Kprime + S - j - 1)..(Kprime + S)]);
|
|
|
|
} else {
|
|
|
|
fused_addassign_mul_scalar( &mut result_row[0..=j], &gamma_row[(Kprime + S - j - 1)..(Kprime + S)], &scalar);
|
|
|
|
}
|
|
|
|
}
|
2019-01-27 05:35:43 +00:00
|
|
|
for j in 0..(Kprime + S) {
|
2019-04-09 01:15:21 +00:00
|
|
|
if result_row[j] != 0 {
|
|
|
|
matrix.set(i + S, j, Octet::new(result_row[j]));
|
2019-04-07 18:25:07 +00:00
|
|
|
}
|
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;
|
2019-04-14 20:40:43 +00:00
|
|
|
let lt_symbols = num_lt_symbols(Kprime as u32);
|
|
|
|
let pi_symbols = num_pi_symbols(Kprime as u32);
|
|
|
|
let sys_index = systematic_index(Kprime as u32);
|
|
|
|
let p1 = calculate_p1(Kprime as u32);
|
2019-02-18 18:34:43 +00:00
|
|
|
for &i in encoded_symbol_indices.iter() {
|
2019-01-29 01:17:05 +00:00
|
|
|
// row != i, because i is the ESI
|
2019-04-14 20:40:43 +00:00
|
|
|
let tuple = intermediate_tuple(i, lt_symbols, sys_index, p1);
|
2019-01-27 05:35:43 +00:00
|
|
|
|
2019-04-14 20:40:43 +00:00
|
|
|
for j in enc_indices(tuple, lt_symbols, pi_symbols, p1) {
|
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
|
|
|
}
|