1// Adapted from https://github.com/Alexhuszagh/rust-lexical.
23//! Utilities to calculate exponents.
45/// 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]
10fn into_i32(value: usize) -> i32 {
11if value > i32::MAX as usize {
12 i32::MAX
13 } else {
14 value as i32
15 }
16}
1718// EXPONENT CALCULATION
1920// 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]
24pub(crate) fn scientific_exponent(
25 exponent: i32,
26 integer_digits: usize,
27 fraction_start: usize,
28) -> i32 {
29if integer_digits == 0 {
30let fraction_start = into_i32(fraction_start);
31 exponent.saturating_sub(fraction_start).saturating_sub(1)
32 } else {
33let integer_shift = into_i32(integer_digits - 1);
34 exponent.saturating_add(integer_shift)
35 }
36}
3738// 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]
44pub(crate) fn mantissa_exponent(exponent: i32, fraction_digits: usize, truncated: usize) -> i32 {
45if 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}