pub fn decode_ms<T: DecodeFrom>(&self, llrs: &[T], output: &mut [u8],
                                    working: &mut [T], working_u8: &mut [u8],
                                    maxiters: usize)
        -> (bool, usize)
    {
        let n = self.n();
        let k = self.k();
        let p = self.punctured_bits();

        assert_eq!(llrs.len(), n, "llrs.len() != n");
        assert_eq!(output.len(), self.output_len(), "output.len() != (n+p)/8");
        assert_eq!(working.len(), self.decode_ms_working_len(), "working.len() incorrect");
        assert_eq!(working_u8.len(), self.decode_ms_working_u8_len(), "working_u8 != (n+p-k)/8");

        // Rename output to parities as we'll use it to keep track of the parity bits until the end
        let parities = output;

        // Rename working_u8 to ui_sgns, we'll use it to accumulate signs for each check
        let ui_sgns = working_u8;

        // Zero the working area and split it up
        for w in &mut working[..] { *w = T::zero() }
        let (u, working)        = working.split_at_mut(self.paritycheck_sum() as usize);
        let (v, working)        = working.split_at_mut(self.paritycheck_sum() as usize);
        let (va, working)       = working.split_at_mut(n + p);
        let (ui_min1, ui_min2)  = working.split_at_mut(n + p - k);

        for iter in 0..maxiters {
            // Initialise the marginals to the input LLRs (and to 0 for punctured bits)
            va[..llrs.len()].copy_from_slice(llrs);
            for x in &mut va[llrs.len()..] { *x = T::zero() }

            // You'd think .enumerate() would be sensible, but actually it prevents
            // inlining the iterator's next() method, which leads to a big performance hit.
            let mut idx = 0;
            for (check, var) in self.iter_paritychecks() {
                // Work out messages to this variable
                if v[idx].abs() == ui_min1[check] {
                    u[idx] = ui_min2[check];
                } else {
                    u[idx] = ui_min1[check];
                }
                if ui_sgns[check/8] >> (check%8) & 1 == 1 {
                    u[idx] = -u[idx];
                }
                if v[idx] < T::zero() {
                    u[idx] = -u[idx];
                }

                // Accumulate incoming messages to each variable
                va[var] = va[var].saturating_add(u[idx]);

                // DIY enumerate
                idx += 1;
            }

            for x in &mut ui_min1[..] { *x = T::maxval() }
            for x in &mut ui_min2[..] { *x = T::maxval() }
            for x in &mut ui_sgns[..] { *x = 0 }
            for x in &mut parities[..] { *x = 0 }
            idx = 0;
            for (check, var) in self.iter_paritychecks() {
                // Work out messages to this parity check
                let new_v_ai = va[var] - u[idx];
                if v[idx] != T::zero() && (new_v_ai >= T::zero()) != (v[idx] >= T::zero()) {
                    v[idx] = T::zero();
                } else {
                    v[idx] = new_v_ai;
                }

                // Accumulate two minimums
                if v[idx].abs() < ui_min1[check] {
                    ui_min2[check] = ui_min1[check];
                    ui_min1[check] = v[idx].abs();
                } else if v[idx].abs() < ui_min2[check] {
                    ui_min2[check] = v[idx].abs();
                }

                // Accumulate signs
                if v[idx] < T::zero() {
                    ui_sgns[check/8] ^= 1<<(check%8);
                }

                // Accumulate parity
                if va[var] <= T::zero() {
                    parities[check/8] ^= 1<<(check%8);
                }

                idx += 1;
            }

            // Check parities. If none are 1 then we have a valid codeword.
            if *parities.iter().max().unwrap() == 0 {
                // Hard decode marginals into the output
                let output = parities;
                for o in &mut output[..] { *o = 0 }
                for (var, &va) in va[0..(n+p)].iter().enumerate() {
                    if va <= T::zero() {
                        output[var/8] |= 1 << (7 - (var%8));
                    }
                }
                return (true, iter);
            }
        }

        // If we failed to find a codeword, at least hard decode the marginals into the output
        let output = parities;
        for o in &mut output[..] { *o = 0 }
        for (var, &va) in va[0..(n+p)].iter().enumerate() {
            if va <= T::zero() {
                output[var/8] |= 1 << (7 - (var%8));
            }
        }
        (false, maxiters)
    }
