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