use super::ScalarFxP;
use core::ops::Add;
use fixed::types::extra::{LeEqU16, LeEqU32, Sum, Unsigned, U16};
use fixed::{traits::Fixed, FixedI32};
pub trait Fixed16: Fixed {
const ONE_OR_MAX: Self = if let Some(val) = Self::TRY_ONE {
val
} else {
Self::MAX
};
fn multiply_fixed(self, rhs: Self) -> Self;
fn scale_fixed(self, rhs: ScalarFxP) -> Self;
type Widened: Fixed;
fn widen(self) -> Self::Widened;
fn widened_from_bits(bits: i32) -> Self::Widened;
}
impl<N> Fixed16 for fixed::FixedI16<N>
where
N: Unsigned + LeEqU16 + LeEqU32 + Add<N> + Add<U16>,
Sum<N, N>: Unsigned + LeEqU32,
Sum<N, U16>: Unsigned + LeEqU32,
{
fn multiply_fixed(self, rhs: Self) -> Self {
Self::from_num(self.wide_mul(rhs))
}
fn scale_fixed(self, rhs: ScalarFxP) -> Self {
Self::from_num(self.wide_mul_unsigned(rhs))
}
type Widened = FixedI32<Self::Frac>;
fn widen(self) -> FixedI32<Self::Frac> {
FixedI32::<Self::Frac>::from_num(self)
}
fn widened_from_bits(bits: i32) -> Self::Widened {
Self::Widened::from_bits(bits)
}
}
impl<N> Fixed16 for fixed::FixedU16<N>
where
N: Unsigned + LeEqU16 + LeEqU32 + Add<N> + Add<U16>,
Sum<N, N>: Unsigned + LeEqU32,
Sum<N, U16>: Unsigned + LeEqU32,
{
fn multiply_fixed(self, rhs: Self) -> Self {
Self::from_num(self.wide_mul(rhs))
}
fn scale_fixed(self, rhs: ScalarFxP) -> Self {
Self::from_num(self.wide_mul(rhs))
}
type Widened = FixedI32<Self::Frac>;
fn widen(self) -> FixedI32<Self::Frac> {
FixedI32::<Self::Frac>::from_num(self)
}
fn widened_from_bits(bits: i32) -> Self::Widened {
Self::Widened::from_bits(bits)
}
}