• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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]
parse_number_fast<'a, Iter1, Iter2>( integer: Iter1, fraction: Iter2, exponent: i32, ) -> Option<Number> where Iter1: Iterator<Item = &'a u8>, Iter2: Iterator<Item = &'a u8>,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::default();
31     let mut integer_count: usize = 0;
32     let mut fraction_count: usize = 0;
33     for &c in integer {
34         integer_count += 1;
35         let digit = c - b'0';
36         num.mantissa = num.mantissa.wrapping_mul(10).wrapping_add(digit as u64);
37     }
38     for &c in fraction {
39         fraction_count += 1;
40         let digit = 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]
parse_number<'a, Iter1, Iter2>(mut integer: Iter1, mut fraction: Iter2, exponent: i32) -> Number where Iter1: Iterator<Item = &'a u8> + Clone, Iter2: Iterator<Item = &'a u8> + Clone,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.
parse_float<'a, F, Iter1, Iter2>(integer: Iter1, fraction: Iter2, exponent: i32) -> F where F: Float, Iter1: Iterator<Item = &'a u8> + Clone, Iter2: Iterator<Item = &'a u8> + Clone,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 = parse_number(integer.clone(), fraction.clone(), exponent);
154     // Try the fast-path algorithm.
155     if let Some(value) = num.try_fast_path() {
156         return value;
157     }
158 
159     // Now try the moderate path algorithm.
160     let mut fp = 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]
moderate_path<F: Float>(num: &Number) -> ExtendedFloat176 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]
into_i32(value: usize) -> i32189 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]
add_digit(value: u64, digit: u8) -> Option<u64>199 pub fn add_digit(value: u64, digit: u8) -> Option<u64> {
200     value.checked_mul(10)?.checked_add(digit as u64)
201 }
202