pub fn factorial(n: usize) -> f64 {
rising_factorial(1f64, n)
}
fn rising_factorial(z: f64, n: usize) -> f64 {
let m = (n as f64).sqrt().floor().min(60f64) as usize;
let mut k = 0usize;
let mut r = 1f64;
while k < n {
let l = m.min(n - k);
let t = (k..k + l).fold(1f64, |acc, i| acc * (z + i as f64));
r *= t;
k += m;
}
r
}
pub fn frexp(x: f64) -> (f64, i32) {
if x == 0.0 {
return (0.0, 0);
}
let bits = x.to_bits();
let sign = if (bits >> 63) != 0 { -1.0 } else { 1.0 };
let exponent = ((bits >> 52) & 0x7ff) as i32 - 1023;
let mantissa = sign * f64::from_bits((bits & 0xfffffffffffff) | 0x3fe0000000000000);
(mantissa, exponent + 1)
}
pub fn ldexp(x: f64, exp: i32) -> f64 {
if x == 0.0 || exp == 0 {
return x;
}
let bits = x.to_bits();
let exponent = ((bits >> 52) & 0x7ff) as i32;
let new_exponent = exponent + exp;
if !(0..=0x7ff).contains(&new_exponent) {
return if (bits >> 63) != 0 {
f64::NEG_INFINITY
} else {
f64::INFINITY
};
}
let result_bits = (bits & 0x800fffffffffffff) | ((new_exponent as u64) << 52);
f64::from_bits(result_bits)
}
pub fn sign(a: f64, b: f64) -> f64 {
if b.is_sign_positive() {
a.abs()
} else {
-(a.abs())
}
}
pub(crate) fn polynomial<I>(x: f64, coefficients: I) -> f64
where
I: IntoIterator<Item = f64>,
{
coefficients
.into_iter()
.fold(0.0, |acc, coeff| mul_add(acc, x, coeff))
}
fn mul_add(x: f64, mul: f64, add: f64) -> f64 {
#[cfg(not(target_feature = "fma"))]
{
x * mul + add
}
#[cfg(target_feature = "fma")]
{
x.mul_add(mul, add)
}
}