use crate::defs::Error;
use crate::defs::DECIMAL_SIGN_POS;
use crate::inc::inc::BigFloatInc;
use crate::inc::inc::DECIMAL_PARTS;
use crate::inc::inc::ZEROED_MANTISSA;
use crate::inc::ops::tables::cbrt_const::CBRT_VALUES;
const ONE_THIRD: BigFloatInc = BigFloatInc {
m: [3333, 3333, 3333, 3333, 3333, 3333, 3333, 3333, 3333, 3333, 3333],
n: 44,
sign: DECIMAL_SIGN_POS,
e: -44,
};
const TWO_THIRD: BigFloatInc = BigFloatInc {
m: [6667, 6666, 6666, 6666, 6666, 6666, 6666, 6666, 6666, 6666, 6666],
n: 44,
sign: DECIMAL_SIGN_POS,
e: -44,
};
const CBRT_OF_10: BigFloatInc = BigFloatInc {
m: [3449, 5259, 5049, 5193, 3566, 5929, 7217, 1883, 9003, 4346, 2154],
n: 44,
sign: DECIMAL_SIGN_POS,
e: -43,
};
const CBRT_OF_100: BigFloatInc = BigFloatInc {
m: [3491, 6551, 4657, 9194, 6350, 1007, 8924, 2778, 3361, 5888, 4641],
n: 44,
sign: DECIMAL_SIGN_POS,
e: -43,
};
impl BigFloatInc {
pub fn cbrt(&self) -> Result<Self, Error> {
if self.n == 0 || self.m == ZEROED_MANTISSA {
return Ok(*self);
}
let mut int_num = *self;
int_num.e = 0;
int_num.sign = DECIMAL_SIGN_POS;
let part1 = Self::cbrt_int(&int_num)?;
let e = (self.e as i32).abs() % 3;
let mut ret = if e > 0 {
let part2 = if e < 2 { CBRT_OF_10 } else { CBRT_OF_100 };
if self.e < 0 { part1.div(&part2) } else { part1.mul(&part2) }?
} else {
part1
};
ret.e += self.e / 3;
ret.sign = self.sign;
Ok(ret)
}
fn cbrt_int(d1: &Self) -> Result<Self, Error> {
let mut i = DECIMAL_PARTS - 1;
while d1.m[i] == 0 && i > 0 {
i -= 1;
}
let j = d1.m[i] / 100;
let mut n = if i > 0 || j > 0 { CBRT_VALUES[i * 99 + j as usize] } else { *d1 };
let s = d1.mul(&ONE_THIRD)?;
let mut err = *d1;
loop {
if n.n == 0 {
break;
}
let p1 = s.div(&n)?.div(&n)?;
let p2 = TWO_THIRD.mul(&n)?;
let n2 = p1.add(&p2)?;
let err2 = n.sub(&n2)?;
if err2.cmp(&err) >= 0 {
break;
}
err = err2;
n = n2;
}
Ok(n)
}
}