| 1 | //! Parse byte iterators to float. |
| 2 | |
| 3 | #![doc (hidden)] |
| 4 | |
| 5 | #[cfg (feature = "compact" )] |
| 6 | use crate::bellerophon::bellerophon; |
| 7 | use crate::extended_float::{extended_to_float, ExtendedFloat}; |
| 8 | #[cfg (not(feature = "compact" ))] |
| 9 | use crate::lemire::lemire; |
| 10 | use crate::num::Float; |
| 11 | use crate::number::Number; |
| 12 | use crate::slow::slow; |
| 13 | |
| 14 | /// Try to parse the significant digits quickly. |
| 15 | /// |
| 16 | /// This attempts a very quick parse, to deal with common cases. |
| 17 | /// |
| 18 | /// * `integer` - Slice containing the integer digits. |
| 19 | /// * `fraction` - Slice containing the fraction digits. |
| 20 | #[inline ] |
| 21 | fn parse_number_fast<'a, Iter1, Iter2>( |
| 22 | integer: Iter1, |
| 23 | fraction: Iter2, |
| 24 | exponent: i32, |
| 25 | ) -> Option<Number> |
| 26 | where |
| 27 | Iter1: Iterator<Item = &'a u8>, |
| 28 | Iter2: Iterator<Item = &'a u8>, |
| 29 | { |
| 30 | let mut num: Number = Number::default(); |
| 31 | let mut integer_count: usize = 0; |
| 32 | let mut fraction_count: usize = 0; |
| 33 | for &c: u8 in integer { |
| 34 | integer_count += 1; |
| 35 | let digit: u8 = c - b'0' ; |
| 36 | num.mantissa = num.mantissa.wrapping_mul(10).wrapping_add(digit as u64); |
| 37 | } |
| 38 | for &c: u8 in fraction { |
| 39 | fraction_count += 1; |
| 40 | let digit: u8 = c - b'0' ; |
| 41 | num.mantissa = num.mantissa.wrapping_mul(10).wrapping_add(digit as u64); |
| 42 | } |
| 43 | |
| 44 | if integer_count + fraction_count <= 19 { |
| 45 | // Can't overflow, since must be <= 19. |
| 46 | num.exponent = exponent.saturating_sub(fraction_count as i32); |
| 47 | Some(num) |
| 48 | } else { |
| 49 | None |
| 50 | } |
| 51 | } |
| 52 | |
| 53 | /// Parse the significant digits of the float and adjust the exponent. |
| 54 | /// |
| 55 | /// * `integer` - Slice containing the integer digits. |
| 56 | /// * `fraction` - Slice containing the fraction digits. |
| 57 | #[inline ] |
| 58 | fn parse_number<'a, Iter1, Iter2>(mut integer: Iter1, mut fraction: Iter2, exponent: i32) -> Number |
| 59 | where |
| 60 | Iter1: Iterator<Item = &'a u8> + Clone, |
| 61 | Iter2: Iterator<Item = &'a u8> + Clone, |
| 62 | { |
| 63 | // NOTE: for performance, we do this in 2 passes: |
| 64 | if let Some(num) = parse_number_fast(integer.clone(), fraction.clone(), exponent) { |
| 65 | return num; |
| 66 | } |
| 67 | |
| 68 | // Can only add 19 digits. |
| 69 | let mut num = Number::default(); |
| 70 | let mut count = 0; |
| 71 | while let Some(&c) = integer.next() { |
| 72 | count += 1; |
| 73 | if count == 20 { |
| 74 | // Only the integer digits affect the exponent. |
| 75 | num.many_digits = true; |
| 76 | num.exponent = exponent.saturating_add(into_i32(1 + integer.count())); |
| 77 | return num; |
| 78 | } else { |
| 79 | let digit = c - b'0' ; |
| 80 | num.mantissa = num.mantissa * 10 + digit as u64; |
| 81 | } |
| 82 | } |
| 83 | |
| 84 | // Skip leading fraction zeros. |
| 85 | // This is required otherwise we might have a 0 mantissa and many digits. |
| 86 | let mut fraction_count: usize = 0; |
| 87 | if count == 0 { |
| 88 | for &c in &mut fraction { |
| 89 | fraction_count += 1; |
| 90 | if c != b'0' { |
| 91 | count += 1; |
| 92 | let digit = c - b'0' ; |
| 93 | num.mantissa = num.mantissa * 10 + digit as u64; |
| 94 | break; |
| 95 | } |
| 96 | } |
| 97 | } |
| 98 | for c in fraction { |
| 99 | fraction_count += 1; |
| 100 | count += 1; |
| 101 | if count == 20 { |
| 102 | num.many_digits = true; |
| 103 | // This can't wrap, since we have at most 20 digits. |
| 104 | // We've adjusted the exponent too high by `fraction_count - 1`. |
| 105 | // Note: -1 is due to incrementing this loop iteration, which we |
| 106 | // didn't use. |
| 107 | num.exponent = exponent.saturating_sub(fraction_count as i32 - 1); |
| 108 | return num; |
| 109 | } else { |
| 110 | let digit = c - b'0' ; |
| 111 | num.mantissa = num.mantissa * 10 + digit as u64; |
| 112 | } |
| 113 | } |
| 114 | |
| 115 | // No truncated digits: easy. |
| 116 | // Cannot overflow: <= 20 digits. |
| 117 | num.exponent = exponent.saturating_sub(fraction_count as i32); |
| 118 | num |
| 119 | } |
| 120 | |
| 121 | /// Parse float from extracted float components. |
| 122 | /// |
| 123 | /// * `integer` - Cloneable, forward iterator over integer digits. |
| 124 | /// * `fraction` - Cloneable, forward iterator over integer digits. |
| 125 | /// * `exponent` - Parsed, 32-bit exponent. |
| 126 | /// |
| 127 | /// # Preconditions |
| 128 | /// 1. The integer should not have leading zeros. |
| 129 | /// 2. The fraction should not have trailing zeros. |
| 130 | /// 3. All bytes in `integer` and `fraction` should be valid digits, |
| 131 | /// in the range [`b'0', b'9']. |
| 132 | /// |
| 133 | /// # Panics |
| 134 | /// |
| 135 | /// Although passing garbage input will not cause memory safety issues, |
| 136 | /// it is very likely to cause a panic with a large number of digits, or |
| 137 | /// in debug mode. The big-integer arithmetic without the `alloc` feature |
| 138 | /// assumes a maximum, fixed-width input, which assumes at maximum a |
| 139 | /// value of `10^(769 + 342)`, or ~4000 bits of storage. Passing in |
| 140 | /// nonsensical digits may require up to ~6000 bits of storage, which will |
| 141 | /// panic when attempting to add it to the big integer. It is therefore |
| 142 | /// up to the caller to validate this input. |
| 143 | /// |
| 144 | /// We cannot efficiently remove trailing zeros while only accepting a |
| 145 | /// forward iterator. |
| 146 | pub fn parse_float<'a, F, Iter1, Iter2>(integer: Iter1, fraction: Iter2, exponent: i32) -> F |
| 147 | where |
| 148 | F: Float, |
| 149 | Iter1: Iterator<Item = &'a u8> + Clone, |
| 150 | Iter2: Iterator<Item = &'a u8> + Clone, |
| 151 | { |
| 152 | // Parse the mantissa and attempt the fast and moderate-path algorithms. |
| 153 | let num: Number = parse_number(integer.clone(), fraction.clone(), exponent); |
| 154 | // Try the fast-path algorithm. |
| 155 | if let Some(value: F) = num.try_fast_path() { |
| 156 | return value; |
| 157 | } |
| 158 | |
| 159 | // Now try the moderate path algorithm. |
| 160 | let mut fp: ExtendedFloat = moderate_path::<F>(&num); |
| 161 | if fp.exp < 0 { |
| 162 | // Undo the invalid extended float biasing. |
| 163 | fp.exp -= F::INVALID_FP; |
| 164 | fp = slow::<F, _, _>(num, fp, integer, fraction); |
| 165 | } |
| 166 | |
| 167 | // Unable to correctly round the float using the fast or moderate algorithms. |
| 168 | // Fallback to a slower, but always correct algorithm. If we have |
| 169 | // lossy, we can't be here. |
| 170 | extended_to_float::<F>(fp) |
| 171 | } |
| 172 | |
| 173 | /// Wrapper for different moderate-path algorithms. |
| 174 | /// A return exponent of `-1` indicates an invalid value. |
| 175 | #[inline ] |
| 176 | pub fn moderate_path<F: Float>(num: &Number) -> ExtendedFloat { |
| 177 | #[cfg (not(feature = "compact" ))] |
| 178 | return lemire::<F>(num); |
| 179 | |
| 180 | #[cfg (feature = "compact" )] |
| 181 | return bellerophon::<F>(num); |
| 182 | } |
| 183 | |
| 184 | /// Convert usize into i32 without overflow. |
| 185 | /// |
| 186 | /// This is needed to ensure when adjusting the exponent relative to |
| 187 | /// the mantissa we do not overflow for comically-long exponents. |
| 188 | #[inline ] |
| 189 | fn into_i32(value: usize) -> i32 { |
| 190 | if value > i32::max_value() as usize { |
| 191 | i32::max_value() |
| 192 | } else { |
| 193 | value as i32 |
| 194 | } |
| 195 | } |
| 196 | |
| 197 | // Add digit to mantissa. |
| 198 | #[inline ] |
| 199 | pub fn add_digit(value: u64, digit: u8) -> Option<u64> { |
| 200 | value.checked_mul(10)?.checked_add(digit as u64) |
| 201 | } |
| 202 | |