use crate::dyadic_float::{DyadicSign, f64_from_parts};
#[inline]
pub(crate) fn ldexp(d: f64, i: i32) -> f64 {
let mut n = i;
let exp_max = 1023;
let exp_min = -1022;
const EXP_BIAS: u64 = (1u64 << (11 - 1u64)) - 1u64;
let f_exp_max = f64_from_parts(DyadicSign::Pos, EXP_BIAS << 1, 0);
let f_exp_min = f64_from_parts(DyadicSign::Pos, 1, 0);
let mut x = d;
if n < exp_min {
let f_pow_subnorm = f64_from_parts(DyadicSign::Pos, 52 + EXP_BIAS, 0);
let mul = f_exp_min * f_pow_subnorm;
let add = -exp_min - 52i32;
debug_assert!(-exp_min + 52i32 + exp_max <= add * 2 + -exp_min);
x *= mul;
n += add;
if n < exp_min {
x *= mul;
n += add;
if n < exp_min {
n = exp_min;
}
}
} else if n > exp_max {
x *= f_exp_max;
n -= exp_max;
if n > exp_max {
x *= f_exp_max;
n -= exp_max;
if n > exp_max {
n = exp_max;
}
}
}
let scale = f64_from_parts(DyadicSign::Pos, (EXP_BIAS as i32 + n) as u64, 0);
x * scale
}
#[inline]
pub(crate) fn fast_ldexp(d: f64, i: i32) -> f64 {
let mut u = d.to_bits();
u = u.wrapping_add((i as u64).wrapping_shl(52));
f64::from_bits(u)
}