/// Message passing based min-sum decoder.
///
/// This algorithm is slower and requires more memory than the bit-flipping decode, but
/// operates on soft information and provides very close to optimal decoding. If you don't have
/// soft information, you can use `decode_hard_to_llrs` to go from hard information (bytes from
/// a receiver) to soft information (LLRs).
///
/// Requires:
///
/// * `llrs` must be `n` long, with positive numbers more likely to be a 0 bit.
/// * `output` must be allocated to (n+punctured_bits)/8 bytes, aka `output_len()`, of which
///   the first k/8 bytes will be set to the decoded message (and the rest to the parity bits
///   of the complete codeword)
/// * `working` is the main working area which must be provided and must have
///   `decode_ms_working_len()` elements, equal to
///   2*paritycheck_sum + 3*n + 3*punctured_bits - 2*k
/// * `working_u8` is the secondary working area which must be provided and must have
///   `decode_ms_working_u8_len()` elements, equal to (n + punctured_bits - k)/8.
///
/// Will run for at most `maxiters` iterations.
///
/// Returns decoding success and the number of iterations run for.
///
/// ## Log Likelihood Ratios and choice of `T`
///
/// The `llrs` input is a list of signed numbers, one per bit, where positive numbers mean
/// a bit is more likely to be 0, and larger magnitude numbers indicate increased confidence
/// on a logarithmic scale (so every step increase is a multiplication of the confidence).
///
/// This decoder is invariant to a linear scaling of all the LLRs (in other words, it is
/// invariant to the channel noise level), so you can choose any quantisation level and
/// fixed-point interpretation you desire. This means you can view `i8` as representing
/// the 256 numbers between -1 and +0.9921875, or as just representing -128 to +127.
///
/// Internally, variables of type `T` are used to accumulate messages, so it is useful to leave
/// some headroom in `T` after the range of your LLRs. For `T=i8` you might assign -32 to 31
/// for LLR inputs, so that several full-scale messages can be accumulated before saturation
/// occurs. On floating point types this is less of a concern.
///
/// This also means if you only have hard information it makes no practical difference what
/// exact value you give the LLRs, but in the interests of avoiding saturation you may as
/// well pick +-1 in any unit (and you may as well use i8 since the additional range will
/// not be of benefit).
Message passing based min-sum decoder.
This algorithm is slower and requires more memory than the bit-flipping decode, but
operates on soft information and provides very close to optimal decoding. If you don't have
soft information, you can use `decode_hard_to_llrs` to go from hard information (bytes from
a receiver) to soft information (LLRs).



`llrs` must be `n` long, with positive numbers more likely to be a 0 bit.

Will run for at most `maxiters` iterations.

Returns decoding success and the number of iterations run for.
Message passing based min - sum decoder . This algorithm is slower and requires more memory than the bit - flipping decode but operates on soft information and provides very close to optimal decoding . If you don ' t have soft information you can use ` decode_hard_to_llrs ` to go from hard information ( bytes from a receiver ) to soft information ( LLRs ) . ` llrs ` must be ` n ` long with positive numbers more likely to be a 0 bit . Will run for at most ` maxiters ` iterations . Returns decoding success and the number of iterations run for .
pub fn decode_ms<T: DecodeFrom>(&self, llrs: &[T], output: &mut [u8],
                                    working: &mut [T], working_u8: &mut [u8],
                                    maxiters: usize)
        -> (bool, usize)
    {
        let n = self.n();
        let k = self.k();
        let p = self.punctured_bits();
        assert_eq!(llrs.len(), n, "llrs.len() != n");
        assert_eq!(output.len(), self.output_len(), "output.len() != (n+p)/8");
        assert_eq!(working.len(), self.decode_ms_working_len(), "working.len() incorrect");
        assert_eq!(working_u8.len(), self.decode_ms_working_u8_len(), "working_u8 != (n+p-k)/8");
        // Rename output to parities as we'll use it to keep track of the parity bits until the end
        let parities = output;
        // Rename working_u8 to ui_sgns, we'll use it to accumulate signs for each check
        let ui_sgns = working_u8;
        // Zero the working area and split it up
        for w in &mut working[..] { *w = T::zero() }
        let (u, working)        = working.split_at_mut(self.paritycheck_sum() as usize);
        let (v, working)        = working.split_at_mut(self.paritycheck_sum() as usize);
        let (va, working)       = working.split_at_mut(n + p);
        let (ui_min1, ui_min2)  = working.split_at_mut(n + p - k);
        for iter in 0..maxiters {
            // Initialise the marginals to the input LLRs (and to 0 for punctured bits)
            va[..llrs.len()].copy_from_slice(llrs);
            for x in &mut va[llrs.len()..] { *x = T::zero() }
            // You'd think .enumerate() would be sensible, but actually it prevents
            // inlining the iterator's next() method, which leads to a big performance hit.
            let mut idx = 0;
            for (check, var) in self.iter_paritychecks() {
                // Work out messages to this variable
                if v[idx].abs() == ui_min1[check] {
                    u[idx] = ui_min2[check];
                } else {
                    u[idx] = ui_min1[check];
                }
                if ui_sgns[check/8] >> (check%8) & 1 == 1 {
                    u[idx] = -u[idx];
                }
                if v[idx] < T::zero() {
                    u[idx] = -u[idx];
                }
                // Accumulate incoming messages to each variable
                va[var] = va[var].saturating_add(u[idx]);
                // DIY enumerate
                idx += 1;
            }
            for x in &mut ui_min1[..] { *x = T::maxval() }
            for x in &mut ui_min2[..] { *x = T::maxval() }
            for x in &mut ui_sgns[..] { *x = 0 }
            for x in &mut parities[..] { *x = 0 }
            idx = 0;
            for (check, var) in self.iter_paritychecks() {
                // Work out messages to this parity check
                let new_v_ai = va[var] - u[idx];
                if v[idx] != T::zero() && (new_v_ai >= T::zero()) != (v[idx] >= T::zero()) {
                    v[idx] = T::zero();
                } else {
                    v[idx] = new_v_ai;
                }
                // Accumulate two minimums
                if v[idx].abs() < ui_min1[check] {
                    ui_min2[check] = ui_min1[check];
                    ui_min1[check] = v[idx].abs();
                } else if v[idx].abs() < ui_min2[check] {
                    ui_min2[check] = v[idx].abs();
                }
                // Accumulate signs
                if v[idx] < T::zero() {
                    ui_sgns[check/8] ^= 1<<(check%8);
                }
                // Accumulate parity
                if va[var] <= T::zero() {
                    parities[check/8] ^= 1<<(check%8);
                }
                idx += 1;
            }
            // Check parities. If none are 1 then we have a valid codeword.
            if *parities.iter().max().unwrap() == 0 {
                // Hard decode marginals into the output
                let output = parities;
                for o in &mut output[..] { *o = 0 }
                for (var, &va) in va[0..(n+p)].iter().enumerate() {
                    if va <= T::zero() {
                        output[var/8] |= 1 << (7 - (var%8));
                    }
                }
                return (true, iter);
            }
        }
        // If we failed to find a codeword, at least hard decode the marginals into the output
        let output = parities;
        for o in &mut output[..] { *o = 0 }
        for (var, &va) in va[0..(n+p)].iter().enumerate() {
            if va <= T::zero() {
                output[var/8] |= 1 << (7 - (var%8));
            }
        }
        (false, maxiters)
    }
