fn decode_erasures(&self, codeword: &mut [u8], working: &mut [u8], maxiters: usize)
        -> (bool, usize)
    {
        assert_eq!(codeword.len(), self.output_len());
        assert_eq!(working.len(), self.decode_bf_working_len());

        let n = self.n();
        let p = self.punctured_bits();

        // Working area:
        // * The top bit 0x80 for byte 'i' is the parity bit for check 'i'.
        // * The second and third top bits 0x60 for byte 'i' indicate the number of erased
        //   variables connected to check 'i':
        //   00 for no erasures, 01 for a single erasure, 11 for more than one erasure
        // * The fourth top bit 0x10 for byte 'a' indicates whether variable 'a' is erased
        // * The lowest four bits 0x0F for byte 'a' indicate the votes received for variable 'a',
        //   starting at 8 for 0 votes and being incremented and decremented from there.

        // Initialse working area: mark all punctured bits as erased
        for w in &mut working[..n] { *w = 0x00 }
        for w in &mut working[n..] { *w = 0x10 }

        // Also write all the punctured bits in the codeword to zero
        for c in &mut codeword[n/8..] { *c = 0x00 }

        // Keep track of how many bits we've fixed
        let mut bits_fixed = 0;

        for iter in 0..maxiters {
            // Initialise parity and erasure counts to zero, reset votes, preserve erasure bit
            for w in &mut working[..] { *w = (*w & 0x10) | 0x08 }

            // Compute check parity and erasure count
            for (check, var) in self.iter_paritychecks() {
                if working[var] & 0x10 == 0x10 {
                    // If var is erased, update check erasure count
                    match working[check] & 0x60 {
                        0x00 => working[check] |= 0x20,
                        0x20 => working[check] |= 0x40,
                        _    => (),
                    }
                } else if codeword[var/8] >> (7-(var%8)) & 1 == 1 {
                    // If var is not erased and this codeword bit is set, update check parity
                    working[check] ^= 0x80;
                }
            }

            // Now accumulate votes for each erased variable
            for (check, var) in self.iter_paritychecks() {
                // If this variable is erased and this check has only one vote
                if working[var] & 0x10 == 0x10 && working[check] & 0x60 == 0x20 {
                    // Vote +1 if our parity is currently 1, -1 otherwise
                    if working[check] & 0x80 == 0x80 {
                        working[var] += 1;
                    } else {
                        working[var] -= 1;
                    }
                }
            }

            // Finally fix all bits that are erased and have a majority vote
            for (var, working) in working[0..(n+p)].iter_mut().enumerate() {
                if *working & 0x10 == 0x10 {
                    if *working & 0x0F > 0x08 {
                        codeword[var/8] |= 1<<(7-(var%8));
                        *working &= !0x10;
                    }
                    bits_fixed += 1;
                }
            }

            if bits_fixed == p {
                // Hurray we're done
                return (true, iter)
            }
        }

        // If we finished the iteration loop then we did not succeed.
        (false, maxiters)
    }
/// Hard erasure decoding algorithm.
///
/// Used to preprocess punctured codes before attempting bit-flipping decoding,
/// as the bit-flipping algorithm cannot handle erasures.
///
/// The algorithm is:
///     * We compute the parity of each check over all non-erased bits
///     * We count how many erased bits are connected to each check (0, 1, or "more than 1")
///     * Then each parity check with exactly one erased variable casts a vote for
///       that variable, +1 if check parity is 1, otherwise -1
///     * Each variable that receives a majority vote (i.e. not equal 0) is set to that
///       vote and marked decoded
///     * Iterate until all variables are decoded or we reach the iteration limit
///
/// This is based on the paper:
/// Novel multi-Gbps bit-flipping decoders for punctured LDPC codes,
/// by Archonta, Kanistras, and Paliouras, MOCAST 2016.
///
/// * `codeword` must be (n+p)/8 long (`self.output_len()`), with the first n/8 bytes already
///   set to the received hard information, and the punctured bits at the end will be updated.
/// * `working` must be (n+p) bytes long (`self.decode_bf_working_len()`).
///
/// Returns `(success, number of iterations run)`. Success only indicates that every punctured
/// bit got a majority vote; but they might still be wrong; likewise failure means not every
/// bit got a vote but many may still have been determined correctly.
Hard erasure decoding algorithm.
Used to preprocess punctured codes before attempting bit-flipping decoding,
as the bit-flipping algorithm cannot handle erasures.

