| 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 | |