1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
//! LDPC decoder with horizontal layered schedule.
//!
//! This module implements a generice belief propagation LDPC decoder with a
//! serial, per check node (horizontal layered) schedule as described in [An
//! Efficient Message-Passing Schedule for LDPC
//! Decoding](https://www.eng.biu.ac.il/~goldbej/papers/engisrael.pdf), by
//! E. Sharon, S. Litsyn, and J. Goldberg.

use super::{
    arithmetic::DecoderArithmetic, check_llrs, hard_decisions, DecoderOutput, LdpcDecoder,
    SentMessages,
};
use crate::sparse::SparseMatrix;

/// LDPC belief propagation horizontal layered decoder.
#[derive(Debug, Clone, PartialEq)]
pub struct Decoder<A: DecoderArithmetic> {
    arithmetic: A,
    h: SparseMatrix,
    llrs: Box<[A::VarLlr]>,                        // Qv
    check_messages: SentMessages<A::CheckMessage>, // Rcv
}

impl<A: DecoderArithmetic> Decoder<A> {
    /// Creates a new horizontal layered LDPC decoder.
    ///
    /// The parameter `h` indicates the parity check matrix.
    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,
        }
    }

    /// Decodes a codeword.
    ///
    /// The parameters are the LLRs for the received codeword and the maximum
    /// number of iterations to perform. If decoding is successful, the function
    /// returns an `Ok` containing the (hard decision) on the decoded codeword
    /// and the number of iterations used in decoding. If decoding is not
    /// successful, the function returns an `Err` containing the hard decision
    /// on the final decoder LLRs (which still has some bit errors) and the
    /// number of iterations used in decoding (which is equal to
    /// `max_iterations`).
    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) {
            // No bit errors case
            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))
            }) {
                // Decode succeeded
                return Ok(DecoderOutput {
                    codeword: hard_decisions(&self.llrs, |x| {
                        self.arithmetic
                            .llr_hard_decision(self.arithmetic.var_llr_to_llr(x))
                    }),
                    iterations: iteration,
                });
            }
        }
        // Decode failed
        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]) {
        // Initialize Qv to input LLRs.
        for (x, &y) in self.llrs.iter_mut().zip(llrs.iter()) {
            *x = self
                .arithmetic
                .llr_to_var_llr(self.arithmetic.input_llr_quantize(y))
        }
        // Initialize Rcv to zero.
        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)
    }
}