The algorithm is:
We compute the parity of each check over all non-erased bits
We count how many erased bits are connected to each check (0, 1, or "more than 1")
Then each parity check with exactly one erased variable casts a vote for
that variable, +1 if check parity is 1, otherwise -1
Each variable that receives a majority vote  is set to that
vote and marked decoded
Iterate until all variables are decoded or we reach the iteration limit

This is based on the paper:
Novel multi-Gbps bit-flipping decoders for punctured LDPC codes,
by Archonta, Kanistras, and Paliouras, MOCAST 2016.

`codeword` must be (n+p)/8 long (`self.output_len()`), with the first n/8 bytes already
set to the received hard information, and the punctured bits at the end will be updated.
`working` must be (n+p) bytes long (`self.decode_bf_working_len()`).

Returns `(success, number of iterations run)`. Success only indicates that every punctured
bit got a majority vote; but they might still be wrong; likewise failure means not every
bit got a vote but many may still have been determined correctly.
Hard erasure decoding algorithm . Used to preprocess punctured codes before attempting bit - flipping decoding as the bit - flipping algorithm cannot handle erasures . The algorithm is : We compute the parity of each check over all non - erased bits We count how many erased bits are connected to each check ( 0 1 or " more than 1 " ) Then each parity check with exactly one erased variable casts a vote for that variable + 1 if check parity is 1 otherwise - 1 Each variable that receives a majority vote is set to that vote and marked decoded Iterate until all variables are decoded or we reach the iteration limit This is based on the paper : Novel multi - Gbps bit - flipping decoders for punctured LDPC codes by Archonta Kanistras and Paliouras MOCAST 2016 . ` codeword ` must be ( n + p ) / 8 long ( ` self . output_len () ` ) with the first n / 8 bytes already set to the received hard information and the punctured bits at the end will be updated . ` working ` must be ( n + p ) bytes long ( ` self . decode_bf_working_len () ` ) . Returns ` ( success number of iterations run ) ` . Success only indicates that every punctured bit got a majority vote ; but they might still be wrong ; likewise failure means not every bit got a vote but many may still have been determined correctly .
fn decode_erasures(&self, codeword: &mut [u8], working: &mut [u8], maxiters: usize)
        -> (bool, usize)
    {
        assert_eq!(codeword.len(), self.output_len());
        assert_eq!(working.len(), self.decode_bf_working_len());
        let n = self.n();
        let p = self.punctured_bits();
        // Working area:
        // * The top bit 0x80 for byte 'i' is the parity bit for check 'i'.
        // * The second and third top bits 0x60 for byte 'i' indicate the number of erased
        //   variables connected to check 'i':
        //   00 for no erasures, 01 for a single erasure, 11 for more than one erasure
        // * The fourth top bit 0x10 for byte 'a' indicates whether variable 'a' is erased
        // * The lowest four bits 0x0F for byte 'a' indicate the votes received for variable 'a',
        //   starting at 8 for 0 votes and being incremented and decremented from there.
        // Initialse working area: mark all punctured bits as erased
        for w in &mut working[..n] { *w = 0x00 }
        for w in &mut working[n..] { *w = 0x10 }
        // Also write all the punctured bits in the codeword to zero
        for c in &mut codeword[n/8..] { *c = 0x00 }
        // Keep track of how many bits we've fixed
        let mut bits_fixed = 0;
        for iter in 0..maxiters {
            // Initialise parity and erasure counts to zero, reset votes, preserve erasure bit
            for w in &mut working[..] { *w = (*w & 0x10) | 0x08 }
            // Compute check parity and erasure count
            for (check, var) in self.iter_paritychecks() {
                if working[var] & 0x10 == 0x10 {
                    // If var is erased, update check erasure count
                    match working[check] & 0x60 {
                        0x00 => working[check] |= 0x20,
                        0x20 => working[check] |= 0x40,
                        _    => (),
                    }
                } else if codeword[var/8] >> (7-(var%8)) & 1 == 1 {
                    // If var is not erased and this codeword bit is set, update check parity
                    working[check] ^= 0x80;
                }
            }
            // Now accumulate votes for each erased variable
            for (check, var) in self.iter_paritychecks() {
                // If this variable is erased and this check has only one vote
                if working[var] & 0x10 == 0x10 && working[check] & 0x60 == 0x20 {
                    // Vote +1 if our parity is currently 1, -1 otherwise
                    if working[check] & 0x80 == 0x80 {
                        working[var] += 1;
                    } else {
                        working[var] -= 1;
                    }
                }
            }
            // Finally fix all bits that are erased and have a majority vote
            for (var, working) in working[0..(n+p)].iter_mut().enumerate() {
                if *working & 0x10 == 0x10 {
                    if *working & 0x0F > 0x08 {
                        codeword[var/8] |= 1<<(7-(var%8));
                        *working &= !0x10;
                    }
                    bits_fixed += 1;
                }
            }
            if bits_fixed == p {
                // Hurray we're done
                return (true, iter)
            }
        }
        // If we finished the iteration loop then we did not succeed.
        (false, maxiters)
    }
