use super::{
DecoderOutput, LdpcDecoder, SentMessages, arithmetic::DecoderArithmetic, check_llrs,
hard_decisions,
};
use crate::sparse::SparseMatrix;
#[derive(Debug, Clone, PartialEq)]
pub struct Decoder<A: DecoderArithmetic> {
arithmetic: A,
h: SparseMatrix,
llrs: Box<[A::VarLlr]>, check_messages: SentMessages<A::CheckMessage>, }
impl<A: DecoderArithmetic> Decoder<A> {
pub fn new(h: SparseMatrix, arithmetic: A) -> Self {
let llrs = vec![Default::default(); h.num_cols()].into_boxed_slice();
let check_messages = SentMessages::from_iter((0..h.num_rows()).map(|r| h.iter_row(r)));
Decoder {
arithmetic,
h,
llrs,
check_messages,
}
}
pub fn decode(
&mut self,
llrs: &[f64],
max_iterations: usize,
) -> Result<DecoderOutput, DecoderOutput> {
assert_eq!(llrs.len(), self.llrs.len());
let input_llrs_hard_decision = |x| x <= 0.0;
if check_llrs(&self.h, llrs, input_llrs_hard_decision) {
return Ok(DecoderOutput {
codeword: hard_decisions(llrs, input_llrs_hard_decision),
iterations: 0,
});
}
self.initialize(llrs);
for iteration in 1..=max_iterations {
self.process_check_nodes();
if check_llrs(&self.h, &self.llrs, |x| {
self.arithmetic
.llr_hard_decision(self.arithmetic.var_llr_to_llr(x))
}) {
return Ok(DecoderOutput {
codeword: hard_decisions(&self.llrs, |x| {
self.arithmetic
.llr_hard_decision(self.arithmetic.var_llr_to_llr(x))
}),
iterations: iteration,
});
}
}
Err(DecoderOutput {
codeword: hard_decisions(&self.llrs, |x| {
self.arithmetic
.llr_hard_decision(self.arithmetic.var_llr_to_llr(x))
}),
iterations: max_iterations,
})
}
fn initialize(&mut self, llrs: &[f64]) {
for (x, &y) in self.llrs.iter_mut().zip(llrs.iter()) {
*x = self
.arithmetic
.llr_to_var_llr(self.arithmetic.input_llr_quantize(y))
}
for x in self.check_messages.per_source.iter_mut() {
for msg in x.iter_mut() {
msg.value = A::CheckMessage::default();
}
}
}
fn process_check_nodes(&mut self) {
for messages in self.check_messages.per_source.iter_mut() {
self.arithmetic
.update_check_messages_and_vars(messages, &mut self.llrs);
}
}
}
impl<A: DecoderArithmetic> LdpcDecoder for Decoder<A> {
fn decode(
&mut self,
llrs: &[f64],
max_iterations: usize,
) -> Result<DecoderOutput, DecoderOutput> {
Decoder::decode(self, llrs, max_iterations)
}
}