use std::ops::Rem;
use num_traits::Float;
use strafe_consts::LOG10_2;
use crate::traits::DPQ;
pub fn fround(mut x: f64, digits: isize) -> f64 {
let max_digits = f64::MAX_10_EXP as usize + f64::DIGITS as usize;
let max10e = f64::MAX_10_EXP;
if x.is_nan() {
return f64::nan();
}
if !x.is_finite() {
return x;
}
if digits as usize > max_digits || x == 0.0 {
return x;
} else if digits < -max10e as isize {
return 0.;
} else if digits == 0 {
return x.round();
}
let mut sgn = 1.0;
if x < 0.0 {
sgn = -1.0;
x = -x;
} let l10x = LOG10_2 * (0.5 + x.log2()); if l10x as u32 + digits as u32 > f64::DIGITS {
return sgn * x;
} else {
let pow10;
let x10;
let i10;
let xd;
let xu; if digits <= max10e as isize {
pow10 = 10.0.pow_di(digits);
x10 = x * pow10;
i10 = x10.floor();
xd = i10 / pow10;
xu = x10.ceil() / pow10;
} else {
let e10 = digits - max10e as isize; let p10 = 10.0.pow_di(e10);
pow10 = 10.0.pow_di(max10e as isize);
x10 = (x * pow10) * p10;
i10 = x10.floor();
xd = i10 / pow10 / p10;
xu = x10.ceil() / pow10 / p10;
}
let du = xu - x;
let dd = x - xd;
return sgn
* if du < dd || (i10.rem(2.0) == 1.0 && du == dd) {
xu
} else {
xd
};
}
}