fn decode_erasures ( & self , codeword : & mut [ u8 ] , working : & mut [ u8 ] , maxiters : usize ) -> ( bool , usize ) { assert_eq ! ( codeword len ( ) self output_len ( ) ) ; assert_eq ! ( working len ( ) self decode_bf_working_len ( ) ) ; let n = self . n ( ) ; let p = self . punctured_bits ( ) ; // Working area: // * The top bit 0x80 for byte 'i' is the parity bit for check 'i'. // * The second and third top bits 0x60 for byte 'i' indicate the number of erased //   variables connected to check 'i': //   00 for no erasures, 01 for a single erasure, 11 for more than one erasure // * The fourth top bit 0x10 for byte 'a' indicates whether variable 'a' is erased // * The lowest four bits 0x0F for byte 'a' indicate the votes received for variable 'a', //   starting at 8 for 0 votes and being incremented and decremented from there. // Initialse working area: mark all punctured bits as erased for w in & mut working [ .. n ] { * w = 0x00 } for w in & mut working [ n .. ] { * w = 0x10 } // Also write all the punctured bits in the codeword to zero for c in & mut codeword [ n / 8 .. ] { * c = 0x00 } // Keep track of how many bits we've fixed let mut bits_fixed = 0 ; for iter in 0 .. maxiters { // Initialise parity and erasure counts to zero, reset votes, preserve erasure bit for w in & mut working [ .. ] { * w = ( * w & 0x10 ) | 0x08 } // Compute check parity and erasure count for ( check , var ) in self . iter_paritychecks ( ) { if working [ var ] & 0x10 == 0x10 { // If var is erased, update check erasure count match working [ check ] & 0x60 { 0x00 => working [ check ] |= 0x20 , 0x20 => working [ check ] |= 0x40 , _ => ( ) , } } else if codeword [ var / 8 ] >> ( 7 - ( var % 8 ) ) & 1 == 1 { // If var is not erased and this codeword bit is set, update check parity working [ check ] ^= 0x80 ; } } // Now accumulate votes for each erased variable for ( check , var ) in self . iter_paritychecks ( ) { // If this variable is erased and this check has only one vote if working [ var ] & 0x10 == 0x10 && working [ check ] & 0x60 == 0x20 { // Vote +1 if our parity is currently 1, -1 otherwise if working [ check ] & 0x80 == 0x80 { working [ var ] += 1 ; } else { working [ var ] -= 1 ; } } } // Finally fix all bits that are erased and have a majority vote for ( var , working ) in working [ 0 .. ( n + p ) ] . iter_mut ( ) . enumerate ( ) { if * working & 0x10 == 0x10 { if * working & 0x0F > 0x08 { codeword [ var / 8 ] |= 1 << ( 7 - ( var % 8 ) ) ; * working &= ! 0x10 ; } bits_fixed += 1 ; } } if bits_fixed == p { // Hurray we're done return ( true , iter ) } } // If we finished the iteration loop then we did not succeed. ( false , maxiters ) }
Hard erasure decoding algorithm.
Hard erasure decoding algorithm .
&self
codeword
&mut [u8]
working
&mut [u8]
maxiters
usize