1 | // Adapted from https://github.com/Alexhuszagh/rust-lexical. |
2 | |
3 | //! Utilities to calculate exponents. |
4 | |
5 | /// Convert usize into i32 without overflow. |
6 | /// |
7 | /// This is needed to ensure when adjusting the exponent relative to |
8 | /// the mantissa we do not overflow for comically-long exponents. |
9 | #[inline ] |
10 | fn into_i32(value: usize) -> i32 { |
11 | if value > i32::max_value() as usize { |
12 | i32::max_value() |
13 | } else { |
14 | value as i32 |
15 | } |
16 | } |
17 | |
18 | // EXPONENT CALCULATION |
19 | |
20 | // Calculate the scientific notation exponent without overflow. |
21 | // |
22 | // For example, 0.1 would be -1, and 10 would be 1 in base 10. |
23 | #[inline ] |
24 | pub(crate) fn scientific_exponent( |
25 | exponent: i32, |
26 | integer_digits: usize, |
27 | fraction_start: usize, |
28 | ) -> i32 { |
29 | if integer_digits == 0 { |
30 | let fraction_start = into_i32(fraction_start); |
31 | exponent.saturating_sub(fraction_start).saturating_sub(1) |
32 | } else { |
33 | let integer_shift = into_i32(integer_digits - 1); |
34 | exponent.saturating_add(integer_shift) |
35 | } |
36 | } |
37 | |
38 | // Calculate the mantissa exponent without overflow. |
39 | // |
40 | // Remove the number of digits that contributed to the mantissa past |
41 | // the dot, and add the number of truncated digits from the mantissa, |
42 | // to calculate the scaling factor for the mantissa from a raw exponent. |
43 | #[inline ] |
44 | pub(crate) fn mantissa_exponent(exponent: i32, fraction_digits: usize, truncated: usize) -> i32 { |
45 | if fraction_digits > truncated { |
46 | exponent.saturating_sub(into_i32(fraction_digits - truncated)) |
47 | } else { |
48 | exponent.saturating_add(into_i32(truncated - fraction_digits)) |
49 | } |
50 | } |
51 | |