use crate::codecs::g729::impls::dsp::arith::extract_h;
use crate::codecs::g729::impls::dsp::types::{DspContext, Word16, Word32, MAX_32, MIN_32};
use super::{l_add, l_mac, l_msu, l_mult, l_sub};
#[inline(always)]
pub fn mac_r(ctx: &mut DspContext, l_var3: Word32, var1: Word16, var2: Word16) -> Word16 {
let l = l_mac(ctx, l_var3, var1, var2);
let l = l_add(ctx, l, Word32(0x0000_8000));
extract_h(l)
}
#[inline(always)]
pub fn msu_r(ctx: &mut DspContext, l_var3: Word32, var1: Word16, var2: Word16) -> Word16 {
let l = l_msu(ctx, l_var3, var1, var2);
let l = l_add(ctx, l, Word32(0x0000_8000));
extract_h(l)
}
#[inline(always)]
pub fn l_abs(_ctx: &mut DspContext, l_var1: Word32) -> Word32 {
if l_var1.0 == MIN_32 {
Word32(MAX_32)
} else if l_var1.0 < 0 {
Word32(-l_var1.0)
} else {
l_var1
}
}
#[inline(always)]
pub fn l_sat(ctx: &mut DspContext, l_var1: Word32) -> Word32 {
let mut out = l_var1;
if ctx.overflow {
if ctx.carry {
out = Word32(MIN_32);
} else {
out = Word32(MAX_32);
}
ctx.carry = false;
ctx.overflow = false;
}
out
}
#[allow(non_snake_case)]
#[inline(always)]
pub fn L_mult(ctx: &mut DspContext, var1: Word16, var2: Word16) -> Word32 {
l_mult(ctx, var1, var2)
}
#[allow(non_snake_case)]
#[inline(always)]
pub fn L_add(ctx: &mut DspContext, l_var1: Word32, l_var2: Word32) -> Word32 {
l_add(ctx, l_var1, l_var2)
}
#[allow(non_snake_case)]
#[inline(always)]
pub fn L_sub(ctx: &mut DspContext, l_var1: Word32, l_var2: Word32) -> Word32 {
l_sub(ctx, l_var1, l_var2)
}
#[allow(non_snake_case)]
#[inline(always)]
pub fn L_mac(ctx: &mut DspContext, l_var3: Word32, var1: Word16, var2: Word16) -> Word32 {
l_mac(ctx, l_var3, var1, var2)
}
#[allow(non_snake_case)]
#[inline(always)]
pub fn L_msu(ctx: &mut DspContext, l_var3: Word32, var1: Word16, var2: Word16) -> Word32 {
l_msu(ctx, l_var3, var1, var2)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn dsp_l_add_overflow_sets_flag() {
let mut ctx = DspContext::default();
let _ = l_add(&mut ctx, Word32(MAX_32), Word32(1));
assert!(ctx.overflow);
}
#[test]
fn dsp_l_mult_min_min_saturates() {
let mut ctx = DspContext::default();
let r = l_mult(&mut ctx, Word16(i16::MIN), Word16(i16::MIN));
assert_eq!(r.0, MAX_32);
assert!(ctx.overflow);
}
#[test]
fn dsp_l_add_c_carry_paths() {
let mut ctx = DspContext {
overflow: false,
carry: true,
};
let _ = super::super::l_add_c(&mut ctx, Word32(MAX_32), Word32(0));
assert!(ctx.overflow);
}
}