1//! log base 2 approximation for a single-precision float.
2
3use super::F32;
4use core::f32::consts::LOG10_E;
5
6impl F32 {
7 /// Approximates the base 10 logarithm of the number.
8 pub fn log10(self) -> Self {
9 self.ln() * LOG10_E
10 }
11}
12
13#[cfg(test)]
14mod tests {
15 use super::F32;
16 pub(crate) const MAX_ERROR: f32 = 0.001;
17
18 /// log10(x) test vectors - `(input, output)`
19 pub(crate) const TEST_VECTORS: &[(f32, f32)] = &[
20 (1e-20, -20.0),
21 (1e-19, -19.0),
22 (1e-18, -18.0),
23 (1e-17, -17.0),
24 (1e-16, -16.0),
25 (1e-15, -15.0),
26 (1e-14, -14.0),
27 (1e-13, -13.0),
28 (1e-12, -12.0),
29 (1e-11, -11.0),
30 (1e-10, -10.0),
31 (1e-09, -9.0),
32 (1e-08, -8.0),
33 (1e-07, -7.0),
34 (1e-06, -6.0),
35 (1e-05, -5.0),
36 (1e-04, -4.0),
37 (0.001, -3.0),
38 (0.01, -2.0),
39 (0.1, -1.0),
40 (10.0, 1.0),
41 (100.0, 2.0),
42 (1000.0, 3.0),
43 (10000.0, 4.0),
44 (100000.0, 5.0),
45 (1000000.0, 6.0),
46 (10000000.0, 7.0),
47 (100000000.0, 8.0),
48 (1000000000.0, 9.0),
49 (10000000000.0, 10.0),
50 (100000000000.0, 11.0),
51 (1000000000000.0, 12.0),
52 (10000000000000.0, 13.0),
53 (100000000000000.0, 14.0),
54 (1000000000000000.0, 15.0),
55 (1e+16, 16.0),
56 (1e+17, 17.0),
57 (1e+18, 18.0),
58 (1e+19, 19.0),
59 ];
60
61 #[test]
62 fn sanity_check() {
63 assert_eq!(F32::ONE.log10(), F32::ZERO);
64
65 for &(x, expected) in TEST_VECTORS {
66 let ln_x = F32(x).log10();
67 let relative_error = (ln_x - expected).abs() / expected;
68
69 assert!(
70 relative_error <= MAX_ERROR,
71 "relative_error {} too large: {} vs {}",
72 relative_error,
73 ln_x,
74 expected
75 );
76 }
77 }
78}
79