num_bigfloat/ops/
cbrt.rs

1//! Cube root.
2
3use crate::defs::BigFloatNum;
4use crate::defs::Error;
5
6impl BigFloatNum {
7    /// Return cube root of a number.
8    pub fn cbrt(&self) -> Result<Self, Error> {
9        let arg = Self::to_big_float_inc(self);
10        let ret = arg.cbrt()?;
11        Self::from_big_float_inc(ret)
12    }
13}
14
15#[cfg(test)]
16mod tests {
17
18    use super::*;
19    use crate::defs::{
20        DECIMAL_MIN_EXPONENT, DECIMAL_POSITIONS, DECIMAL_SIGN_NEG, DECIMAL_SIGN_POS,
21    };
22
23    #[test]
24    fn test_cbrt() {
25        let mut d1;
26
27        let one = BigFloatNum::one();
28        let mut epsilon = BigFloatNum::one();
29        epsilon.e = -epsilon.n as i8 + 2 - (DECIMAL_POSITIONS as i8);
30
31        /*
32                for i in 0..11 {
33                    for j in 1..100 {
34                        let mut d = crate::inc::inc::BigFloatInc::new();
35                        d.m[i] = j*100;
36                        d.n = crate::inc::inc::BigFloatInc::num_digits(&d.m);
37                        let ret = d.cbrt().unwrap();
38                    }
39                }
40        */
41        // 0
42        d1 = BigFloatNum::new();
43        assert!(d1.cbrt().unwrap().n == 0);
44
45        // |d1| = 1
46        d1 = BigFloatNum::one();
47        let d2 = d1;
48        let ret = d1.cbrt().unwrap();
49        assert!(ret.sub(&d2).unwrap().abs().cmp(&epsilon) <= 0);
50
51        d1.sign = DECIMAL_SIGN_NEG;
52        let d2 = d1;
53        let ret = d1.cbrt().unwrap();
54        assert!(ret.sub(&d2).unwrap().abs().cmp(&epsilon) <= 0);
55
56        // |d1| < 1
57        d1 = BigFloatNum::one();
58        d1.m[0] = 456;
59        d1.m[8] = 123;
60        d1.e -= 1;
61        let d2 = d1;
62        let ret = d1.cbrt().unwrap();
63        let ret = ret.mul(&ret).unwrap().mul(&ret).unwrap();
64        assert!(ret.div(&d2).unwrap().sub(&one).unwrap().abs().cmp(&epsilon) <= 0);
65
66        d1.sign = DECIMAL_SIGN_NEG;
67        let d2 = d1;
68        let ret = d1.cbrt().unwrap();
69        let ret = ret.mul(&ret).unwrap().mul(&ret).unwrap();
70        assert!(ret.div(&d2).unwrap().sub(&one).unwrap().abs().cmp(&epsilon) <= 0);
71
72        // |d1| > 1
73        d1.e += 2;
74        d1.sign = DECIMAL_SIGN_POS;
75        let d2 = d1;
76        let ret = d1.cbrt().unwrap();
77        let ret = ret.mul(&ret).unwrap().mul(&ret).unwrap();
78        assert!(ret.div(&d2).unwrap().sub(&one).unwrap().abs().cmp(&epsilon) <= 0);
79
80        d1.sign = DECIMAL_SIGN_NEG;
81        let d2 = d1;
82        let ret = d1.cbrt().unwrap();
83        let ret = ret.mul(&ret).unwrap().mul(&ret).unwrap();
84        assert!(ret.div(&d2).unwrap().sub(&one).unwrap().abs().cmp(&epsilon) <= 0);
85
86        // subnormal
87        d1 = BigFloatNum::new();
88        d1.m[0] = 456;
89        d1.m[1] = 123;
90        d1.n = 7;
91        d1.e = DECIMAL_MIN_EXPONENT;
92        let d2 = d1;
93        let ret = d1.cbrt().unwrap();
94        let ret = ret.mul(&ret).unwrap().mul(&ret).unwrap();
95        assert!(ret.sub(&d2).unwrap().abs().get_mantissa_len() < 2);
96
97        // range of numbers
98        let mut ret;
99        let mut d1 = BigFloatNum::new();
100        d1.m[0] = 4560;
101        d1.m[1] = 123;
102        d1.m[2] = 6789;
103        d1.m[3] = 2345;
104        d1.m[4] = 651;
105        d1.m[5] = 41;
106        d1.m[6] = 671;
107        d1.m[7] = 100;
108        d1.m[8] = 0;
109        d1.m[9] = 0;
110        d1.n = 32;
111        d1.e = -38;
112        epsilon.e = -epsilon.n as i8 + 3 - (DECIMAL_POSITIONS as i8);
113        for i in 1..8000 {
114            d1.m[8] = 10 + i;
115            d1.m[9] = i;
116            d1.n = if i < 10 {
117                1
118            } else if i < 100 {
119                2
120            } else if i < 1000 {
121                3
122            } else {
123                4
124            } + 36;
125            ret = d1.cbrt().unwrap();
126            ret = ret.mul(&ret).unwrap().mul(&ret).unwrap();
127            assert!(ret.div(&d1).unwrap().sub(&one).unwrap().abs().cmp(&epsilon) <= 0);
128        }
129    }
130}