1 //! Utilities to calculate exponents.
2
3 /// Convert usize into i32 without overflow.
4 ///
5 /// This is needed to ensure when adjusting the exponent relative to
6 /// the mantissa we do not overflow for comically-long exponents.
7 #[inline]
into_i32(value: usize) -> i328 fn into_i32(value: usize) -> i32 {
9 if value > i32::max_value() as usize {
10 i32::max_value()
11 } else {
12 value as i32
13 }
14 }
15
16 // EXPONENT CALCULATION
17
18 // Calculate the scientific notation exponent without overflow.
19 //
20 // For example, 0.1 would be -1, and 10 would be 1 in base 10.
21 #[inline]
scientific_exponent( exponent: i32, integer_digits: usize, fraction_start: usize, ) -> i3222 pub(crate) fn scientific_exponent(
23 exponent: i32,
24 integer_digits: usize,
25 fraction_start: usize,
26 ) -> i32 {
27 if integer_digits == 0 {
28 let fraction_start = into_i32(fraction_start);
29 exponent.saturating_sub(fraction_start).saturating_sub(1)
30 } else {
31 let integer_shift = into_i32(integer_digits - 1);
32 exponent.saturating_add(integer_shift)
33 }
34 }
35
36 // Calculate the mantissa exponent without overflow.
37 //
38 // Remove the number of digits that contributed to the mantissa past
39 // the dot, and add the number of truncated digits from the mantissa,
40 // to calculate the scaling factor for the mantissa from a raw exponent.
41 #[inline]
mantissa_exponent(exponent: i32, fraction_digits: usize, truncated: usize) -> i3242 pub(crate) fn mantissa_exponent(exponent: i32, fraction_digits: usize, truncated: usize) -> i32 {
43 if fraction_digits > truncated {
44 exponent.saturating_sub(into_i32(fraction_digits - truncated))
45 } else {
46 exponent.saturating_add(into_i32(truncated - fraction_digits))
47 }
48 }
49
50 // TESTS
51 // -----
52
53 #[cfg(test)]
54 mod test {
55 use super::*;
56
57 #[test]
scientific_exponent_test()58 fn scientific_exponent_test() {
59 // 0 digits in the integer
60 assert_eq!(scientific_exponent(0, 0, 5), -6);
61 assert_eq!(scientific_exponent(10, 0, 5), 4);
62 assert_eq!(scientific_exponent(-10, 0, 5), -16);
63
64 // >0 digits in the integer
65 assert_eq!(scientific_exponent(0, 1, 5), 0);
66 assert_eq!(scientific_exponent(0, 2, 5), 1);
67 assert_eq!(scientific_exponent(0, 2, 20), 1);
68 assert_eq!(scientific_exponent(10, 2, 20), 11);
69 assert_eq!(scientific_exponent(-10, 2, 20), -9);
70
71 // Underflow
72 assert_eq!(scientific_exponent(i32::min_value(), 0, 0), i32::min_value());
73 assert_eq!(scientific_exponent(i32::min_value(), 0, 5), i32::min_value());
74
75 // Overflow
76 assert_eq!(scientific_exponent(i32::max_value(), 0, 0), i32::max_value() - 1);
77 assert_eq!(scientific_exponent(i32::max_value(), 5, 0), i32::max_value());
78 }
79
80 #[test]
mantissa_exponent_test()81 fn mantissa_exponent_test() {
82 assert_eq!(mantissa_exponent(10, 5, 0), 5);
83 assert_eq!(mantissa_exponent(0, 5, 0), -5);
84 assert_eq!(mantissa_exponent(i32::max_value(), 5, 0), i32::max_value() - 5);
85 assert_eq!(mantissa_exponent(i32::max_value(), 0, 5), i32::max_value());
86 assert_eq!(mantissa_exponent(i32::min_value(), 5, 0), i32::min_value());
87 assert_eq!(mantissa_exponent(i32::min_value(), 0, 5), i32::min_value() + 5);
88 }
89 }
90