use crate::sparse::SparseMatrix;
pub mod arithmetic;
pub mod factory;
pub mod flooding;
pub mod horizontal_layered;
pub trait LdpcDecoder: std::fmt::Debug + Send {
fn decode(
&mut self,
llrs: &[f64],
max_iterations: usize,
) -> Result<DecoderOutput, DecoderOutput>;
}
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
pub struct DecoderOutput {
pub codeword: Vec<u8>,
pub iterations: usize,
}
#[derive(Debug, Copy, Clone, Eq, PartialEq, Default, Hash)]
pub struct Message<T> {
pub source: usize,
pub value: T,
}
#[derive(Debug, Copy, Clone, Eq, PartialEq, Default, Hash)]
pub struct SentMessage<T> {
pub dest: usize,
pub value: T,
}
#[derive(Debug, Clone, Eq, PartialEq, Default, Hash)]
struct Messages<T> {
per_destination: Box<[Box<[Message<T>]>]>,
}
impl<T: Default> Messages<T> {
fn from_iter<I, J, B>(iter: I) -> Messages<T>
where
I: Iterator<Item = J>,
J: Iterator<Item = B>,
B: core::borrow::Borrow<usize>,
{
Messages {
per_destination: iter
.map(|i| {
i.map(|j| Message {
source: *j.borrow(),
value: T::default(),
})
.collect::<Vec<_>>()
.into_boxed_slice()
})
.collect::<Vec<_>>()
.into_boxed_slice(),
}
}
fn send(&mut self, source: usize, destination: usize, value: T) {
let message = self.per_destination[destination]
.iter_mut()
.find(|m| m.source == source)
.expect("message for source not found");
message.value = value;
}
}
#[derive(Debug, Clone, Eq, PartialEq, Default, Hash)]
struct SentMessages<T> {
per_source: Box<[Box<[SentMessage<T>]>]>,
}
impl<T: Default> SentMessages<T> {
fn from_iter<I, J, B>(iter: I) -> SentMessages<T>
where
I: Iterator<Item = J>,
J: Iterator<Item = B>,
B: core::borrow::Borrow<usize>,
{
SentMessages {
per_source: iter
.map(|i| {
i.map(|j| SentMessage {
dest: *j.borrow(),
value: T::default(),
})
.collect::<Vec<_>>()
.into_boxed_slice()
})
.collect::<Vec<_>>()
.into_boxed_slice(),
}
}
#[allow(dead_code)]
fn send(&mut self, source: usize, destination: usize, value: T) {
let message = self.per_source[source]
.iter_mut()
.find(|m| m.dest == destination)
.expect("message for destination not found");
message.value = value;
}
}
fn check_llrs<T, F>(h: &SparseMatrix, llrs: &[T], hard_decision: F) -> bool
where
T: Copy,
F: Fn(T) -> bool,
{
!(0..h.num_rows()).any(|r| h.iter_row(r).filter(|&&c| hard_decision(llrs[c])).count() % 2 == 1)
}
fn hard_decisions<T, F>(llrs: &[T], hard_decision: F) -> Vec<u8>
where
T: Copy,
F: Fn(T) -> bool,
{
llrs.iter()
.map(|&llr| u8::from(hard_decision(llr)))
.collect()
}