#![doc(hidden)]
use crate::extended_float::ExtendedFloat;
use crate::mask::{lower_n_halfway, lower_n_mask};
use crate::num::Float;
#[cfg_attr(not(feature = "compact"), inline)]
pub fn round<F, Cb>(fp: &mut ExtendedFloat, cb: Cb)
where
F: Float,
Cb: Fn(&mut ExtendedFloat, i32),
{
let fp_inf = ExtendedFloat {
mant: 0,
exp: F::INFINITE_POWER,
};
let mantissa_shift = 64 - F::MANTISSA_SIZE - 1;
if -fp.exp >= mantissa_shift {
let shift = -fp.exp + 1;
debug_assert!(shift <= 65);
cb(fp, shift.min(64));
fp.exp = (fp.mant >= F::HIDDEN_BIT_MASK) as i32;
return;
}
cb(fp, mantissa_shift);
let carry_mask = F::CARRY_MASK;
if fp.mant & carry_mask == carry_mask {
fp.mant >>= 1;
fp.exp += 1;
}
if fp.exp >= F::INFINITE_POWER {
*fp = fp_inf;
return;
}
fp.mant &= F::MANTISSA_MASK;
}
#[cfg_attr(not(feature = "compact"), inline)]
pub fn round_nearest_tie_even<Cb>(fp: &mut ExtendedFloat, shift: i32, cb: Cb)
where
Cb: Fn(bool, bool, bool) -> bool,
{
debug_assert!(shift <= 64);
let mask = lower_n_mask(shift as u64);
let halfway = lower_n_halfway(shift as u64);
let truncated_bits = fp.mant & mask;
let is_above = truncated_bits > halfway;
let is_halfway = truncated_bits == halfway;
fp.mant = match shift == 64 {
true => 0,
false => fp.mant >> shift,
};
fp.exp += shift;
let is_odd = fp.mant & 1 == 1;
fp.mant += cb(is_odd, is_halfway, is_above) as u64;
}
#[cfg_attr(not(feature = "compact"), inline)]
pub fn round_down(fp: &mut ExtendedFloat, shift: i32) {
fp.mant = match shift == 64 {
true => 0,
false => fp.mant >> shift,
};
fp.exp += shift;
}