1use crate::defs::BigFloatNum;
4use crate::defs::Error;
5use crate::defs::DECIMAL_BASE;
6use crate::defs::DECIMAL_PARTS;
7use crate::defs::DECIMAL_POSITIONS;
8
9impl BigFloatNum {
10 pub fn ln(&self) -> Result<Self, Error> {
18 let arg = Self::to_big_float_inc(self);
19 let ret = arg.ln()?;
20 Self::from_big_float_inc(ret)
21 }
22
23 pub fn exp(&self) -> Result<Self, Error> {
29 let arg = Self::to_big_float_inc(self);
30 let ret = arg.exp()?;
31 Self::from_big_float_inc(ret)
32 }
33
34 pub fn log(&self, b: &Self) -> Result<Self, Error> {
44 let arg = Self::to_big_float_inc(self);
45 let base = Self::to_big_float_inc(b);
46 let ret = arg.log(&base)?;
47 Self::from_big_float_inc(ret)
48 }
49
50 pub fn log2(&self) -> Result<Self, Error> {
58 let mut two = Self::new();
59 two.m[DECIMAL_PARTS - 1] = DECIMAL_BASE as i16 / 5;
60 two.n = DECIMAL_POSITIONS as i16;
61 two.e = 1 - DECIMAL_POSITIONS as i8;
62 self.log(&two)
63 }
64
65 pub fn log10(&self) -> Result<Self, Error> {
73 let mut ten = Self::new();
74 ten.m[DECIMAL_PARTS - 1] = DECIMAL_BASE as i16 / 10;
75 ten.n = DECIMAL_POSITIONS as i16;
76 ten.e = 2 - DECIMAL_POSITIONS as i8;
77 self.log(&ten)
78 }
79}
80
81#[cfg(test)]
82mod tests {
83
84 use super::*;
85 use crate::defs::DECIMAL_POSITIONS;
86 use crate::defs::DECIMAL_SIGN_NEG;
87 use crate::defs::E;
88
89 #[test]
90 fn test_log() {
91 let mut d1;
92 let mut d2;
93 let one = BigFloatNum::one();
94 let two = one.add(&one).unwrap();
95 let mut epsilon = BigFloatNum::one();
96 epsilon.e = -epsilon.n as i8 + 1 - (DECIMAL_POSITIONS as i8);
97
98 d1 = BigFloatNum::new();
100 assert!(d1.ln().unwrap_err() == Error::InvalidArgument);
101 assert!(d1.log(&two).unwrap_err() == Error::InvalidArgument);
102
103 assert!(two.log(&d1).unwrap_err() == Error::InvalidArgument);
105
106 d1 = BigFloatNum::one();
108 d1.sign = DECIMAL_SIGN_NEG;
109 assert!(d1.ln().unwrap_err() == Error::InvalidArgument);
110 assert!(d1.log(&two).unwrap_err() == Error::InvalidArgument);
111
112 assert!(two.log(&d1).unwrap_err() == Error::InvalidArgument);
114
115 epsilon.e = -77; assert!(E.ln().unwrap().sub(&one).unwrap().abs().cmp(&epsilon) <= 0);
118
119 let four = two.add(&two).unwrap();
121 assert!(
122 four.log(&two)
123 .unwrap()
124 .sub(&two)
125 .unwrap()
126 .abs()
127 .cmp(&epsilon)
128 <= 0
129 );
130
131 let half = one.div(&two).unwrap();
133 assert!(
134 four.log(&half)
135 .unwrap()
136 .add(&two)
137 .unwrap()
138 .abs()
139 .cmp(&epsilon)
140 <= 0
141 );
142
143 assert!(four.log(&one).unwrap_err() == Error::DivisionByZero);
145
146 d2 = BigFloatNum::new();
147 d2.m[0] = 4567;
148 d2.m[1] = 123;
149 d2.m[2] = 6789;
150 d2.m[3] = 2345;
151 d2.m[4] = 651;
152 d2.m[5] = 41;
153 d2.m[6] = 671;
154 d2.m[7] = 9999;
155 d2.m[8] = 0;
156 d2.m[9] = 0;
157 d2.e = -10;
158 for i in 1..1000 {
159 d2.m[2] = i;
160 d2.m[9] = i;
161 d2.n = if i < 10 {
162 1
163 } else if i < 100 {
164 2
165 } else if i < 1000 {
166 3
167 } else {
168 4
169 } + 36;
170 d2.e = -50 + (i % 100) as i8;
171 epsilon.e = -epsilon.n as i8 + 4 - (DECIMAL_POSITIONS as i8) + d2.e + d2.n as i8;
172 let ret = d2.ln().unwrap();
173 d1 = ret.exp().unwrap();
174 assert!(d2.sub(&d1).unwrap().abs().cmp(&epsilon) < 0);
175
176 let ret = d2.log(&two).unwrap();
178 d1 = two.pow(&ret).unwrap();
179 assert!(d2.sub(&d1).unwrap().abs().cmp(&epsilon) < 0);
180
181 let ret = d2.log(&half).unwrap();
183 d1 = half.pow(&ret).unwrap();
184 assert!(d2.sub(&d1).unwrap().abs().cmp(&epsilon) < 0);
185 }
186
187 epsilon.e = -epsilon.n as i8 + 1 - (DECIMAL_POSITIONS as i8);
189 assert!(four.log2().unwrap().sub(&two).unwrap().abs().cmp(&epsilon) <= 0);
190
191 d1 = BigFloatNum::new();
193 d1.m[0] = 100;
194 d1.n = 3;
195 assert!(d1.log10().unwrap().sub(&two).unwrap().abs().cmp(&epsilon) <= 0);
196 }
197}