1 //! Algorithm to parse an exponent from a float string.
2 
3 use atoi;
4 use util::*;
5 
6 /// Parse the exponential portion from a float-string, if we have an `(e|^)[+-]?\d+`.
7 ///
8 /// On overflow, just return a comically large exponent, since we don't
9 /// care. It will lead to infinity regardless, and doesn't affect whether
10 /// the type is representable.
11 ///
12 /// Returns the exponent and a pointer to the current buffer position.
13 ///
14 /// The float string must be non-special, non-zero, and positive.
15 #[inline]
parse_exponent<'a>(radix: u32, bytes: &'a [u8]) -> (i32, &'a [u8])16 pub(super) fn parse_exponent<'a>(radix: u32, bytes: &'a [u8])
17     -> (i32, &'a [u8])
18 {
19     // Force a check that the distance is >= 2, so we ensure there's something
20     // after the exponent. This fixes a regression discovered via proptest.
21     // Safety: bytes.len() >= 2.
22     if bytes.len() >= 2 && case_insensitive_equal(index!(bytes[0]), exponent_notation_char(radix)) {
23         // Use atoi_sign so we can handle overflow differently for +/- numbers.
24         // We care whether the value is positive.
25         // Use i32::max_value() since it's valid in 2s complement for
26         // positive or negative numbers, and will trigger a short-circuit.
27         // Safety: bytes.len() >= 2.
28         let bytes = &index!(bytes[1..]);
29         let cb = atoi::unchecked::<i32>;
30         let (exponent, sign, len, truncated) = atoi::filter_sign::<i32, _>(radix, bytes, cb);
31         let exponent = match truncated.is_some() {
32             true  => match sign {
33                 Sign::Negative => -i32::max_value(),
34                 Sign::Positive => i32::max_value(),
35             },
36             false => exponent,
37         };
38 
39         // Safety: atoi always returns a value <= bytes.len().
40         (exponent, &index!(bytes[len..]))
41     } else {
42         (0, bytes)
43     }
44 }
45 
46 /// Calculate the scientific notation exponent without overflow.
47 ///
48 /// For example, 0.1 would be -1, and 10 would be 1 in base 10.
49 #[inline]
50 #[cfg(feature = "correct")]
scientific_exponent(exponent: i32, integer_digits: usize, fraction_start: usize) -> i3251 pub(super) fn scientific_exponent(exponent: i32, integer_digits: usize, fraction_start: usize)
52     -> i32
53 {
54     if integer_digits == 0 {
55         let fraction_start = fraction_start.try_i32_or_max();
56         exponent.saturating_sub(fraction_start).saturating_sub(1)
57     } else {
58         let integer_shift = (integer_digits - 1).try_i32_or_max();
59         exponent.saturating_add(integer_shift)
60     }
61 }
62 
63 /// Calculate the mantissa exponent without overflow.
64 ///
65 /// Remove the number of digits that contributed to the mantissa past
66 /// the dot, and add the number of truncated digits from the mantissa,
67 /// to calculate the scaling factor for the mantissa from a raw exponent.
68 #[inline]
69 #[cfg(feature = "correct")]
mantissa_exponent(raw_exponent: i32, fraction_digits: usize, truncated: usize) -> i3270 pub(super) fn mantissa_exponent(raw_exponent: i32, fraction_digits: usize, truncated: usize)
71     -> i32
72 {
73     if fraction_digits > truncated {
74         raw_exponent.saturating_sub((fraction_digits - truncated).try_i32_or_max())
75     } else {
76         raw_exponent.saturating_add((truncated - fraction_digits).try_i32_or_max())
77     }
78 }
79 
80 /// Calculate the integral ceiling of the binary factor from a basen number.
81 #[inline]
82 #[cfg(feature = "correct")]
integral_binary_factor(radix: u32) -> u3283 pub(super) fn integral_binary_factor(radix: u32)
84     -> u32
85 {
86     debug_assert_radix!(radix);
87 
88     #[cfg(not(feature = "radix"))] {
89         4
90     }
91 
92     #[cfg(feature = "radix")] {
93         match radix.as_i32() {
94             2  => 1,
95             3  => 2,
96             4  => 2,
97             5  => 3,
98             6  => 3,
99             7  => 3,
100             8  => 3,
101             9  => 4,
102             10 => 4,
103             11 => 4,
104             12 => 4,
105             13 => 4,
106             14 => 4,
107             15 => 4,
108             16 => 4,
109             17 => 5,
110             18 => 5,
111             19 => 5,
112             20 => 5,
113             21 => 5,
114             22 => 5,
115             23 => 5,
116             24 => 5,
117             25 => 5,
118             26 => 5,
119             27 => 5,
120             28 => 5,
121             29 => 5,
122             30 => 5,
123             31 => 5,
124             32 => 5,
125             33 => 6,
126             34 => 6,
127             35 => 6,
128             36 => 6,
129             // Invalid radix
130             _  => unreachable!(),
131         }
132     }
133 }
134 
135 // TESTS
136 // -----
137 
138 #[cfg(test)]
139 mod test {
140     use super::*;
141 
check_parse_exponent(radix: u32, s: &str, tup: (i32, usize))142     fn check_parse_exponent(radix: u32, s: &str, tup: (i32, usize)) {
143         let (value, slc) = parse_exponent(radix, s.as_bytes());
144         assert_eq!(value, tup.0);
145         assert_eq!(distance(s.as_ptr(), slc.as_ptr()), tup.1);
146     }
147 
148     #[test]
parse_exponent_test()149     fn parse_exponent_test() {
150         // empty
151         check_parse_exponent(10, "", (0, 0));
152 
153         // invalid exponent character
154         #[cfg(feature = "radix")]
155         check_parse_exponent(28, "e1h", (0, 0));
156         check_parse_exponent(10, "^45", (0, 0));
157 
158         // trailing characters
159         check_parse_exponent(10, "e45 ", (45, 3));
160         check_parse_exponent(10, "e45-", (45, 3));
161         check_parse_exponent(10, "e45+", (45, 3));
162         check_parse_exponent(10, "e45a", (45, 3));
163 
164         // positive
165         check_parse_exponent(10, "e+45", (45, 4));
166 
167         // negative
168         check_parse_exponent(10, "e-45", (-45, 4));
169 
170         // overflow
171         check_parse_exponent(10, "e3000000000", (i32::max_value(), 11));
172         check_parse_exponent(10, "e+3000000000", (i32::max_value(), 12));
173         check_parse_exponent(10, "e-3000000000", (-i32::max_value(), 12));
174 
175         // lowercase
176         check_parse_exponent(10, "e45", (45, 3));
177         check_parse_exponent(10, "e+45", (45, 4));
178         check_parse_exponent(10, "e-45", (-45, 4));
179         check_parse_exponent(10, "e20", (20, 3));
180         check_parse_exponent(10, "e+20", (20, 4));
181         check_parse_exponent(10, "e-20", (-20, 4));
182 
183         // uppercase
184         check_parse_exponent(10, "E45", (45, 3));
185         check_parse_exponent(10, "E+45", (45, 4));
186         check_parse_exponent(10, "E-45", (-45, 4));
187         check_parse_exponent(10, "E20", (20, 3));
188         check_parse_exponent(10, "E+20", (20, 4));
189         check_parse_exponent(10, "E-20", (-20, 4));
190 
191         // overflow
192         check_parse_exponent(10, "e10000000000", (i32::max_value(), 12));
193         check_parse_exponent(10, "e+10000000000", (i32::max_value(), 13));
194         check_parse_exponent(10, "e-10000000000", (-i32::max_value(), 13));
195 
196         #[cfg(feature = "radix")] {
197             let data = [
198                 (2, "e101101"),
199                 (3, "e1200"),
200                 (4, "e231"),
201                 (5, "e140"),
202                 (6, "e113"),
203                 (7, "e63"),
204                 (8, "e55"),
205                 (9, "e50"),
206                 (10, "e45"),
207                 (11, "e41"),
208                 (12, "e39"),
209                 (13, "e36"),
210                 (14, "e33"),
211                 (15, "^30"),
212                 (16, "^2d"),
213                 (17, "^2b"),
214                 (18, "^29"),
215                 (19, "^27"),
216                 (20, "^25"),
217                 (21, "^23"),
218                 (22, "^21"),
219                 (23, "^1m"),
220                 (24, "^1l"),
221                 (25, "^1k"),
222                 (26, "^1j"),
223                 (27, "^1i"),
224                 (28, "^1h"),
225                 (29, "^1g"),
226                 (30, "^1f"),
227                 (31, "^1e"),
228                 (32, "^1d"),
229                 (33, "^1c"),
230                 (34, "^1b"),
231                 (35, "^1a"),
232                 (36, "^19")
233             ];
234             // basen
235             for item in data.iter() {
236                 check_parse_exponent(item.0, item.1, (45, item.1.len()));
237             }
238 
239             // >= base15
240             check_parse_exponent(15, "^20", (30, 3));
241             check_parse_exponent(15, "^+20", (30, 4));
242             check_parse_exponent(15, "^-20", (-30, 4));
243         }
244     }
245 
246     #[cfg(feature = "correct")]
247     #[test]
scientific_exponent_test()248     fn scientific_exponent_test() {
249         // 0 digits in the integer
250         assert_eq!(scientific_exponent(0, 0, 5), -6);
251         assert_eq!(scientific_exponent(10, 0, 5), 4);
252         assert_eq!(scientific_exponent(-10, 0, 5), -16);
253 
254         // >0 digits in the integer
255         assert_eq!(scientific_exponent(0, 1, 5), 0);
256         assert_eq!(scientific_exponent(0, 2, 5), 1);
257         assert_eq!(scientific_exponent(0, 2, 20), 1);
258         assert_eq!(scientific_exponent(10, 2, 20), 11);
259         assert_eq!(scientific_exponent(-10, 2, 20), -9);
260 
261         // Underflow
262         assert_eq!(scientific_exponent(i32::min_value(), 0, 0), i32::min_value());
263         assert_eq!(scientific_exponent(i32::min_value(), 0, 5), i32::min_value());
264 
265         // Overflow
266         assert_eq!(scientific_exponent(i32::max_value(), 0, 0), i32::max_value()-1);
267         assert_eq!(scientific_exponent(i32::max_value(), 5, 0), i32::max_value());
268     }
269 
270     #[cfg(feature = "correct")]
271     #[test]
mantissa_exponent_test()272     fn mantissa_exponent_test() {
273         assert_eq!(mantissa_exponent(10, 5, 0), 5);
274         assert_eq!(mantissa_exponent(0, 5, 0), -5);
275         assert_eq!(mantissa_exponent(i32::max_value(), 5, 0), i32::max_value()-5);
276         assert_eq!(mantissa_exponent(i32::max_value(), 0, 5), i32::max_value());
277         assert_eq!(mantissa_exponent(i32::min_value(), 5, 0), i32::min_value());
278         assert_eq!(mantissa_exponent(i32::min_value(), 0, 5), i32::min_value()+5);
279     }
280 
281     #[cfg(all(feature = "correct", feature = "radix"))]
282     #[test]
integral_binary_factor_test()283     fn integral_binary_factor_test() {
284         const TABLE: [u32; 35] = [1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6];
285         for (idx, base) in (2..37).enumerate() {
286             assert_eq!(integral_binary_factor(base), TABLE[idx]);
287         }
288     }
289 }
290