use super::bhcomp::*;
use super::cached::*;
use super::errors::*;
use super::float::ExtendedFloat;
use super::num::*;
use super::small_powers::*;
pub(crate) fn fast_path<F>(mantissa: u64, exponent: i32) -> Option<F>
where
F: Float,
{
let (min_exp, max_exp) = F::exponent_limit();
let shift_exp = F::mantissa_limit();
let mantissa_size = F::MANTISSA_SIZE + 1;
if mantissa == 0 {
Some(F::ZERO)
} else if mantissa >> mantissa_size != 0 {
None
} else if exponent == 0 {
let float = F::as_cast(mantissa);
Some(float)
} else if exponent >= min_exp && exponent <= max_exp {
let float = F::as_cast(mantissa);
Some(float.pow10(exponent))
} else if exponent >= 0 && exponent <= max_exp + shift_exp {
let small_powers = POW10_64;
let shift = exponent - max_exp;
let power = small_powers[shift as usize];
let value = match mantissa.checked_mul(power) {
None => return None,
Some(value) => value,
};
if value >> mantissa_size != 0 {
None
} else {
let float = F::as_cast(value);
Some(float.pow10(max_exp))
}
} else {
None
}
}
fn multiply_exponent_extended<F>(fp: &mut ExtendedFloat, exponent: i32, truncated: bool) -> bool
where
F: Float,
{
let powers = ExtendedFloat::get_powers();
let exponent = exponent.saturating_add(powers.bias);
let small_index = exponent % powers.step;
let large_index = exponent / powers.step;
if exponent < 0 {
fp.mant = 0;
true
} else if large_index as usize >= powers.large.len() {
fp.mant = 1 << 63;
fp.exp = 0x7FF;
true
} else {
let mut errors: u32 = 0;
if truncated {
errors += u64::error_halfscale();
}
match fp
.mant
.overflowing_mul(powers.get_small_int(small_index as usize))
{
(_, true) => {
fp.normalize();
fp.imul(&powers.get_small(small_index as usize));
errors += u64::error_halfscale();
}
(mant, false) => {
fp.mant = mant;
fp.normalize();
}
}
fp.imul(&powers.get_large(large_index as usize));
if errors > 0 {
errors += 1;
}
errors += u64::error_halfscale();
let shift = fp.normalize();
errors <<= shift;
u64::error_is_accurate::<F>(errors, fp)
}
}
#[inline]
pub(crate) fn moderate_path<F>(
mantissa: u64,
exponent: i32,
truncated: bool,
) -> (ExtendedFloat, bool)
where
F: Float,
{
let mut fp = ExtendedFloat {
mant: mantissa,
exp: 0,
};
let valid = multiply_exponent_extended::<F>(&mut fp, exponent, truncated);
(fp, valid)
}
pub(crate) fn fallback_path<F>(
integer: &[u8],
fraction: &[u8],
mantissa: u64,
exponent: i32,
mantissa_exponent: i32,
truncated: bool,
) -> F
where
F: Float,
{
let (fp, valid) = moderate_path::<F>(mantissa, mantissa_exponent, truncated);
if valid {
return fp.into_float::<F>();
}
let b = fp.into_downward_float::<F>();
if b.is_special() {
b
} else {
bhcomp(b, integer, fraction, exponent)
}
}