ldpc_toolbox/decoder/
horizontal_layered.rs1use super::{
10 DecoderOutput, LdpcDecoder, SentMessages, arithmetic::DecoderArithmetic, check_llrs,
11 hard_decisions,
12};
13use crate::sparse::SparseMatrix;
14
15#[derive(Debug, Clone, PartialEq)]
17pub struct Decoder<A: DecoderArithmetic> {
18 arithmetic: A,
19 h: SparseMatrix,
20 llrs: Box<[A::VarLlr]>, check_messages: SentMessages<A::CheckMessage>, }
23
24impl<A: DecoderArithmetic> Decoder<A> {
25 pub fn new(h: SparseMatrix, arithmetic: A) -> Self {
29 let llrs = vec![Default::default(); h.num_cols()].into_boxed_slice();
30 let check_messages = SentMessages::from_iter((0..h.num_rows()).map(|r| h.iter_row(r)));
31 Decoder {
32 arithmetic,
33 h,
34 llrs,
35 check_messages,
36 }
37 }
38
39 pub fn decode(
50 &mut self,
51 llrs: &[f64],
52 max_iterations: usize,
53 ) -> Result<DecoderOutput, DecoderOutput> {
54 assert_eq!(llrs.len(), self.llrs.len());
55 let input_llrs_hard_decision = |x| x <= 0.0;
56 if check_llrs(&self.h, llrs, input_llrs_hard_decision) {
57 return Ok(DecoderOutput {
59 codeword: hard_decisions(llrs, input_llrs_hard_decision),
60 iterations: 0,
61 });
62 }
63 self.initialize(llrs);
64 for iteration in 1..=max_iterations {
65 self.process_check_nodes();
66 if check_llrs(&self.h, &self.llrs, |x| {
67 self.arithmetic
68 .llr_hard_decision(self.arithmetic.var_llr_to_llr(x))
69 }) {
70 return Ok(DecoderOutput {
72 codeword: hard_decisions(&self.llrs, |x| {
73 self.arithmetic
74 .llr_hard_decision(self.arithmetic.var_llr_to_llr(x))
75 }),
76 iterations: iteration,
77 });
78 }
79 }
80 Err(DecoderOutput {
82 codeword: hard_decisions(&self.llrs, |x| {
83 self.arithmetic
84 .llr_hard_decision(self.arithmetic.var_llr_to_llr(x))
85 }),
86 iterations: max_iterations,
87 })
88 }
89
90 fn initialize(&mut self, llrs: &[f64]) {
91 for (x, &y) in self.llrs.iter_mut().zip(llrs.iter()) {
93 *x = self
94 .arithmetic
95 .llr_to_var_llr(self.arithmetic.input_llr_quantize(y))
96 }
97 for x in self.check_messages.per_source.iter_mut() {
99 for msg in x.iter_mut() {
100 msg.value = A::CheckMessage::default();
101 }
102 }
103 }
104
105 fn process_check_nodes(&mut self) {
106 for messages in self.check_messages.per_source.iter_mut() {
107 self.arithmetic
108 .update_check_messages_and_vars(messages, &mut self.llrs);
109 }
110 }
111}
112
113impl<A: DecoderArithmetic> LdpcDecoder for Decoder<A> {
114 fn decode(
115 &mut self,
116 llrs: &[f64],
117 max_iterations: usize,
118 ) -> Result<DecoderOutput, DecoderOutput> {
119 Decoder::decode(self, llrs, max_iterations)
120 }
121}