pub fn decode_ms < T : DecodeFrom > ( & self , llrs : & [ T ] , output : & mut [ u8 ] , working : & mut [ T ] , working_u8 : & mut [ u8 ] , maxiters : usize ) -> ( bool , usize ) { let n = self . n ( ) ; let k = self . k ( ) ; let p = self . punctured_bits ( ) ; assert_eq ! ( llrs len ( ) n " " ) ; assert_eq ! ( output len ( ) self output_len ( ) " " ) ; assert_eq ! ( working len ( ) self decode_ms_working_len ( ) " " ) ; assert_eq ! ( working_u8 len ( ) self decode_ms_working_u8_len ( ) " " ) ; // Rename output to parities as we'll use it to keep track of the parity bits until the end let parities = output ; // Rename working_u8 to ui_sgns, we'll use it to accumulate signs for each check let ui_sgns = working_u8 ; // Zero the working area and split it up for w in & mut working [ .. ] { * w = T :: zero ( ) } let ( u , working ) = working . split_at_mut ( self . paritycheck_sum ( ) as usize ) ; let ( v , working ) = working . split_at_mut ( self . paritycheck_sum ( ) as usize ) ; let ( va , working ) = working . split_at_mut ( n + p ) ; let ( ui_min1 , ui_min2 ) = working . split_at_mut ( n + p - k ) ; for iter in 0 .. maxiters { // Initialise the marginals to the input LLRs (and to 0 for punctured bits) va [ .. llrs . len ( ) ] . copy_from_slice ( llrs ) ; for x in & mut va [ llrs . len ( ) .. ] { * x = T :: zero ( ) } // You'd think .enumerate() would be sensible, but actually it prevents // inlining the iterator's next() method, which leads to a big performance hit. let mut idx = 0 ; for ( check , var ) in self . iter_paritychecks ( ) { // Work out messages to this variable if v [ idx ] . abs ( ) == ui_min1 [ check ] { u [ idx ] = ui_min2 [ check ] ; } else { u [ idx ] = ui_min1 [ check ] ; } if ui_sgns [ check / 8 ] >> ( check % 8 ) & 1 == 1 { u [ idx ] = - u [ idx ] ; } if v [ idx ] < T :: zero ( ) { u [ idx ] = - u [ idx ] ; } // Accumulate incoming messages to each variable va [ var ] = va [ var ] . saturating_add ( u [ idx ] ) ; // DIY enumerate idx += 1 ; } for x in & mut ui_min1 [ .. ] { * x = T :: maxval ( ) } for x in & mut ui_min2 [ .. ] { * x = T :: maxval ( ) } for x in & mut ui_sgns [ .. ] { * x = 0 } for x in & mut parities [ .. ] { * x = 0 } idx = 0 ; for ( check , var ) in self . iter_paritychecks ( ) { // Work out messages to this parity check let new_v_ai = va [ var ] - u [ idx ] ; if v [ idx ] != T :: zero ( ) && ( new_v_ai >= T :: zero ( ) ) != ( v [ idx ] >= T :: zero ( ) ) { v [ idx ] = T :: zero ( ) ; } else { v [ idx ] = new_v_ai ; } // Accumulate two minimums if v [ idx ] . abs ( ) < ui_min1 [ check ] { ui_min2 [ check ] = ui_min1 [ check ] ; ui_min1 [ check ] = v [ idx ] . abs ( ) ; } else if v [ idx ] . abs ( ) < ui_min2 [ check ] { ui_min2 [ check ] = v [ idx ] . abs ( ) ; } // Accumulate signs if v [ idx ] < T :: zero ( ) { ui_sgns [ check / 8 ] ^= 1 << ( check % 8 ) ; } // Accumulate parity if va [ var ] <= T :: zero ( ) { parities [ check / 8 ] ^= 1 << ( check % 8 ) ; } idx += 1 ; } // Check parities. If none are 1 then we have a valid codeword. if * parities . iter ( ) . max ( ) . unwrap ( ) == 0 { // Hard decode marginals into the output let output = parities ; for o in & mut output [ .. ] { * o = 0 } for ( var , & va ) in va [ 0 .. ( n + p ) ] . iter ( ) . enumerate ( ) { if va <= T :: zero ( ) { output [ var / 8 ] |= 1 << ( 7 - ( var % 8 ) ) ; } } return ( true , iter ) ; } } // If we failed to find a codeword, at least hard decode the marginals into the output let output = parities ; for o in & mut output [ .. ] { * o = 0 } for ( var , & va ) in va [ 0 .. ( n + p ) ] . iter ( ) . enumerate ( ) { if va <= T :: zero ( ) { output [ var / 8 ] |= 1 << ( 7 - ( var % 8 ) ) ; } } ( false , maxiters ) }
Message passing based min-sum decoder.
Message passing based min - sum decoder .
&self
llrs
&[T]
output
&mut [u8]
working
&mut [T]
working_u8
&mut [u8]
maxiters
usize
log likelihood ratios and choice of `t`
The `llrs` input is a list of signed numbers, one per bit, where positive numbers mean
a bit is more likely to be 0, and larger magnitude numbers indicate increased confidence
on a logarithmic scale (so every step increase is a multiplication of the confidence).

This decoder is invariant to a linear scaling of all the LLRs (in other words, it is
invariant to the channel noise level), so you can choose any quantisation level and
fixed-point interpretation you desire. This means you can view `i8` as representing
the 256 numbers between -1 and +0.9921875, or as just representing -128 to +127.

Internally, variables of type `T` are used to accumulate messages, so it is useful to leave
some headroom in `T` after the range of your LLRs. For `T=i8` you might assign -32 to 31
for LLR inputs, so that several full-scale messages can be accumulated before saturation
occurs. On floating point types this is less of a concern.

This also means if you only have hard information it makes no practical difference what
exact value you give the LLRs, but in the interests of avoiding saturation you may as
well pick +-1 in any unit (and you may as well use i8 since the additional range will
not be of benefit).
The ` llrs ` input is a list of signed numbers one per bit where positive numbers mean a bit is more likely to be 0 and larger magnitude numbers indicate increased confidence on a logarithmic scale ( so every step increase is a multiplication of the confidence ) . This decoder is invariant to a linear scaling of all the LLRs ( in other words it is invariant to the channel noise level ) so you can choose any quantisation level and fixed - point interpretation you desire . This means you can view ` i8 ` as representing the 256 numbers between - 1 and + 0 . 9921875 or as just representing - 128 to + 127 . Internally variables of type ` T ` are used to accumulate messages so it is useful to leave some headroom in ` T ` after the range of your LLRs . For ` T = i8 ` you might assign - 32 to 31 for LLR inputs so that several full - scale messages can be accumulated before saturation occurs . On floating point types this is less of a concern . This also means if you only have hard information it makes no practical difference what exact value you give the LLRs but in the interests of avoiding saturation you may as well pick + - 1 in any unit ( and you may as well use i8 since the additional range will not be of benefit ) .