//! Parse byte iterators to float. #![doc(hidden)] #[cfg(feature = "compact")] use crate::bellerophon::bellerophon; use crate::extended_float::{extended_to_float, ExtendedFloat}; #[cfg(not(feature = "compact"))] use crate::lemire::lemire; use crate::num::Float; use crate::number::Number; use crate::slow::slow; /// Try to parse the significant digits quickly. /// /// This attempts a very quick parse, to deal with common cases. /// /// * `integer` - Slice containing the integer digits. /// * `fraction` - Slice containing the fraction digits. #[inline] fn parse_number_fast<'a, Iter1, Iter2>( integer: Iter1, fraction: Iter2, exponent: i32, ) -> Option where Iter1: Iterator, Iter2: Iterator, { let mut num = Number::default(); let mut integer_count: usize = 0; let mut fraction_count: usize = 0; for &c in integer { integer_count += 1; let digit = c - b'0'; num.mantissa = num.mantissa.wrapping_mul(10).wrapping_add(digit as u64); } for &c in fraction { fraction_count += 1; let digit = c - b'0'; num.mantissa = num.mantissa.wrapping_mul(10).wrapping_add(digit as u64); } if integer_count + fraction_count <= 19 { // Can't overflow, since must be <= 19. num.exponent = exponent.saturating_sub(fraction_count as i32); Some(num) } else { None } } /// Parse the significant digits of the float and adjust the exponent. /// /// * `integer` - Slice containing the integer digits. /// * `fraction` - Slice containing the fraction digits. #[inline] fn parse_number<'a, Iter1, Iter2>(mut integer: Iter1, mut fraction: Iter2, exponent: i32) -> Number where Iter1: Iterator + Clone, Iter2: Iterator + Clone, { // NOTE: for performance, we do this in 2 passes: if let Some(num) = parse_number_fast(integer.clone(), fraction.clone(), exponent) { return num; } // Can only add 19 digits. let mut num = Number::default(); let mut count = 0; while let Some(&c) = integer.next() { count += 1; if count == 20 { // Only the integer digits affect the exponent. num.many_digits = true; num.exponent = exponent.saturating_add(into_i32(1 + integer.count())); return num; } else { let digit = c - b'0'; num.mantissa = num.mantissa * 10 + digit as u64; } } // Skip leading fraction zeros. // This is required otherwise we might have a 0 mantissa and many digits. let mut fraction_count: usize = 0; if count == 0 { for &c in &mut fraction { fraction_count += 1; if c != b'0' { count += 1; let digit = c - b'0'; num.mantissa = num.mantissa * 10 + digit as u64; break; } } } for c in fraction { fraction_count += 1; count += 1; if count == 20 { num.many_digits = true; // This can't wrap, since we have at most 20 digits. // We've adjusted the exponent too high by `fraction_count - 1`. // Note: -1 is due to incrementing this loop iteration, which we // didn't use. num.exponent = exponent.saturating_sub(fraction_count as i32 - 1); return num; } else { let digit = c - b'0'; num.mantissa = num.mantissa * 10 + digit as u64; } } // No truncated digits: easy. // Cannot overflow: <= 20 digits. num.exponent = exponent.saturating_sub(fraction_count as i32); num } /// Parse float from extracted float components. /// /// * `integer` - Cloneable, forward iterator over integer digits. /// * `fraction` - Cloneable, forward iterator over integer digits. /// * `exponent` - Parsed, 32-bit exponent. /// /// # Preconditions /// 1. The integer should not have leading zeros. /// 2. The fraction should not have trailing zeros. /// 3. All bytes in `integer` and `fraction` should be valid digits, /// in the range [`b'0', b'9']. /// /// # Panics /// /// Although passing garbage input will not cause memory safety issues, /// it is very likely to cause a panic with a large number of digits, or /// in debug mode. The big-integer arithmetic without the `alloc` feature /// assumes a maximum, fixed-width input, which assumes at maximum a /// value of `10^(769 + 342)`, or ~4000 bits of storage. Passing in /// nonsensical digits may require up to ~6000 bits of storage, which will /// panic when attempting to add it to the big integer. It is therefore /// up to the caller to validate this input. /// /// We cannot efficiently remove trailing zeros while only accepting a /// forward iterator. pub fn parse_float<'a, F, Iter1, Iter2>(integer: Iter1, fraction: Iter2, exponent: i32) -> F where F: Float, Iter1: Iterator + Clone, Iter2: Iterator + Clone, { // Parse the mantissa and attempt the fast and moderate-path algorithms. let num = parse_number(integer.clone(), fraction.clone(), exponent); // Try the fast-path algorithm. if let Some(value) = num.try_fast_path() { return value; } // Now try the moderate path algorithm. let mut fp = moderate_path::(&num); if fp.exp < 0 { // Undo the invalid extended float biasing. fp.exp -= F::INVALID_FP; fp = slow::(num, fp, integer, fraction); } // Unable to correctly round the float using the fast or moderate algorithms. // Fallback to a slower, but always correct algorithm. If we have // lossy, we can't be here. extended_to_float::(fp) } /// Wrapper for different moderate-path algorithms. /// A return exponent of `-1` indicates an invalid value. #[inline] pub fn moderate_path(num: &Number) -> ExtendedFloat { #[cfg(not(feature = "compact"))] return lemire::(num); #[cfg(feature = "compact")] return bellerophon::(num); } /// Convert usize into i32 without overflow. /// /// This is needed to ensure when adjusting the exponent relative to /// the mantissa we do not overflow for comically-long exponents. #[inline] fn into_i32(value: usize) -> i32 { if value > i32::max_value() as usize { i32::max_value() } else { value as i32 } } // Add digit to mantissa. #[inline] pub fn add_digit(value: u64, digit: u8) -> Option { value.checked_mul(10)?.checked_add(digit as u64) }