use super::exp::approx_exp;
use super::log::approx_ln;
use super::Float512;
use crate::{abs_bits, f256, BinEncSpecial};
const ONE_THIRD: Float512 = Float512::new(
1,
-2,
&[
0x55555555555555555555555555555555_u128,
0x55555555555555555555555555555555_u128,
0x55555555555555555555555555555555_u128,
0x55555555555555555555555555555556_u128,
],
);
impl f256 {
#[must_use]
pub fn cbrt(self) -> Self {
let abs_bits = abs_bits(&self);
if abs_bits.is_special() || abs_bits == Self::ONE.bits {
return self;
}
let x = Float512::from(&self);
let mut r = approx_exp(&(ONE_THIRD * approx_ln(&x.abs())));
r.copy_sign(&x);
Self::from(&r)
}
}
#[cfg(test)]
mod cbrt_tests {
use super::*;
use crate::big_uint::U256;
use crate::fast_mul;
use core::str::FromStr;
#[test]
fn test_special_values() {
assert!(f256::NAN.cbrt().is_nan());
for val in [
f256::NEG_INFINITY,
f256::NEG_ONE,
f256::NEG_ZERO,
f256::ZERO,
f256::ONE,
f256::INFINITY,
] {
assert_eq!(val.cbrt(), val);
}
}
#[test]
fn test_exact_cubes() {
let f = f256::from(343);
assert_eq!(f.cbrt(), f256::from(7));
let f = f256::from(27) / f256::from(8);
assert_eq!(f.cbrt(), f256::ONE + f256::ONE.div2());
let f = f256::from_str("84807037425.375").unwrap();
assert_eq!(f.cbrt(), f256::from_str("4393.5").unwrap());
}
#[test]
fn test_cbrt_max() {
let f = f256::MAX;
let r = f.cbrt();
assert_eq!(f, r.powi(3));
}
#[test]
fn test_cbrt_min() {
let f = f256::MIN;
let r = f.cbrt();
assert_eq!(f, r.powi(3));
}
#[test]
fn test_subnormal() {
let f = f256 {
bits: U256::new(
161381583805889998189973969922,
288413346707470246106660640932215474040,
),
};
assert!(f.is_subnormal());
let r = f.cbrt();
assert!(r.is_normal());
assert_eq!(r.powi(3), f);
}
#[test]
fn test_near_zero() {
let f = f256::MIN_GT_ZERO;
let r = f.cbrt();
assert!(r.is_normal());
let (a, b) = fast_mul(&r, &r);
let g = a.mul_add(r, b * r);
assert_eq!(g, f);
}
}