use crate::error::Result;
use crate::rng::SimRng;
use crate::signal::{Bits, Llr, Signal, Symbols};
use crate::units::Hertz;
pub trait Encode {
fn rate(&self) -> f64;
fn encode_into(&self, info: &Bits, out: &mut Bits) -> Result<()>;
fn encode(&self, info: &Bits) -> Result<Bits> {
let mut out = Bits::default();
self.encode_into(info, &mut out)?;
Ok(out)
}
}
pub trait Decode {
fn decode_into(&mut self, llr: &Llr, out: &mut Bits) -> Result<()>;
fn decode(&mut self, llr: &Llr) -> Result<Bits> {
let mut out = Bits::default();
self.decode_into(llr, &mut out)?;
Ok(out)
}
}
pub trait Map {
fn map_into(&self, bits: &Bits, out: &mut Symbols) -> Result<()>;
fn map(&self, bits: &Bits) -> Result<Symbols> {
let mut out = Symbols::default();
self.map_into(bits, &mut out)?;
Ok(out)
}
}
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
pub enum Jacobian {
#[default]
Exact,
MaxLog,
}
impl Jacobian {
pub fn from_max_log(max_log: bool) -> Jacobian {
if max_log { Jacobian::MaxLog } else { Jacobian::Exact }
}
pub fn is_exact(self) -> bool {
self == Jacobian::Exact
}
}
#[derive(Clone, Copy, Debug, Default, PartialEq)]
pub struct Demapping<'a> {
pub log_priors: Option<&'a [f64]>,
pub jacobian: Jacobian,
}
pub trait Demap {
fn demap_with_into(&self, y: &Symbols, noise_var: f64, demapping: Demapping<'_>, out: &mut Llr) -> Result<()>;
fn demap_into(&self, y: &Symbols, noise_var: f64, out: &mut Llr) -> Result<()> {
self.demap_with_into(y, noise_var, Demapping::default(), out)
}
fn demap_with(&self, y: &Symbols, noise_var: f64, demapping: Demapping<'_>) -> Result<Llr> {
let mut out = Llr::default();
self.demap_with_into(y, noise_var, demapping, &mut out)?;
Ok(out)
}
fn demap(&self, y: &Symbols, noise_var: f64) -> Result<Llr> {
let mut out = Llr::default();
self.demap_into(y, noise_var, &mut out)?;
Ok(out)
}
}
pub trait Modulate<In = Symbols> {
fn modulate_into(&self, x: &In, out: &mut Signal) -> Result<()>;
fn modulate(&self, x: &In) -> Result<Signal> {
let mut out = Signal::zeros(0, 0, Hertz(1.0));
self.modulate_into(x, &mut out)?;
Ok(out)
}
}
pub trait Demodulate<Out = Symbols> {
fn demodulate_into(&mut self, y: &Signal, out: &mut Out) -> Result<()>;
fn demodulate(&mut self, y: &Signal) -> Result<Out>
where
Out: Default,
{
let mut out = Out::default();
self.demodulate_into(y, &mut out)?;
Ok(out)
}
}
pub trait Precode {
fn precode_into(&self, x: &Symbols, out: &mut Symbols) -> Result<()>;
}
pub trait Detect {
fn detect_into(&mut self, y: &Symbols, noise_var: f64, out: &mut Symbols) -> Result<()>;
}
pub trait Propagate {
fn propagate_into(&mut self, x: &Signal, rng: &mut SimRng, out: &mut Signal) -> Result<()>;
fn propagate(&mut self, x: &Signal, rng: &mut SimRng) -> Result<Signal> {
let mut out = Signal::zeros(0, 0, x.sample_rate());
self.propagate_into(x, rng, &mut out)?;
Ok(out)
}
}
pub trait Impair {
fn impair_into(&mut self, x: &Signal, rng: &mut SimRng, out: &mut Signal) -> Result<()>;
fn impair(&mut self, x: &Signal, rng: &mut SimRng) -> Result<Signal> {
let mut out = Signal::zeros(0, 0, x.sample_rate());
self.impair_into(x, rng, &mut out)?;
Ok(out)
}
}