pub fn fprec(mut x: f64, digits: usize) -> f64 {
let max10e = f64::MAX_10_EXP;
if x.is_nan() {
return x;
}
if !x.is_finite() {
return x;
}
if x == 0.0 {
return x;
}
let mut dig = digits as i32;
if dig > 22 {
return x;
} else if dig < 1 {
dig = 1
}
let mut sgn = 1.0;
if x < 0.0 {
sgn = -sgn;
x = -x
}
let l10 = x.log10();
let mut e10 = (dig - 1) - l10.floor() as i32;
if l10.abs() < max10e as f64 - 2.0 {
let mut p10 = 1.0;
if e10 > max10e {
p10 = 10.0_f64.powi(e10 - max10e);
e10 = max10e
}
if e10 > 0 {
let pow10 = 10.0_f64.powi(e10);
sgn * ((x * pow10 * p10).round() / pow10) / p10
} else {
let pow10 = 10.0_f64.powi(-e10);
sgn * ((x / pow10).round() * pow10)
}
} else {
let do_round = max10e as f64 - l10 >= 10.0_f64.powi(-dig);
let e2 = dig + (if e10 > 0 { 1 } else { -(1) }) * 22;
let p10 = 10.0_f64.powi(e2);
x *= p10;
let p_10 = 10.0_f64.powi(e10 - e2);
x *= p_10;
if do_round {
x += 0.5
}
x = x.floor() / p10;
sgn * x / p_10
}
}