use core::ops::{Rem, RemAssign};
use crate::{UInt, Fp, util};
use super::super::as_lossless;
impl<U: UInt, const SIGN_BIT: bool, const EXP_SIZE: usize, const INT_SIZE: usize, const FRAC_SIZE: usize, const EXP_BASE: usize> Rem<Self> for Fp<U, SIGN_BIT, EXP_SIZE, INT_SIZE, FRAC_SIZE, EXP_BASE>
where
[(); util::bitsize_of::<U>() - SIGN_BIT as usize - EXP_SIZE - INT_SIZE - FRAC_SIZE]:,
[(); EXP_BASE - 2]:
{
type Output = Self;
fn rem(self, rhs: Self) -> Self::Output
{
as_lossless!(
[self, rhs],
|[lhs, rhs]| [lhs % rhs],
{
if self.is_nan() || rhs.is_nan()
{
return self + rhs;
}
if self.is_infinite() || rhs.is_zero()
{
return Self::snan()
}
let fa = self.abs();
let fb = rhs.abs();
if fa < fb
{
return self
}
let mut dividend = fa;
let expo_a = fa.exp_bits();
let mut frac_b = fb.frac_bits();
if !Self::IS_INT_IMPLICIT
{
frac_b = frac_b + (fb.int_bits() << Self::INT_POS)
}
let mut divisor = Self::from_bits(Self::shift_exp(expo_a) + Self::shift_frac(frac_b));
while divisor < dividend.divb()
{
divisor = divisor.mulb();
}
while divisor >= fb && !divisor.is_zero() && divisor.is_finite()
{
while dividend >= divisor
{
dividend -= divisor;
}
divisor = divisor.divb();
}
assert!(dividend.is_finite());
dividend.copysign(self)
}
)
}
}
impl<U: UInt, const SIGN_BIT: bool, const EXP_SIZE: usize, const INT_SIZE: usize, const FRAC_SIZE: usize, const EXP_BASE: usize> RemAssign for Fp<U, SIGN_BIT, EXP_SIZE, INT_SIZE, FRAC_SIZE, EXP_BASE>
where
[(); util::bitsize_of::<U>() - SIGN_BIT as usize - EXP_SIZE - INT_SIZE - FRAC_SIZE]:,
[(); EXP_BASE - 2]:
{
#[inline]
fn rem_assign(&mut self, rhs: Self)
{
*self = *self % rhs
}
}
#[cfg(test)]
mod test
{
use std::ops::Rem;
use test::Bencher;
use crate::tests::{self, F};
#[test]
fn test_rem()
{
crate::tests::test_op2("rem", Rem::rem, Rem::rem, None)
}
#[bench]
fn bench_rem(bencher: &mut Bencher)
{
test_rem();
tests::bench_op2::<F, _>(bencher, Rem::rem)
}
}