]>
Commit | Line | Data |
---|---|---|
ba9703b0 | 1 | use std::{fmt, str}; |
d9579d0f | 2 | |
dfeec247 XL |
3 | use core::num::flt2dec::{decode, DecodableFloat, Decoded, FullDecoded}; |
4 | use core::num::flt2dec::{round_up, Formatted, Part, Sign, MAX_SIG_DIGITS}; | |
5 | use core::num::flt2dec::{ | |
6 | to_exact_exp_str, to_exact_fixed_str, to_shortest_exp_str, to_shortest_str, | |
7 | }; | |
d9579d0f AL |
8 | |
9 | pub use test::Bencher; | |
10 | ||
11 | mod estimator; | |
d9579d0f AL |
12 | mod strategy { |
13 | mod dragon; | |
14 | mod grisu; | |
15 | } | |
0531ce1d | 16 | mod random; |
d9579d0f AL |
17 | |
18 | pub fn decode_finite<T: DecodableFloat>(v: T) -> Decoded { | |
19 | match decode(v).1 { | |
20 | FullDecoded::Finite(decoded) => decoded, | |
dfeec247 | 21 | full_decoded => panic!("expected finite, got {:?} instead", full_decoded), |
d9579d0f AL |
22 | } |
23 | } | |
24 | ||
25 | macro_rules! check_shortest { | |
26 | ($f:ident($v:expr) => $buf:expr, $exp:expr) => ( | |
27 | check_shortest!($f($v) => $buf, $exp; | |
28 | "shortest mismatch for v={v}: actual {actual:?}, expected {expected:?}", | |
29 | v = stringify!($v)) | |
30 | ); | |
31 | ||
32 | ($f:ident{$($k:ident: $v:expr),+} => $buf:expr, $exp:expr) => ( | |
33 | check_shortest!($f{$($k: $v),+} => $buf, $exp; | |
34 | "shortest mismatch for {v:?}: actual {actual:?}, expected {expected:?}", | |
35 | v = Decoded { $($k: $v),+ }) | |
36 | ); | |
37 | ||
38 | ($f:ident($v:expr) => $buf:expr, $exp:expr; $fmt:expr, $($key:ident = $val:expr),*) => ({ | |
39 | let mut buf = [b'_'; MAX_SIG_DIGITS]; | |
40 | let (len, k) = $f(&decode_finite($v), &mut buf); | |
41 | assert!((&buf[..len], k) == ($buf, $exp), | |
42 | $fmt, actual = (str::from_utf8(&buf[..len]).unwrap(), k), | |
43 | expected = (str::from_utf8($buf).unwrap(), $exp), | |
44 | $($key = $val),*); | |
45 | }); | |
46 | ||
47 | ($f:ident{$($k:ident: $v:expr),+} => $buf:expr, $exp:expr; | |
48 | $fmt:expr, $($key:ident = $val:expr),*) => ({ | |
49 | let mut buf = [b'_'; MAX_SIG_DIGITS]; | |
50 | let (len, k) = $f(&Decoded { $($k: $v),+ }, &mut buf); | |
51 | assert!((&buf[..len], k) == ($buf, $exp), | |
52 | $fmt, actual = (str::from_utf8(&buf[..len]).unwrap(), k), | |
53 | expected = (str::from_utf8($buf).unwrap(), $exp), | |
54 | $($key = $val),*); | |
55 | }) | |
56 | } | |
57 | ||
58 | macro_rules! try_exact { | |
59 | ($f:ident($decoded:expr) => $buf:expr, $expected:expr, $expectedk:expr; | |
60 | $fmt:expr, $($key:ident = $val:expr),*) => ({ | |
61 | let (len, k) = $f($decoded, &mut $buf[..$expected.len()], i16::MIN); | |
62 | assert!((&$buf[..len], k) == ($expected, $expectedk), | |
63 | $fmt, actual = (str::from_utf8(&$buf[..len]).unwrap(), k), | |
64 | expected = (str::from_utf8($expected).unwrap(), $expectedk), | |
65 | $($key = $val),*); | |
66 | }) | |
67 | } | |
68 | ||
69 | macro_rules! try_fixed { | |
70 | ($f:ident($decoded:expr) => $buf:expr, $request:expr, $expected:expr, $expectedk:expr; | |
71 | $fmt:expr, $($key:ident = $val:expr),*) => ({ | |
72 | let (len, k) = $f($decoded, &mut $buf[..], $request); | |
73 | assert!((&$buf[..len], k) == ($expected, $expectedk), | |
74 | $fmt, actual = (str::from_utf8(&$buf[..len]).unwrap(), k), | |
75 | expected = (str::from_utf8($expected).unwrap(), $expectedk), | |
76 | $($key = $val),*); | |
77 | }) | |
78 | } | |
79 | ||
3157f602 XL |
80 | fn ldexp_f32(a: f32, b: i32) -> f32 { |
81 | ldexp_f64(a as f64, b) as f32 | |
82 | } | |
83 | ||
84 | fn ldexp_f64(a: f64, b: i32) -> f64 { | |
dfeec247 | 85 | extern "C" { |
3157f602 XL |
86 | fn ldexp(x: f64, n: i32) -> f64; |
87 | } | |
60c5eb7d XL |
88 | // SAFETY: assuming a correct `ldexp` has been supplied, the given arguments cannot possibly |
89 | // cause undefined behavior | |
3157f602 XL |
90 | unsafe { ldexp(a, b) } |
91 | } | |
92 | ||
d9579d0f | 93 | fn check_exact<F, T>(mut f: F, v: T, vstr: &str, expected: &[u8], expectedk: i16) |
dfeec247 XL |
94 | where |
95 | T: DecodableFloat, | |
96 | F: FnMut(&Decoded, &mut [u8], i16) -> (usize, i16), | |
97 | { | |
d9579d0f AL |
98 | // use a large enough buffer |
99 | let mut buf = [b'_'; 1024]; | |
100 | let mut expected_ = [b'_'; 1024]; | |
101 | ||
102 | let decoded = decode_finite(v); | |
103 | let cut = expected.iter().position(|&c| c == b' '); | |
104 | ||
105 | // check significant digits | |
106 | for i in 1..cut.unwrap_or(expected.len() - 1) { | |
7453a54e | 107 | expected_[..i].copy_from_slice(&expected[..i]); |
d9579d0f AL |
108 | let mut expectedk_ = expectedk; |
109 | if expected[i] >= b'5' { | |
110 | // check if this is a rounding-to-even case. | |
111 | // we avoid rounding ...x5000... (with infinite zeroes) to ...(x+1) when x is even. | |
dfeec247 XL |
112 | if !(i + 1 < expected.len() |
113 | && expected[i - 1] & 1 == 0 | |
114 | && expected[i] == b'5' | |
115 | && expected[i + 1] == b' ') | |
116 | { | |
d9579d0f AL |
117 | // if this returns true, expected_[..i] is all `9`s and being rounded up. |
118 | // we should always return `100..00` (`i` digits) instead, since that's | |
119 | // what we can came up with `i` digits anyway. `round_up` assumes that | |
120 | // the adjustment to the length is done by caller, which we simply ignore. | |
dfeec247 XL |
121 | if let Some(_) = round_up(&mut expected_, i) { |
122 | expectedk_ += 1; | |
123 | } | |
d9579d0f AL |
124 | } |
125 | } | |
126 | ||
127 | try_exact!(f(&decoded) => &mut buf, &expected_[..i], expectedk_; | |
128 | "exact sigdigit mismatch for v={v}, i={i}: \ | |
129 | actual {actual:?}, expected {expected:?}", | |
130 | v = vstr, i = i); | |
131 | try_fixed!(f(&decoded) => &mut buf, expectedk_ - i as i16, &expected_[..i], expectedk_; | |
132 | "fixed sigdigit mismatch for v={v}, i={i}: \ | |
133 | actual {actual:?}, expected {expected:?}", | |
134 | v = vstr, i = i); | |
135 | } | |
136 | ||
137 | // check exact rounding for zero- and negative-width cases | |
138 | let start; | |
139 | if expected[0] >= b'5' { | |
140 | try_fixed!(f(&decoded) => &mut buf, expectedk, b"1", expectedk + 1; | |
141 | "zero-width rounding-up mismatch for v={v}: \ | |
142 | actual {actual:?}, expected {expected:?}", | |
143 | v = vstr); | |
144 | start = 1; | |
145 | } else { | |
146 | start = 0; | |
147 | } | |
148 | for i in start..-10 { | |
149 | try_fixed!(f(&decoded) => &mut buf, expectedk - i, b"", expectedk; | |
150 | "rounding-down mismatch for v={v}, i={i}: \ | |
151 | actual {actual:?}, expected {expected:?}", | |
152 | v = vstr, i = -i); | |
153 | } | |
154 | ||
155 | // check infinite zero digits | |
156 | if let Some(cut) = cut { | |
dfeec247 | 157 | for i in cut..expected.len() - 1 { |
7453a54e | 158 | expected_[..cut].copy_from_slice(&expected[..cut]); |
dfeec247 XL |
159 | for c in &mut expected_[cut..i] { |
160 | *c = b'0'; | |
161 | } | |
d9579d0f AL |
162 | |
163 | try_exact!(f(&decoded) => &mut buf, &expected_[..i], expectedk; | |
164 | "exact infzero mismatch for v={v}, i={i}: \ | |
165 | actual {actual:?}, expected {expected:?}", | |
166 | v = vstr, i = i); | |
167 | try_fixed!(f(&decoded) => &mut buf, expectedk - i as i16, &expected_[..i], expectedk; | |
168 | "fixed infzero mismatch for v={v}, i={i}: \ | |
169 | actual {actual:?}, expected {expected:?}", | |
170 | v = vstr, i = i); | |
171 | } | |
172 | } | |
173 | } | |
174 | ||
dfeec247 | 175 | trait TestableFloat: DecodableFloat + fmt::Display { |
e9174d1e SL |
176 | /// Returns `x * 2^exp`. Almost same to `std::{f32,f64}::ldexp`. |
177 | /// This is used for testing. | |
178 | fn ldexpi(f: i64, exp: isize) -> Self; | |
179 | } | |
180 | ||
181 | impl TestableFloat for f32 { | |
dfeec247 XL |
182 | fn ldexpi(f: i64, exp: isize) -> Self { |
183 | f as Self * (exp as Self).exp2() | |
184 | } | |
e9174d1e SL |
185 | } |
186 | ||
187 | impl TestableFloat for f64 { | |
dfeec247 XL |
188 | fn ldexpi(f: i64, exp: isize) -> Self { |
189 | f as Self * (exp as Self).exp2() | |
190 | } | |
e9174d1e SL |
191 | } |
192 | ||
d9579d0f | 193 | fn check_exact_one<F, T>(mut f: F, x: i64, e: isize, tstr: &str, expected: &[u8], expectedk: i16) |
dfeec247 XL |
194 | where |
195 | T: TestableFloat, | |
196 | F: FnMut(&Decoded, &mut [u8], i16) -> (usize, i16), | |
197 | { | |
d9579d0f AL |
198 | // use a large enough buffer |
199 | let mut buf = [b'_'; 1024]; | |
e9174d1e | 200 | let v: T = TestableFloat::ldexpi(x, e); |
d9579d0f AL |
201 | let decoded = decode_finite(v); |
202 | ||
203 | try_exact!(f(&decoded) => &mut buf, &expected, expectedk; | |
204 | "exact mismatch for v={x}p{e}{t}: actual {actual:?}, expected {expected:?}", | |
205 | x = x, e = e, t = tstr); | |
206 | try_fixed!(f(&decoded) => &mut buf, expectedk - expected.len() as i16, &expected, expectedk; | |
207 | "fixed mismatch for v={x}p{e}{t}: actual {actual:?}, expected {expected:?}", | |
208 | x = x, e = e, t = tstr); | |
209 | } | |
210 | ||
211 | macro_rules! check_exact { | |
dfeec247 XL |
212 | ($f:ident($v:expr) => $buf:expr, $exp:expr) => { |
213 | check_exact(|d, b, k| $f(d, b, k), $v, stringify!($v), $buf, $exp) | |
214 | }; | |
d9579d0f AL |
215 | } |
216 | ||
217 | macro_rules! check_exact_one { | |
dfeec247 XL |
218 | ($f:ident($x:expr, $e:expr; $t:ty) => $buf:expr, $exp:expr) => { |
219 | check_exact_one::<_, $t>(|d, b, k| $f(d, b, k), $x, $e, stringify!($t), $buf, $exp) | |
220 | }; | |
d9579d0f AL |
221 | } |
222 | ||
223 | // in the following comments, three numbers are spaced by 1 ulp apart, | |
224 | // and the second one is being formatted. | |
225 | // | |
226 | // some tests are derived from [1]. | |
227 | // | |
228 | // [1] Vern Paxson, A Program for Testing IEEE Decimal-Binary Conversion | |
229 | // ftp://ftp.ee.lbl.gov/testbase-report.ps.Z | |
230 | ||
dfeec247 XL |
231 | pub fn f32_shortest_sanity_test<F>(mut f: F) |
232 | where | |
233 | F: FnMut(&Decoded, &mut [u8]) -> (usize, i16), | |
234 | { | |
d9579d0f AL |
235 | // 0.0999999940395355224609375 |
236 | // 0.100000001490116119384765625 | |
237 | // 0.10000000894069671630859375 | |
238 | check_shortest!(f(0.1f32) => b"1", 0); | |
239 | ||
240 | // 0.333333313465118408203125 | |
241 | // 0.3333333432674407958984375 (1/3 in the default rounding) | |
242 | // 0.33333337306976318359375 | |
243 | check_shortest!(f(1.0f32/3.0) => b"33333334", 0); | |
244 | ||
245 | // 10^1 * 0.31415917873382568359375 | |
246 | // 10^1 * 0.31415920257568359375 | |
247 | // 10^1 * 0.31415922641754150390625 | |
248 | check_shortest!(f(3.141592f32) => b"3141592", 1); | |
249 | ||
250 | // 10^18 * 0.31415916243714048 | |
251 | // 10^18 * 0.314159196796878848 | |
252 | // 10^18 * 0.314159231156617216 | |
253 | check_shortest!(f(3.141592e17f32) => b"3141592", 18); | |
254 | ||
255 | // regression test for decoders | |
256 | // 10^8 * 0.3355443 | |
257 | // 10^8 * 0.33554432 | |
258 | // 10^8 * 0.33554436 | |
3157f602 | 259 | check_shortest!(f(ldexp_f32(1.0, 25)) => b"33554432", 8); |
d9579d0f AL |
260 | |
261 | // 10^39 * 0.340282326356119256160033759537265639424 | |
262 | // 10^39 * 0.34028234663852885981170418348451692544 | |
263 | // 10^39 * 0.340282366920938463463374607431768211456 | |
264 | check_shortest!(f(f32::MAX) => b"34028235", 39); | |
265 | ||
266 | // 10^-37 * 0.1175494210692441075487029444849287348827... | |
267 | // 10^-37 * 0.1175494350822287507968736537222245677818... | |
268 | // 10^-37 * 0.1175494490952133940450443629595204006810... | |
269 | check_shortest!(f(f32::MIN_POSITIVE) => b"11754944", -37); | |
270 | ||
271 | // 10^-44 * 0 | |
272 | // 10^-44 * 0.1401298464324817070923729583289916131280... | |
273 | // 10^-44 * 0.2802596928649634141847459166579832262560... | |
3157f602 | 274 | let minf32 = ldexp_f32(1.0, -149); |
d9579d0f AL |
275 | check_shortest!(f(minf32) => b"1", -44); |
276 | } | |
277 | ||
278 | pub fn f32_exact_sanity_test<F>(mut f: F) | |
dfeec247 XL |
279 | where |
280 | F: FnMut(&Decoded, &mut [u8], i16) -> (usize, i16), | |
281 | { | |
3157f602 | 282 | let minf32 = ldexp_f32(1.0, -149); |
d9579d0f AL |
283 | |
284 | check_exact!(f(0.1f32) => b"100000001490116119384765625 ", 0); | |
285 | check_exact!(f(0.5f32) => b"5 ", 0); | |
286 | check_exact!(f(1.0f32/3.0) => b"3333333432674407958984375 ", 0); | |
287 | check_exact!(f(3.141592f32) => b"31415920257568359375 ", 1); | |
288 | check_exact!(f(3.141592e17f32) => b"314159196796878848 ", 18); | |
289 | check_exact!(f(f32::MAX) => b"34028234663852885981170418348451692544 ", 39); | |
290 | check_exact!(f(f32::MIN_POSITIVE) => b"1175494350822287507968736537222245677818", -37); | |
291 | check_exact!(f(minf32) => b"1401298464324817070923729583289916131280", -44); | |
292 | ||
293 | // [1], Table 16: Stress Inputs for Converting 24-bit Binary to Decimal, < 1/2 ULP | |
294 | check_exact_one!(f(12676506, -102; f32) => b"2", -23); | |
295 | check_exact_one!(f(12676506, -103; f32) => b"12", -23); | |
296 | check_exact_one!(f(15445013, 86; f32) => b"119", 34); | |
297 | check_exact_one!(f(13734123, -138; f32) => b"3941", -34); | |
298 | check_exact_one!(f(12428269, -130; f32) => b"91308", -32); | |
299 | check_exact_one!(f(15334037, -146; f32) => b"171900", -36); | |
300 | check_exact_one!(f(11518287, -41; f32) => b"5237910", -5); | |
301 | check_exact_one!(f(12584953, -145; f32) => b"28216440", -36); | |
302 | check_exact_one!(f(15961084, -125; f32) => b"375243281", -30); | |
303 | check_exact_one!(f(14915817, -146; f32) => b"1672120916", -36); | |
304 | check_exact_one!(f(10845484, -102; f32) => b"21388945814", -23); | |
305 | check_exact_one!(f(16431059, -61; f32) => b"712583594561", -11); | |
306 | ||
307 | // [1], Table 17: Stress Inputs for Converting 24-bit Binary to Decimal, > 1/2 ULP | |
308 | check_exact_one!(f(16093626, 69; f32) => b"1", 29); | |
309 | check_exact_one!(f( 9983778, 25; f32) => b"34", 15); | |
310 | check_exact_one!(f(12745034, 104; f32) => b"259", 39); | |
311 | check_exact_one!(f(12706553, 72; f32) => b"6001", 29); | |
312 | check_exact_one!(f(11005028, 45; f32) => b"38721", 21); | |
313 | check_exact_one!(f(15059547, 71; f32) => b"355584", 29); | |
314 | check_exact_one!(f(16015691, -99; f32) => b"2526831", -22); | |
315 | check_exact_one!(f( 8667859, 56; f32) => b"62458507", 24); | |
316 | check_exact_one!(f(14855922, -82; f32) => b"307213267", -17); | |
317 | check_exact_one!(f(14855922, -83; f32) => b"1536066333", -17); | |
318 | check_exact_one!(f(10144164, -110; f32) => b"78147796834", -26); | |
319 | check_exact_one!(f(13248074, 95; f32) => b"524810279937", 36); | |
320 | } | |
321 | ||
dfeec247 XL |
322 | pub fn f64_shortest_sanity_test<F>(mut f: F) |
323 | where | |
324 | F: FnMut(&Decoded, &mut [u8]) -> (usize, i16), | |
325 | { | |
d9579d0f AL |
326 | // 0.0999999999999999777955395074968691915273... |
327 | // 0.1000000000000000055511151231257827021181... | |
328 | // 0.1000000000000000333066907387546962127089... | |
329 | check_shortest!(f(0.1f64) => b"1", 0); | |
330 | ||
331 | // this example is explicitly mentioned in the paper. | |
332 | // 10^3 * 0.0999999999999999857891452847979962825775... | |
333 | // 10^3 * 0.1 (exact) | |
334 | // 10^3 * 0.1000000000000000142108547152020037174224... | |
335 | check_shortest!(f(100.0f64) => b"1", 3); | |
336 | ||
337 | // 0.3333333333333332593184650249895639717578... | |
338 | // 0.3333333333333333148296162562473909929394... (1/3 in the default rounding) | |
339 | // 0.3333333333333333703407674875052180141210... | |
340 | check_shortest!(f(1.0f64/3.0) => b"3333333333333333", 0); | |
341 | ||
342 | // explicit test case for equally closest representations. | |
343 | // Dragon has its own tie-breaking rule; Grisu should fall back. | |
344 | // 10^1 * 0.1000007629394531027955395074968691915273... | |
345 | // 10^1 * 0.100000762939453125 (exact) | |
346 | // 10^1 * 0.1000007629394531472044604925031308084726... | |
347 | check_shortest!(f(1.00000762939453125f64) => b"10000076293945313", 1); | |
348 | ||
349 | // 10^1 * 0.3141591999999999718085064159822650253772... | |
350 | // 10^1 * 0.3141592000000000162174274009885266423225... | |
351 | // 10^1 * 0.3141592000000000606263483859947882592678... | |
352 | check_shortest!(f(3.141592f64) => b"3141592", 1); | |
353 | ||
354 | // 10^18 * 0.314159199999999936 | |
355 | // 10^18 * 0.3141592 (exact) | |
356 | // 10^18 * 0.314159200000000064 | |
357 | check_shortest!(f(3.141592e17f64) => b"3141592", 18); | |
358 | ||
359 | // regression test for decoders | |
360 | // 10^20 * 0.18446744073709549568 | |
361 | // 10^20 * 0.18446744073709551616 | |
362 | // 10^20 * 0.18446744073709555712 | |
3157f602 | 363 | check_shortest!(f(ldexp_f64(1.0, 64)) => b"18446744073709552", 20); |
d9579d0f AL |
364 | |
365 | // pathological case: high = 10^23 (exact). tie breaking should always prefer that. | |
366 | // 10^24 * 0.099999999999999974834176 | |
367 | // 10^24 * 0.099999999999999991611392 | |
368 | // 10^24 * 0.100000000000000008388608 | |
369 | check_shortest!(f(1.0e23f64) => b"1", 24); | |
370 | ||
371 | // 10^309 * 0.1797693134862315508561243283845062402343... | |
372 | // 10^309 * 0.1797693134862315708145274237317043567980... | |
373 | // 10^309 * 0.1797693134862315907729305190789024733617... | |
374 | check_shortest!(f(f64::MAX) => b"17976931348623157", 309); | |
375 | ||
376 | // 10^-307 * 0.2225073858507200889024586876085859887650... | |
377 | // 10^-307 * 0.2225073858507201383090232717332404064219... | |
378 | // 10^-307 * 0.2225073858507201877155878558578948240788... | |
379 | check_shortest!(f(f64::MIN_POSITIVE) => b"22250738585072014", -307); | |
380 | ||
381 | // 10^-323 * 0 | |
382 | // 10^-323 * 0.4940656458412465441765687928682213723650... | |
383 | // 10^-323 * 0.9881312916824930883531375857364427447301... | |
3157f602 | 384 | let minf64 = ldexp_f64(1.0, -1074); |
d9579d0f AL |
385 | check_shortest!(f(minf64) => b"5", -323); |
386 | } | |
387 | ||
388 | pub fn f64_exact_sanity_test<F>(mut f: F) | |
dfeec247 XL |
389 | where |
390 | F: FnMut(&Decoded, &mut [u8], i16) -> (usize, i16), | |
391 | { | |
3157f602 | 392 | let minf64 = ldexp_f64(1.0, -1074); |
d9579d0f AL |
393 | |
394 | check_exact!(f(0.1f64) => b"1000000000000000055511151231257827021181", 0); | |
395 | check_exact!(f(0.45f64) => b"4500000000000000111022302462515654042363", 0); | |
396 | check_exact!(f(0.5f64) => b"5 ", 0); | |
397 | check_exact!(f(0.95f64) => b"9499999999999999555910790149937383830547", 0); | |
398 | check_exact!(f(100.0f64) => b"1 ", 3); | |
399 | check_exact!(f(999.5f64) => b"9995000000000000000000000000000000000000", 3); | |
400 | check_exact!(f(1.0f64/3.0) => b"3333333333333333148296162562473909929394", 0); | |
401 | check_exact!(f(3.141592f64) => b"3141592000000000162174274009885266423225", 1); | |
402 | check_exact!(f(3.141592e17f64) => b"3141592 ", 18); | |
403 | check_exact!(f(1.0e23f64) => b"99999999999999991611392 ", 23); | |
404 | check_exact!(f(f64::MAX) => b"1797693134862315708145274237317043567980", 309); | |
405 | check_exact!(f(f64::MIN_POSITIVE) => b"2225073858507201383090232717332404064219", -307); | |
406 | check_exact!(f(minf64) => b"4940656458412465441765687928682213723650\ | |
407 | 5980261432476442558568250067550727020875\ | |
408 | 1865299836361635992379796564695445717730\ | |
409 | 9266567103559397963987747960107818781263\ | |
410 | 0071319031140452784581716784898210368871\ | |
411 | 8636056998730723050006387409153564984387\ | |
412 | 3124733972731696151400317153853980741262\ | |
413 | 3856559117102665855668676818703956031062\ | |
414 | 4931945271591492455329305456544401127480\ | |
415 | 1297099995419319894090804165633245247571\ | |
416 | 4786901472678015935523861155013480352649\ | |
417 | 3472019379026810710749170333222684475333\ | |
418 | 5720832431936092382893458368060106011506\ | |
419 | 1698097530783422773183292479049825247307\ | |
420 | 7637592724787465608477820373446969953364\ | |
421 | 7017972677717585125660551199131504891101\ | |
422 | 4510378627381672509558373897335989936648\ | |
423 | 0994116420570263709027924276754456522908\ | |
424 | 7538682506419718265533447265625 ", -323); | |
425 | ||
426 | // [1], Table 3: Stress Inputs for Converting 53-bit Binary to Decimal, < 1/2 ULP | |
427 | check_exact_one!(f(8511030020275656, -342; f64) => b"9", -87); | |
428 | check_exact_one!(f(5201988407066741, -824; f64) => b"46", -232); | |
429 | check_exact_one!(f(6406892948269899, 237; f64) => b"141", 88); | |
430 | check_exact_one!(f(8431154198732492, 72; f64) => b"3981", 38); | |
431 | check_exact_one!(f(6475049196144587, 99; f64) => b"41040", 46); | |
432 | check_exact_one!(f(8274307542972842, 726; f64) => b"292084", 235); | |
433 | check_exact_one!(f(5381065484265332, -456; f64) => b"2891946", -121); | |
434 | check_exact_one!(f(6761728585499734, -1057; f64) => b"43787718", -302); | |
435 | check_exact_one!(f(7976538478610756, 376; f64) => b"122770163", 130); | |
436 | check_exact_one!(f(5982403858958067, 377; f64) => b"1841552452", 130); | |
437 | check_exact_one!(f(5536995190630837, 93; f64) => b"54835744350", 44); | |
438 | check_exact_one!(f(7225450889282194, 710; f64) => b"389190181146", 230); | |
439 | check_exact_one!(f(7225450889282194, 709; f64) => b"1945950905732", 230); | |
440 | check_exact_one!(f(8703372741147379, 117; f64) => b"14460958381605", 52); | |
441 | check_exact_one!(f(8944262675275217, -1001; f64) => b"417367747458531", -285); | |
442 | check_exact_one!(f(7459803696087692, -707; f64) => b"1107950772878888", -196); | |
443 | check_exact_one!(f(6080469016670379, -381; f64) => b"12345501366327440", -98); | |
444 | check_exact_one!(f(8385515147034757, 721; f64) => b"925031711960365024", 233); | |
445 | check_exact_one!(f(7514216811389786, -828; f64) => b"4198047150284889840", -233); | |
446 | check_exact_one!(f(8397297803260511, -345; f64) => b"11716315319786511046", -87); | |
447 | check_exact_one!(f(6733459239310543, 202; f64) => b"432810072844612493629", 77); | |
448 | check_exact_one!(f(8091450587292794, -473; f64) => b"3317710118160031081518", -126); | |
449 | ||
450 | // [1], Table 4: Stress Inputs for Converting 53-bit Binary to Decimal, > 1/2 ULP | |
451 | check_exact_one!(f(6567258882077402, 952; f64) => b"3", 303); | |
452 | check_exact_one!(f(6712731423444934, 535; f64) => b"76", 177); | |
453 | check_exact_one!(f(6712731423444934, 534; f64) => b"378", 177); | |
454 | check_exact_one!(f(5298405411573037, -957; f64) => b"4350", -272); | |
455 | check_exact_one!(f(5137311167659507, -144; f64) => b"23037", -27); | |
456 | check_exact_one!(f(6722280709661868, 363; f64) => b"126301", 126); | |
457 | check_exact_one!(f(5344436398034927, -169; f64) => b"7142211", -35); | |
458 | check_exact_one!(f(8369123604277281, -853; f64) => b"13934574", -240); | |
459 | check_exact_one!(f(8995822108487663, -780; f64) => b"141463449", -218); | |
460 | check_exact_one!(f(8942832835564782, -383; f64) => b"4539277920", -99); | |
461 | check_exact_one!(f(8942832835564782, -384; f64) => b"22696389598", -99); | |
462 | check_exact_one!(f(8942832835564782, -385; f64) => b"113481947988", -99); | |
463 | check_exact_one!(f(6965949469487146, -249; f64) => b"7700366561890", -59); | |
464 | check_exact_one!(f(6965949469487146, -250; f64) => b"38501832809448", -59); | |
465 | check_exact_one!(f(6965949469487146, -251; f64) => b"192509164047238", -59); | |
466 | check_exact_one!(f(7487252720986826, 548; f64) => b"6898586531774201", 181); | |
467 | check_exact_one!(f(5592117679628511, 164; f64) => b"13076622631878654", 66); | |
468 | check_exact_one!(f(8887055249355788, 665; f64) => b"136052020756121240", 217); | |
469 | check_exact_one!(f(6994187472632449, 690; f64) => b"3592810217475959676", 224); | |
470 | check_exact_one!(f(8797576579012143, 588; f64) => b"89125197712484551899", 193); | |
471 | check_exact_one!(f(7363326733505337, 272; f64) => b"558769757362301140950", 98); | |
472 | check_exact_one!(f(8549497411294502, -448; f64) => b"1176257830728540379990", -118); | |
473 | } | |
474 | ||
dfeec247 XL |
475 | pub fn more_shortest_sanity_test<F>(mut f: F) |
476 | where | |
477 | F: FnMut(&Decoded, &mut [u8]) -> (usize, i16), | |
478 | { | |
d9579d0f AL |
479 | check_shortest!(f{mant: 99_999_999_999_999_999, minus: 1, plus: 1, |
480 | exp: 0, inclusive: true} => b"1", 18); | |
481 | check_shortest!(f{mant: 99_999_999_999_999_999, minus: 1, plus: 1, | |
482 | exp: 0, inclusive: false} => b"99999999999999999", 17); | |
483 | } | |
484 | ||
d9579d0f | 485 | fn to_string_with_parts<F>(mut f: F) -> String |
dfeec247 XL |
486 | where |
487 | F: for<'a> FnMut(&'a mut [u8], &'a mut [Part<'a>]) -> Formatted<'a>, | |
488 | { | |
d9579d0f AL |
489 | let mut buf = [0; 1024]; |
490 | let mut parts = [Part::Zero(0); 16]; | |
491 | let formatted = f(&mut buf, &mut parts); | |
492 | let mut ret = vec![0; formatted.len()]; | |
493 | assert_eq!(formatted.write(&mut ret), Some(ret.len())); | |
494 | String::from_utf8(ret).unwrap() | |
495 | } | |
496 | ||
497 | pub fn to_shortest_str_test<F>(mut f_: F) | |
dfeec247 XL |
498 | where |
499 | F: FnMut(&Decoded, &mut [u8]) -> (usize, i16), | |
500 | { | |
d9579d0f AL |
501 | use core::num::flt2dec::Sign::*; |
502 | ||
74b04a01 | 503 | fn to_string<T, F>(f: &mut F, v: T, sign: Sign, frac_digits: usize) -> String |
dfeec247 XL |
504 | where |
505 | T: DecodableFloat, | |
506 | F: FnMut(&Decoded, &mut [u8]) -> (usize, i16), | |
507 | { | |
508 | to_string_with_parts(|buf, parts| { | |
74b04a01 | 509 | to_shortest_str(|d, b| f(d, b), v, sign, frac_digits, buf, parts) |
dfeec247 | 510 | }) |
d9579d0f AL |
511 | } |
512 | ||
513 | let f = &mut f_; | |
514 | ||
74b04a01 XL |
515 | assert_eq!(to_string(f, 0.0, Minus, 0), "0"); |
516 | assert_eq!(to_string(f, 0.0, MinusRaw, 0), "0"); | |
517 | assert_eq!(to_string(f, 0.0, MinusPlus, 0), "+0"); | |
518 | assert_eq!(to_string(f, 0.0, MinusPlusRaw, 0), "+0"); | |
519 | assert_eq!(to_string(f, -0.0, Minus, 0), "0"); | |
520 | assert_eq!(to_string(f, -0.0, MinusRaw, 0), "-0"); | |
521 | assert_eq!(to_string(f, -0.0, MinusPlus, 0), "+0"); | |
522 | assert_eq!(to_string(f, -0.0, MinusPlusRaw, 0), "-0"); | |
523 | assert_eq!(to_string(f, 0.0, Minus, 1), "0.0"); | |
524 | assert_eq!(to_string(f, 0.0, MinusRaw, 1), "0.0"); | |
525 | assert_eq!(to_string(f, 0.0, MinusPlus, 1), "+0.0"); | |
526 | assert_eq!(to_string(f, 0.0, MinusPlusRaw, 1), "+0.0"); | |
527 | assert_eq!(to_string(f, -0.0, Minus, 8), "0.00000000"); | |
528 | assert_eq!(to_string(f, -0.0, MinusRaw, 8), "-0.00000000"); | |
529 | assert_eq!(to_string(f, -0.0, MinusPlus, 8), "+0.00000000"); | |
530 | assert_eq!(to_string(f, -0.0, MinusPlusRaw, 8), "-0.00000000"); | |
531 | ||
532 | assert_eq!(to_string(f, 1.0 / 0.0, Minus, 0), "inf"); | |
533 | assert_eq!(to_string(f, 1.0 / 0.0, MinusRaw, 0), "inf"); | |
534 | assert_eq!(to_string(f, 1.0 / 0.0, MinusPlus, 0), "+inf"); | |
535 | assert_eq!(to_string(f, 1.0 / 0.0, MinusPlusRaw, 0), "+inf"); | |
536 | assert_eq!(to_string(f, 0.0 / 0.0, Minus, 0), "NaN"); | |
537 | assert_eq!(to_string(f, 0.0 / 0.0, MinusRaw, 1), "NaN"); | |
538 | assert_eq!(to_string(f, 0.0 / 0.0, MinusPlus, 8), "NaN"); | |
539 | assert_eq!(to_string(f, 0.0 / 0.0, MinusPlusRaw, 64), "NaN"); | |
540 | assert_eq!(to_string(f, -1.0 / 0.0, Minus, 0), "-inf"); | |
541 | assert_eq!(to_string(f, -1.0 / 0.0, MinusRaw, 1), "-inf"); | |
542 | assert_eq!(to_string(f, -1.0 / 0.0, MinusPlus, 8), "-inf"); | |
543 | assert_eq!(to_string(f, -1.0 / 0.0, MinusPlusRaw, 64), "-inf"); | |
544 | ||
545 | assert_eq!(to_string(f, 3.14, Minus, 0), "3.14"); | |
546 | assert_eq!(to_string(f, 3.14, MinusRaw, 0), "3.14"); | |
547 | assert_eq!(to_string(f, 3.14, MinusPlus, 0), "+3.14"); | |
548 | assert_eq!(to_string(f, 3.14, MinusPlusRaw, 0), "+3.14"); | |
549 | assert_eq!(to_string(f, -3.14, Minus, 0), "-3.14"); | |
550 | assert_eq!(to_string(f, -3.14, MinusRaw, 0), "-3.14"); | |
551 | assert_eq!(to_string(f, -3.14, MinusPlus, 0), "-3.14"); | |
552 | assert_eq!(to_string(f, -3.14, MinusPlusRaw, 0), "-3.14"); | |
553 | assert_eq!(to_string(f, 3.14, Minus, 1), "3.14"); | |
554 | assert_eq!(to_string(f, 3.14, MinusRaw, 2), "3.14"); | |
555 | assert_eq!(to_string(f, 3.14, MinusPlus, 3), "+3.140"); | |
556 | assert_eq!(to_string(f, 3.14, MinusPlusRaw, 4), "+3.1400"); | |
557 | assert_eq!(to_string(f, -3.14, Minus, 8), "-3.14000000"); | |
558 | assert_eq!(to_string(f, -3.14, MinusRaw, 8), "-3.14000000"); | |
559 | assert_eq!(to_string(f, -3.14, MinusPlus, 8), "-3.14000000"); | |
560 | assert_eq!(to_string(f, -3.14, MinusPlusRaw, 8), "-3.14000000"); | |
561 | ||
562 | assert_eq!(to_string(f, 7.5e-11, Minus, 0), "0.000000000075"); | |
563 | assert_eq!(to_string(f, 7.5e-11, Minus, 3), "0.000000000075"); | |
564 | assert_eq!(to_string(f, 7.5e-11, Minus, 12), "0.000000000075"); | |
565 | assert_eq!(to_string(f, 7.5e-11, Minus, 13), "0.0000000000750"); | |
566 | ||
567 | assert_eq!(to_string(f, 1.9971e20, Minus, 0), "199710000000000000000"); | |
568 | assert_eq!(to_string(f, 1.9971e20, Minus, 1), "199710000000000000000.0"); | |
569 | assert_eq!(to_string(f, 1.9971e20, Minus, 8), "199710000000000000000.00000000"); | |
570 | ||
571 | assert_eq!(to_string(f, f32::MAX, Minus, 0), format!("34028235{:0>31}", "")); | |
572 | assert_eq!(to_string(f, f32::MAX, Minus, 1), format!("34028235{:0>31}.0", "")); | |
573 | assert_eq!(to_string(f, f32::MAX, Minus, 8), format!("34028235{:0>31}.00000000", "")); | |
d9579d0f | 574 | |
3157f602 | 575 | let minf32 = ldexp_f32(1.0, -149); |
74b04a01 XL |
576 | assert_eq!(to_string(f, minf32, Minus, 0), format!("0.{:0>44}1", "")); |
577 | assert_eq!(to_string(f, minf32, Minus, 45), format!("0.{:0>44}1", "")); | |
578 | assert_eq!(to_string(f, minf32, Minus, 46), format!("0.{:0>44}10", "")); | |
d9579d0f | 579 | |
74b04a01 XL |
580 | assert_eq!(to_string(f, f64::MAX, Minus, 0), format!("17976931348623157{:0>292}", "")); |
581 | assert_eq!(to_string(f, f64::MAX, Minus, 1), format!("17976931348623157{:0>292}.0", "")); | |
582 | assert_eq!(to_string(f, f64::MAX, Minus, 8), format!("17976931348623157{:0>292}.00000000", "")); | |
d9579d0f | 583 | |
3157f602 | 584 | let minf64 = ldexp_f64(1.0, -1074); |
74b04a01 XL |
585 | assert_eq!(to_string(f, minf64, Minus, 0), format!("0.{:0>323}5", "")); |
586 | assert_eq!(to_string(f, minf64, Minus, 324), format!("0.{:0>323}5", "")); | |
587 | assert_eq!(to_string(f, minf64, Minus, 325), format!("0.{:0>323}50", "")); | |
d9579d0f | 588 | |
dfeec247 XL |
589 | if cfg!(miri) { |
590 | // Miri is too slow | |
416331ca XL |
591 | return; |
592 | } | |
593 | ||
d9579d0f | 594 | // very large output |
74b04a01 | 595 | assert_eq!(to_string(f, 1.1, Minus, 80000), format!("1.1{:0>79999}", "")); |
d9579d0f AL |
596 | } |
597 | ||
598 | pub fn to_shortest_exp_str_test<F>(mut f_: F) | |
dfeec247 XL |
599 | where |
600 | F: FnMut(&Decoded, &mut [u8]) -> (usize, i16), | |
601 | { | |
d9579d0f AL |
602 | use core::num::flt2dec::Sign::*; |
603 | ||
604 | fn to_string<T, F>(f: &mut F, v: T, sign: Sign, exp_bounds: (i16, i16), upper: bool) -> String | |
dfeec247 XL |
605 | where |
606 | T: DecodableFloat, | |
607 | F: FnMut(&Decoded, &mut [u8]) -> (usize, i16), | |
608 | { | |
609 | to_string_with_parts(|buf, parts| { | |
610 | to_shortest_exp_str(|d, b| f(d, b), v, sign, exp_bounds, upper, buf, parts) | |
611 | }) | |
d9579d0f AL |
612 | } |
613 | ||
614 | let f = &mut f_; | |
615 | ||
dfeec247 XL |
616 | assert_eq!(to_string(f, 0.0, Minus, (-4, 16), false), "0"); |
617 | assert_eq!(to_string(f, 0.0, MinusRaw, (-4, 16), false), "0"); | |
618 | assert_eq!(to_string(f, 0.0, MinusPlus, (-4, 16), false), "+0"); | |
619 | assert_eq!(to_string(f, 0.0, MinusPlusRaw, (-4, 16), false), "+0"); | |
620 | assert_eq!(to_string(f, -0.0, Minus, (-4, 16), false), "0"); | |
621 | assert_eq!(to_string(f, -0.0, MinusRaw, (-4, 16), false), "-0"); | |
622 | assert_eq!(to_string(f, -0.0, MinusPlus, (-4, 16), false), "+0"); | |
d9579d0f | 623 | assert_eq!(to_string(f, -0.0, MinusPlusRaw, (-4, 16), false), "-0"); |
dfeec247 XL |
624 | assert_eq!(to_string(f, 0.0, Minus, (0, 0), true), "0E0"); |
625 | assert_eq!(to_string(f, 0.0, MinusRaw, (0, 0), false), "0e0"); | |
626 | assert_eq!(to_string(f, 0.0, MinusPlus, (-9, -5), true), "+0E0"); | |
627 | assert_eq!(to_string(f, 0.0, MinusPlusRaw, (5, 9), false), "+0e0"); | |
628 | assert_eq!(to_string(f, -0.0, Minus, (0, 0), true), "0E0"); | |
629 | assert_eq!(to_string(f, -0.0, MinusRaw, (0, 0), false), "-0e0"); | |
630 | assert_eq!(to_string(f, -0.0, MinusPlus, (-9, -5), true), "+0E0"); | |
631 | assert_eq!(to_string(f, -0.0, MinusPlusRaw, (5, 9), false), "-0e0"); | |
632 | ||
633 | assert_eq!(to_string(f, 1.0 / 0.0, Minus, (-4, 16), false), "inf"); | |
634 | assert_eq!(to_string(f, 1.0 / 0.0, MinusRaw, (-4, 16), true), "inf"); | |
635 | assert_eq!(to_string(f, 1.0 / 0.0, MinusPlus, (-4, 16), false), "+inf"); | |
636 | assert_eq!(to_string(f, 1.0 / 0.0, MinusPlusRaw, (-4, 16), true), "+inf"); | |
637 | assert_eq!(to_string(f, 0.0 / 0.0, Minus, (0, 0), false), "NaN"); | |
638 | assert_eq!(to_string(f, 0.0 / 0.0, MinusRaw, (0, 0), true), "NaN"); | |
639 | assert_eq!(to_string(f, 0.0 / 0.0, MinusPlus, (-9, -5), false), "NaN"); | |
640 | assert_eq!(to_string(f, 0.0 / 0.0, MinusPlusRaw, (5, 9), true), "NaN"); | |
641 | assert_eq!(to_string(f, -1.0 / 0.0, Minus, (0, 0), false), "-inf"); | |
642 | assert_eq!(to_string(f, -1.0 / 0.0, MinusRaw, (0, 0), true), "-inf"); | |
643 | assert_eq!(to_string(f, -1.0 / 0.0, MinusPlus, (-9, -5), false), "-inf"); | |
644 | assert_eq!(to_string(f, -1.0 / 0.0, MinusPlusRaw, (5, 9), true), "-inf"); | |
645 | ||
646 | assert_eq!(to_string(f, 3.14, Minus, (-4, 16), false), "3.14"); | |
647 | assert_eq!(to_string(f, 3.14, MinusRaw, (-4, 16), false), "3.14"); | |
648 | assert_eq!(to_string(f, 3.14, MinusPlus, (-4, 16), false), "+3.14"); | |
649 | assert_eq!(to_string(f, 3.14, MinusPlusRaw, (-4, 16), false), "+3.14"); | |
650 | assert_eq!(to_string(f, -3.14, Minus, (-4, 16), false), "-3.14"); | |
651 | assert_eq!(to_string(f, -3.14, MinusRaw, (-4, 16), false), "-3.14"); | |
652 | assert_eq!(to_string(f, -3.14, MinusPlus, (-4, 16), false), "-3.14"); | |
d9579d0f | 653 | assert_eq!(to_string(f, -3.14, MinusPlusRaw, (-4, 16), false), "-3.14"); |
dfeec247 XL |
654 | assert_eq!(to_string(f, 3.14, Minus, (0, 0), true), "3.14E0"); |
655 | assert_eq!(to_string(f, 3.14, MinusRaw, (0, 0), false), "3.14e0"); | |
656 | assert_eq!(to_string(f, 3.14, MinusPlus, (-9, -5), true), "+3.14E0"); | |
657 | assert_eq!(to_string(f, 3.14, MinusPlusRaw, (5, 9), false), "+3.14e0"); | |
658 | assert_eq!(to_string(f, -3.14, Minus, (0, 0), true), "-3.14E0"); | |
659 | assert_eq!(to_string(f, -3.14, MinusRaw, (0, 0), false), "-3.14e0"); | |
660 | assert_eq!(to_string(f, -3.14, MinusPlus, (-9, -5), true), "-3.14E0"); | |
661 | assert_eq!(to_string(f, -3.14, MinusPlusRaw, (5, 9), false), "-3.14e0"); | |
662 | ||
663 | assert_eq!(to_string(f, 0.1, Minus, (-4, 16), false), "0.1"); | |
664 | assert_eq!(to_string(f, 0.1, MinusRaw, (-4, 16), false), "0.1"); | |
665 | assert_eq!(to_string(f, 0.1, MinusPlus, (-4, 16), false), "+0.1"); | |
666 | assert_eq!(to_string(f, 0.1, MinusPlusRaw, (-4, 16), false), "+0.1"); | |
667 | assert_eq!(to_string(f, -0.1, Minus, (-4, 16), false), "-0.1"); | |
668 | assert_eq!(to_string(f, -0.1, MinusRaw, (-4, 16), false), "-0.1"); | |
669 | assert_eq!(to_string(f, -0.1, MinusPlus, (-4, 16), false), "-0.1"); | |
d9579d0f | 670 | assert_eq!(to_string(f, -0.1, MinusPlusRaw, (-4, 16), false), "-0.1"); |
dfeec247 XL |
671 | assert_eq!(to_string(f, 0.1, Minus, (0, 0), true), "1E-1"); |
672 | assert_eq!(to_string(f, 0.1, MinusRaw, (0, 0), false), "1e-1"); | |
673 | assert_eq!(to_string(f, 0.1, MinusPlus, (-9, -5), true), "+1E-1"); | |
674 | assert_eq!(to_string(f, 0.1, MinusPlusRaw, (5, 9), false), "+1e-1"); | |
675 | assert_eq!(to_string(f, -0.1, Minus, (0, 0), true), "-1E-1"); | |
676 | assert_eq!(to_string(f, -0.1, MinusRaw, (0, 0), false), "-1e-1"); | |
677 | assert_eq!(to_string(f, -0.1, MinusPlus, (-9, -5), true), "-1E-1"); | |
678 | assert_eq!(to_string(f, -0.1, MinusPlusRaw, (5, 9), false), "-1e-1"); | |
679 | ||
680 | assert_eq!(to_string(f, 7.5e-11, Minus, (-4, 16), false), "7.5e-11"); | |
d9579d0f AL |
681 | assert_eq!(to_string(f, 7.5e-11, Minus, (-11, 10), false), "0.000000000075"); |
682 | assert_eq!(to_string(f, 7.5e-11, Minus, (-10, 11), false), "7.5e-11"); | |
683 | ||
dfeec247 | 684 | assert_eq!(to_string(f, 1.9971e20, Minus, (-4, 16), false), "1.9971e20"); |
d9579d0f AL |
685 | assert_eq!(to_string(f, 1.9971e20, Minus, (-20, 21), false), "199710000000000000000"); |
686 | assert_eq!(to_string(f, 1.9971e20, Minus, (-21, 20), false), "1.9971e20"); | |
687 | ||
688 | // the true value of 1.0e23f64 is less than 10^23, but that shouldn't matter here | |
689 | assert_eq!(to_string(f, 1.0e23, Minus, (22, 23), false), "1e23"); | |
690 | assert_eq!(to_string(f, 1.0e23, Minus, (23, 24), false), "100000000000000000000000"); | |
691 | assert_eq!(to_string(f, 1.0e23, Minus, (24, 25), false), "1e23"); | |
692 | ||
dfeec247 | 693 | assert_eq!(to_string(f, f32::MAX, Minus, (-4, 16), false), "3.4028235e38"); |
d9579d0f AL |
694 | assert_eq!(to_string(f, f32::MAX, Minus, (-39, 38), false), "3.4028235e38"); |
695 | assert_eq!(to_string(f, f32::MAX, Minus, (-38, 39), false), format!("34028235{:0>31}", "")); | |
696 | ||
3157f602 | 697 | let minf32 = ldexp_f32(1.0, -149); |
dfeec247 | 698 | assert_eq!(to_string(f, minf32, Minus, (-4, 16), false), "1e-45"); |
d9579d0f AL |
699 | assert_eq!(to_string(f, minf32, Minus, (-44, 45), false), "1e-45"); |
700 | assert_eq!(to_string(f, minf32, Minus, (-45, 44), false), format!("0.{:0>44}1", "")); | |
701 | ||
dfeec247 XL |
702 | assert_eq!(to_string(f, f64::MAX, Minus, (-4, 16), false), "1.7976931348623157e308"); |
703 | assert_eq!( | |
704 | to_string(f, f64::MAX, Minus, (-308, 309), false), | |
705 | format!("17976931348623157{:0>292}", "") | |
706 | ); | |
707 | assert_eq!(to_string(f, f64::MAX, Minus, (-309, 308), false), "1.7976931348623157e308"); | |
d9579d0f | 708 | |
3157f602 | 709 | let minf64 = ldexp_f64(1.0, -1074); |
dfeec247 | 710 | assert_eq!(to_string(f, minf64, Minus, (-4, 16), false), "5e-324"); |
d9579d0f AL |
711 | assert_eq!(to_string(f, minf64, Minus, (-324, 323), false), format!("0.{:0>323}5", "")); |
712 | assert_eq!(to_string(f, minf64, Minus, (-323, 324), false), "5e-324"); | |
713 | ||
714 | assert_eq!(to_string(f, 1.1, Minus, (i16::MIN, i16::MAX), false), "1.1"); | |
715 | } | |
716 | ||
717 | pub fn to_exact_exp_str_test<F>(mut f_: F) | |
dfeec247 XL |
718 | where |
719 | F: FnMut(&Decoded, &mut [u8], i16) -> (usize, i16), | |
720 | { | |
d9579d0f AL |
721 | use core::num::flt2dec::Sign::*; |
722 | ||
723 | fn to_string<T, F>(f: &mut F, v: T, sign: Sign, ndigits: usize, upper: bool) -> String | |
dfeec247 XL |
724 | where |
725 | T: DecodableFloat, | |
726 | F: FnMut(&Decoded, &mut [u8], i16) -> (usize, i16), | |
727 | { | |
728 | to_string_with_parts(|buf, parts| { | |
729 | to_exact_exp_str(|d, b, l| f(d, b, l), v, sign, ndigits, upper, buf, parts) | |
730 | }) | |
d9579d0f AL |
731 | } |
732 | ||
733 | let f = &mut f_; | |
734 | ||
dfeec247 XL |
735 | assert_eq!(to_string(f, 0.0, Minus, 1, true), "0E0"); |
736 | assert_eq!(to_string(f, 0.0, MinusRaw, 1, false), "0e0"); | |
737 | assert_eq!(to_string(f, 0.0, MinusPlus, 1, true), "+0E0"); | |
738 | assert_eq!(to_string(f, 0.0, MinusPlusRaw, 1, false), "+0e0"); | |
739 | assert_eq!(to_string(f, -0.0, Minus, 1, true), "0E0"); | |
740 | assert_eq!(to_string(f, -0.0, MinusRaw, 1, false), "-0e0"); | |
741 | assert_eq!(to_string(f, -0.0, MinusPlus, 1, true), "+0E0"); | |
d9579d0f | 742 | assert_eq!(to_string(f, -0.0, MinusPlusRaw, 1, false), "-0e0"); |
dfeec247 XL |
743 | assert_eq!(to_string(f, 0.0, Minus, 2, true), "0.0E0"); |
744 | assert_eq!(to_string(f, 0.0, MinusRaw, 2, false), "0.0e0"); | |
745 | assert_eq!(to_string(f, 0.0, MinusPlus, 2, true), "+0.0E0"); | |
746 | assert_eq!(to_string(f, 0.0, MinusPlusRaw, 2, false), "+0.0e0"); | |
747 | assert_eq!(to_string(f, -0.0, Minus, 8, true), "0.0000000E0"); | |
748 | assert_eq!(to_string(f, -0.0, MinusRaw, 8, false), "-0.0000000e0"); | |
749 | assert_eq!(to_string(f, -0.0, MinusPlus, 8, true), "+0.0000000E0"); | |
d9579d0f AL |
750 | assert_eq!(to_string(f, -0.0, MinusPlusRaw, 8, false), "-0.0000000e0"); |
751 | ||
dfeec247 XL |
752 | assert_eq!(to_string(f, 1.0 / 0.0, Minus, 1, false), "inf"); |
753 | assert_eq!(to_string(f, 1.0 / 0.0, MinusRaw, 1, true), "inf"); | |
754 | assert_eq!(to_string(f, 1.0 / 0.0, MinusPlus, 1, false), "+inf"); | |
755 | assert_eq!(to_string(f, 1.0 / 0.0, MinusPlusRaw, 1, true), "+inf"); | |
756 | assert_eq!(to_string(f, 0.0 / 0.0, Minus, 8, false), "NaN"); | |
757 | assert_eq!(to_string(f, 0.0 / 0.0, MinusRaw, 8, true), "NaN"); | |
758 | assert_eq!(to_string(f, 0.0 / 0.0, MinusPlus, 8, false), "NaN"); | |
759 | assert_eq!(to_string(f, 0.0 / 0.0, MinusPlusRaw, 8, true), "NaN"); | |
760 | assert_eq!(to_string(f, -1.0 / 0.0, Minus, 64, false), "-inf"); | |
761 | assert_eq!(to_string(f, -1.0 / 0.0, MinusRaw, 64, true), "-inf"); | |
762 | assert_eq!(to_string(f, -1.0 / 0.0, MinusPlus, 64, false), "-inf"); | |
763 | assert_eq!(to_string(f, -1.0 / 0.0, MinusPlusRaw, 64, true), "-inf"); | |
764 | ||
765 | assert_eq!(to_string(f, 3.14, Minus, 1, true), "3E0"); | |
766 | assert_eq!(to_string(f, 3.14, MinusRaw, 1, false), "3e0"); | |
767 | assert_eq!(to_string(f, 3.14, MinusPlus, 1, true), "+3E0"); | |
768 | assert_eq!(to_string(f, 3.14, MinusPlusRaw, 1, false), "+3e0"); | |
769 | assert_eq!(to_string(f, -3.14, Minus, 2, true), "-3.1E0"); | |
770 | assert_eq!(to_string(f, -3.14, MinusRaw, 2, false), "-3.1e0"); | |
771 | assert_eq!(to_string(f, -3.14, MinusPlus, 2, true), "-3.1E0"); | |
d9579d0f | 772 | assert_eq!(to_string(f, -3.14, MinusPlusRaw, 2, false), "-3.1e0"); |
dfeec247 XL |
773 | assert_eq!(to_string(f, 3.14, Minus, 3, true), "3.14E0"); |
774 | assert_eq!(to_string(f, 3.14, MinusRaw, 3, false), "3.14e0"); | |
775 | assert_eq!(to_string(f, 3.14, MinusPlus, 3, true), "+3.14E0"); | |
776 | assert_eq!(to_string(f, 3.14, MinusPlusRaw, 3, false), "+3.14e0"); | |
777 | assert_eq!(to_string(f, -3.14, Minus, 4, true), "-3.140E0"); | |
778 | assert_eq!(to_string(f, -3.14, MinusRaw, 4, false), "-3.140e0"); | |
779 | assert_eq!(to_string(f, -3.14, MinusPlus, 4, true), "-3.140E0"); | |
d9579d0f AL |
780 | assert_eq!(to_string(f, -3.14, MinusPlusRaw, 4, false), "-3.140e0"); |
781 | ||
dfeec247 XL |
782 | assert_eq!(to_string(f, 0.195, Minus, 1, false), "2e-1"); |
783 | assert_eq!(to_string(f, 0.195, MinusRaw, 1, true), "2E-1"); | |
784 | assert_eq!(to_string(f, 0.195, MinusPlus, 1, false), "+2e-1"); | |
785 | assert_eq!(to_string(f, 0.195, MinusPlusRaw, 1, true), "+2E-1"); | |
786 | assert_eq!(to_string(f, -0.195, Minus, 2, false), "-2.0e-1"); | |
787 | assert_eq!(to_string(f, -0.195, MinusRaw, 2, true), "-2.0E-1"); | |
788 | assert_eq!(to_string(f, -0.195, MinusPlus, 2, false), "-2.0e-1"); | |
789 | assert_eq!(to_string(f, -0.195, MinusPlusRaw, 2, true), "-2.0E-1"); | |
790 | assert_eq!(to_string(f, 0.195, Minus, 3, false), "1.95e-1"); | |
791 | assert_eq!(to_string(f, 0.195, MinusRaw, 3, true), "1.95E-1"); | |
792 | assert_eq!(to_string(f, 0.195, MinusPlus, 3, false), "+1.95e-1"); | |
793 | assert_eq!(to_string(f, 0.195, MinusPlusRaw, 3, true), "+1.95E-1"); | |
794 | assert_eq!(to_string(f, -0.195, Minus, 4, false), "-1.950e-1"); | |
795 | assert_eq!(to_string(f, -0.195, MinusRaw, 4, true), "-1.950E-1"); | |
796 | assert_eq!(to_string(f, -0.195, MinusPlus, 4, false), "-1.950e-1"); | |
797 | assert_eq!(to_string(f, -0.195, MinusPlusRaw, 4, true), "-1.950E-1"); | |
798 | ||
799 | assert_eq!(to_string(f, 9.5, Minus, 1, false), "1e1"); | |
800 | assert_eq!(to_string(f, 9.5, Minus, 2, false), "9.5e0"); | |
801 | assert_eq!(to_string(f, 9.5, Minus, 3, false), "9.50e0"); | |
d9579d0f AL |
802 | assert_eq!(to_string(f, 9.5, Minus, 30, false), "9.50000000000000000000000000000e0"); |
803 | ||
dfeec247 XL |
804 | assert_eq!(to_string(f, 1.0e25, Minus, 1, false), "1e25"); |
805 | assert_eq!(to_string(f, 1.0e25, Minus, 2, false), "1.0e25"); | |
d9579d0f AL |
806 | assert_eq!(to_string(f, 1.0e25, Minus, 15, false), "1.00000000000000e25"); |
807 | assert_eq!(to_string(f, 1.0e25, Minus, 16, false), "1.000000000000000e25"); | |
808 | assert_eq!(to_string(f, 1.0e25, Minus, 17, false), "1.0000000000000001e25"); | |
809 | assert_eq!(to_string(f, 1.0e25, Minus, 18, false), "1.00000000000000009e25"); | |
810 | assert_eq!(to_string(f, 1.0e25, Minus, 19, false), "1.000000000000000091e25"); | |
811 | assert_eq!(to_string(f, 1.0e25, Minus, 20, false), "1.0000000000000000906e25"); | |
812 | assert_eq!(to_string(f, 1.0e25, Minus, 21, false), "1.00000000000000009060e25"); | |
813 | assert_eq!(to_string(f, 1.0e25, Minus, 22, false), "1.000000000000000090597e25"); | |
814 | assert_eq!(to_string(f, 1.0e25, Minus, 23, false), "1.0000000000000000905970e25"); | |
815 | assert_eq!(to_string(f, 1.0e25, Minus, 24, false), "1.00000000000000009059697e25"); | |
816 | assert_eq!(to_string(f, 1.0e25, Minus, 25, false), "1.000000000000000090596966e25"); | |
817 | assert_eq!(to_string(f, 1.0e25, Minus, 26, false), "1.0000000000000000905969664e25"); | |
818 | assert_eq!(to_string(f, 1.0e25, Minus, 27, false), "1.00000000000000009059696640e25"); | |
819 | assert_eq!(to_string(f, 1.0e25, Minus, 30, false), "1.00000000000000009059696640000e25"); | |
820 | ||
dfeec247 XL |
821 | assert_eq!(to_string(f, 1.0e-6, Minus, 1, false), "1e-6"); |
822 | assert_eq!(to_string(f, 1.0e-6, Minus, 2, false), "1.0e-6"); | |
d9579d0f AL |
823 | assert_eq!(to_string(f, 1.0e-6, Minus, 16, false), "1.000000000000000e-6"); |
824 | assert_eq!(to_string(f, 1.0e-6, Minus, 17, false), "9.9999999999999995e-7"); | |
825 | assert_eq!(to_string(f, 1.0e-6, Minus, 18, false), "9.99999999999999955e-7"); | |
826 | assert_eq!(to_string(f, 1.0e-6, Minus, 19, false), "9.999999999999999547e-7"); | |
827 | assert_eq!(to_string(f, 1.0e-6, Minus, 20, false), "9.9999999999999995475e-7"); | |
828 | assert_eq!(to_string(f, 1.0e-6, Minus, 30, false), "9.99999999999999954748111825886e-7"); | |
dfeec247 XL |
829 | assert_eq!( |
830 | to_string(f, 1.0e-6, Minus, 40, false), | |
831 | "9.999999999999999547481118258862586856139e-7" | |
832 | ); | |
833 | assert_eq!( | |
834 | to_string(f, 1.0e-6, Minus, 50, false), | |
835 | "9.9999999999999995474811182588625868561393872369081e-7" | |
836 | ); | |
837 | assert_eq!( | |
838 | to_string(f, 1.0e-6, Minus, 60, false), | |
839 | "9.99999999999999954748111825886258685613938723690807819366455e-7" | |
840 | ); | |
841 | assert_eq!( | |
842 | to_string(f, 1.0e-6, Minus, 70, false), | |
843 | "9.999999999999999547481118258862586856139387236908078193664550781250000e-7" | |
844 | ); | |
845 | ||
846 | assert_eq!(to_string(f, f32::MAX, Minus, 1, false), "3e38"); | |
847 | assert_eq!(to_string(f, f32::MAX, Minus, 2, false), "3.4e38"); | |
848 | assert_eq!(to_string(f, f32::MAX, Minus, 4, false), "3.403e38"); | |
849 | assert_eq!(to_string(f, f32::MAX, Minus, 8, false), "3.4028235e38"); | |
d9579d0f AL |
850 | assert_eq!(to_string(f, f32::MAX, Minus, 16, false), "3.402823466385289e38"); |
851 | assert_eq!(to_string(f, f32::MAX, Minus, 32, false), "3.4028234663852885981170418348452e38"); | |
dfeec247 XL |
852 | assert_eq!( |
853 | to_string(f, f32::MAX, Minus, 64, false), | |
854 | "3.402823466385288598117041834845169254400000000000000000000000000e38" | |
855 | ); | |
d9579d0f | 856 | |
3157f602 | 857 | let minf32 = ldexp_f32(1.0, -149); |
dfeec247 XL |
858 | assert_eq!(to_string(f, minf32, Minus, 1, false), "1e-45"); |
859 | assert_eq!(to_string(f, minf32, Minus, 2, false), "1.4e-45"); | |
860 | assert_eq!(to_string(f, minf32, Minus, 4, false), "1.401e-45"); | |
861 | assert_eq!(to_string(f, minf32, Minus, 8, false), "1.4012985e-45"); | |
862 | assert_eq!(to_string(f, minf32, Minus, 16, false), "1.401298464324817e-45"); | |
863 | assert_eq!(to_string(f, minf32, Minus, 32, false), "1.4012984643248170709237295832899e-45"); | |
864 | assert_eq!( | |
865 | to_string(f, minf32, Minus, 64, false), | |
866 | "1.401298464324817070923729583289916131280261941876515771757068284e-45" | |
867 | ); | |
868 | assert_eq!( | |
869 | to_string(f, minf32, Minus, 128, false), | |
870 | "1.401298464324817070923729583289916131280261941876515771757068283\ | |
871 | 8897910826858606014866381883621215820312500000000000000000000000e-45" | |
872 | ); | |
873 | ||
874 | if cfg!(miri) { | |
875 | // Miri is too slow | |
416331ca XL |
876 | return; |
877 | } | |
878 | ||
dfeec247 XL |
879 | assert_eq!(to_string(f, f64::MAX, Minus, 1, false), "2e308"); |
880 | assert_eq!(to_string(f, f64::MAX, Minus, 2, false), "1.8e308"); | |
881 | assert_eq!(to_string(f, f64::MAX, Minus, 4, false), "1.798e308"); | |
882 | assert_eq!(to_string(f, f64::MAX, Minus, 8, false), "1.7976931e308"); | |
883 | assert_eq!(to_string(f, f64::MAX, Minus, 16, false), "1.797693134862316e308"); | |
884 | assert_eq!(to_string(f, f64::MAX, Minus, 32, false), "1.7976931348623157081452742373170e308"); | |
885 | assert_eq!( | |
886 | to_string(f, f64::MAX, Minus, 64, false), | |
887 | "1.797693134862315708145274237317043567980705675258449965989174768e308" | |
888 | ); | |
889 | assert_eq!( | |
890 | to_string(f, f64::MAX, Minus, 128, false), | |
891 | "1.797693134862315708145274237317043567980705675258449965989174768\ | |
892 | 0315726078002853876058955863276687817154045895351438246423432133e308" | |
893 | ); | |
894 | assert_eq!( | |
895 | to_string(f, f64::MAX, Minus, 256, false), | |
896 | "1.797693134862315708145274237317043567980705675258449965989174768\ | |
d9579d0f AL |
897 | 0315726078002853876058955863276687817154045895351438246423432132\ |
898 | 6889464182768467546703537516986049910576551282076245490090389328\ | |
dfeec247 XL |
899 | 9440758685084551339423045832369032229481658085593321233482747978e308" |
900 | ); | |
901 | assert_eq!( | |
902 | to_string(f, f64::MAX, Minus, 512, false), | |
903 | "1.797693134862315708145274237317043567980705675258449965989174768\ | |
d9579d0f AL |
904 | 0315726078002853876058955863276687817154045895351438246423432132\ |
905 | 6889464182768467546703537516986049910576551282076245490090389328\ | |
906 | 9440758685084551339423045832369032229481658085593321233482747978\ | |
907 | 2620414472316873817718091929988125040402618412485836800000000000\ | |
908 | 0000000000000000000000000000000000000000000000000000000000000000\ | |
909 | 0000000000000000000000000000000000000000000000000000000000000000\ | |
dfeec247 XL |
910 | 0000000000000000000000000000000000000000000000000000000000000000e308" |
911 | ); | |
d9579d0f AL |
912 | |
913 | // okay, this is becoming tough. fortunately for us, this is almost the worst case. | |
3157f602 | 914 | let minf64 = ldexp_f64(1.0, -1074); |
dfeec247 XL |
915 | assert_eq!(to_string(f, minf64, Minus, 1, false), "5e-324"); |
916 | assert_eq!(to_string(f, minf64, Minus, 2, false), "4.9e-324"); | |
917 | assert_eq!(to_string(f, minf64, Minus, 4, false), "4.941e-324"); | |
918 | assert_eq!(to_string(f, minf64, Minus, 8, false), "4.9406565e-324"); | |
919 | assert_eq!(to_string(f, minf64, Minus, 16, false), "4.940656458412465e-324"); | |
920 | assert_eq!(to_string(f, minf64, Minus, 32, false), "4.9406564584124654417656879286822e-324"); | |
921 | assert_eq!( | |
922 | to_string(f, minf64, Minus, 64, false), | |
923 | "4.940656458412465441765687928682213723650598026143247644255856825e-324" | |
924 | ); | |
925 | assert_eq!( | |
926 | to_string(f, minf64, Minus, 128, false), | |
927 | "4.940656458412465441765687928682213723650598026143247644255856825\ | |
928 | 0067550727020875186529983636163599237979656469544571773092665671e-324" | |
929 | ); | |
930 | assert_eq!( | |
931 | to_string(f, minf64, Minus, 256, false), | |
932 | "4.940656458412465441765687928682213723650598026143247644255856825\ | |
d9579d0f AL |
933 | 0067550727020875186529983636163599237979656469544571773092665671\ |
934 | 0355939796398774796010781878126300713190311404527845817167848982\ | |
dfeec247 XL |
935 | 1036887186360569987307230500063874091535649843873124733972731696e-324" |
936 | ); | |
937 | assert_eq!( | |
938 | to_string(f, minf64, Minus, 512, false), | |
939 | "4.940656458412465441765687928682213723650598026143247644255856825\ | |
d9579d0f AL |
940 | 0067550727020875186529983636163599237979656469544571773092665671\ |
941 | 0355939796398774796010781878126300713190311404527845817167848982\ | |
942 | 1036887186360569987307230500063874091535649843873124733972731696\ | |
943 | 1514003171538539807412623856559117102665855668676818703956031062\ | |
944 | 4931945271591492455329305456544401127480129709999541931989409080\ | |
945 | 4165633245247571478690147267801593552386115501348035264934720193\ | |
dfeec247 XL |
946 | 7902681071074917033322268447533357208324319360923828934583680601e-324" |
947 | ); | |
948 | assert_eq!( | |
949 | to_string(f, minf64, Minus, 1024, false), | |
950 | "4.940656458412465441765687928682213723650598026143247644255856825\ | |
d9579d0f AL |
951 | 0067550727020875186529983636163599237979656469544571773092665671\ |
952 | 0355939796398774796010781878126300713190311404527845817167848982\ | |
953 | 1036887186360569987307230500063874091535649843873124733972731696\ | |
954 | 1514003171538539807412623856559117102665855668676818703956031062\ | |
955 | 4931945271591492455329305456544401127480129709999541931989409080\ | |
956 | 4165633245247571478690147267801593552386115501348035264934720193\ | |
957 | 7902681071074917033322268447533357208324319360923828934583680601\ | |
958 | 0601150616980975307834227731832924790498252473077637592724787465\ | |
959 | 6084778203734469699533647017972677717585125660551199131504891101\ | |
960 | 4510378627381672509558373897335989936648099411642057026370902792\ | |
961 | 4276754456522908753868250641971826553344726562500000000000000000\ | |
962 | 0000000000000000000000000000000000000000000000000000000000000000\ | |
963 | 0000000000000000000000000000000000000000000000000000000000000000\ | |
964 | 0000000000000000000000000000000000000000000000000000000000000000\ | |
dfeec247 XL |
965 | 0000000000000000000000000000000000000000000000000000000000000000e-324" |
966 | ); | |
d9579d0f AL |
967 | |
968 | // very large output | |
dfeec247 XL |
969 | assert_eq!(to_string(f, 0.0, Minus, 80000, false), format!("0.{:0>79999}e0", "")); |
970 | assert_eq!(to_string(f, 1.0e1, Minus, 80000, false), format!("1.{:0>79999}e1", "")); | |
971 | assert_eq!(to_string(f, 1.0e0, Minus, 80000, false), format!("1.{:0>79999}e0", "")); | |
972 | assert_eq!( | |
973 | to_string(f, 1.0e-1, Minus, 80000, false), | |
974 | format!( | |
975 | "1.000000000000000055511151231257827021181583404541015625{:0>79945}\ | |
976 | e-1", | |
977 | "" | |
978 | ) | |
979 | ); | |
980 | assert_eq!( | |
981 | to_string(f, 1.0e-20, Minus, 80000, false), | |
982 | format!( | |
983 | "9.999999999999999451532714542095716517295037027873924471077157760\ | |
984 | 66783064379706047475337982177734375{:0>79901}e-21", | |
985 | "" | |
986 | ) | |
987 | ); | |
d9579d0f AL |
988 | } |
989 | ||
990 | pub fn to_exact_fixed_str_test<F>(mut f_: F) | |
dfeec247 XL |
991 | where |
992 | F: FnMut(&Decoded, &mut [u8], i16) -> (usize, i16), | |
993 | { | |
d9579d0f AL |
994 | use core::num::flt2dec::Sign::*; |
995 | ||
74b04a01 | 996 | fn to_string<T, F>(f: &mut F, v: T, sign: Sign, frac_digits: usize) -> String |
dfeec247 XL |
997 | where |
998 | T: DecodableFloat, | |
999 | F: FnMut(&Decoded, &mut [u8], i16) -> (usize, i16), | |
1000 | { | |
1001 | to_string_with_parts(|buf, parts| { | |
74b04a01 | 1002 | to_exact_fixed_str(|d, b, l| f(d, b, l), v, sign, frac_digits, buf, parts) |
dfeec247 | 1003 | }) |
d9579d0f AL |
1004 | } |
1005 | ||
1006 | let f = &mut f_; | |
1007 | ||
74b04a01 XL |
1008 | assert_eq!(to_string(f, 0.0, Minus, 0), "0"); |
1009 | assert_eq!(to_string(f, 0.0, MinusRaw, 0), "0"); | |
1010 | assert_eq!(to_string(f, 0.0, MinusPlus, 0), "+0"); | |
1011 | assert_eq!(to_string(f, 0.0, MinusPlusRaw, 0), "+0"); | |
1012 | assert_eq!(to_string(f, -0.0, Minus, 0), "0"); | |
1013 | assert_eq!(to_string(f, -0.0, MinusRaw, 0), "-0"); | |
1014 | assert_eq!(to_string(f, -0.0, MinusPlus, 0), "+0"); | |
1015 | assert_eq!(to_string(f, -0.0, MinusPlusRaw, 0), "-0"); | |
1016 | assert_eq!(to_string(f, 0.0, Minus, 1), "0.0"); | |
1017 | assert_eq!(to_string(f, 0.0, MinusRaw, 1), "0.0"); | |
1018 | assert_eq!(to_string(f, 0.0, MinusPlus, 1), "+0.0"); | |
1019 | assert_eq!(to_string(f, 0.0, MinusPlusRaw, 1), "+0.0"); | |
1020 | assert_eq!(to_string(f, -0.0, Minus, 8), "0.00000000"); | |
1021 | assert_eq!(to_string(f, -0.0, MinusRaw, 8), "-0.00000000"); | |
1022 | assert_eq!(to_string(f, -0.0, MinusPlus, 8), "+0.00000000"); | |
1023 | assert_eq!(to_string(f, -0.0, MinusPlusRaw, 8), "-0.00000000"); | |
1024 | ||
1025 | assert_eq!(to_string(f, 1.0 / 0.0, Minus, 0), "inf"); | |
1026 | assert_eq!(to_string(f, 1.0 / 0.0, MinusRaw, 1), "inf"); | |
1027 | assert_eq!(to_string(f, 1.0 / 0.0, MinusPlus, 8), "+inf"); | |
1028 | assert_eq!(to_string(f, 1.0 / 0.0, MinusPlusRaw, 64), "+inf"); | |
1029 | assert_eq!(to_string(f, 0.0 / 0.0, Minus, 0), "NaN"); | |
1030 | assert_eq!(to_string(f, 0.0 / 0.0, MinusRaw, 1), "NaN"); | |
1031 | assert_eq!(to_string(f, 0.0 / 0.0, MinusPlus, 8), "NaN"); | |
1032 | assert_eq!(to_string(f, 0.0 / 0.0, MinusPlusRaw, 64), "NaN"); | |
1033 | assert_eq!(to_string(f, -1.0 / 0.0, Minus, 0), "-inf"); | |
1034 | assert_eq!(to_string(f, -1.0 / 0.0, MinusRaw, 1), "-inf"); | |
1035 | assert_eq!(to_string(f, -1.0 / 0.0, MinusPlus, 8), "-inf"); | |
1036 | assert_eq!(to_string(f, -1.0 / 0.0, MinusPlusRaw, 64), "-inf"); | |
1037 | ||
1038 | assert_eq!(to_string(f, 3.14, Minus, 0), "3"); | |
1039 | assert_eq!(to_string(f, 3.14, MinusRaw, 0), "3"); | |
1040 | assert_eq!(to_string(f, 3.14, MinusPlus, 0), "+3"); | |
1041 | assert_eq!(to_string(f, 3.14, MinusPlusRaw, 0), "+3"); | |
1042 | assert_eq!(to_string(f, -3.14, Minus, 0), "-3"); | |
1043 | assert_eq!(to_string(f, -3.14, MinusRaw, 0), "-3"); | |
1044 | assert_eq!(to_string(f, -3.14, MinusPlus, 0), "-3"); | |
1045 | assert_eq!(to_string(f, -3.14, MinusPlusRaw, 0), "-3"); | |
1046 | assert_eq!(to_string(f, 3.14, Minus, 1), "3.1"); | |
1047 | assert_eq!(to_string(f, 3.14, MinusRaw, 2), "3.14"); | |
1048 | assert_eq!(to_string(f, 3.14, MinusPlus, 3), "+3.140"); | |
1049 | assert_eq!(to_string(f, 3.14, MinusPlusRaw, 4), "+3.1400"); | |
1050 | assert_eq!(to_string(f, -3.14, Minus, 8), "-3.14000000"); | |
1051 | assert_eq!(to_string(f, -3.14, MinusRaw, 8), "-3.14000000"); | |
1052 | assert_eq!(to_string(f, -3.14, MinusPlus, 8), "-3.14000000"); | |
1053 | assert_eq!(to_string(f, -3.14, MinusPlusRaw, 8), "-3.14000000"); | |
1054 | ||
1055 | assert_eq!(to_string(f, 0.195, Minus, 0), "0"); | |
1056 | assert_eq!(to_string(f, 0.195, MinusRaw, 0), "0"); | |
1057 | assert_eq!(to_string(f, 0.195, MinusPlus, 0), "+0"); | |
1058 | assert_eq!(to_string(f, 0.195, MinusPlusRaw, 0), "+0"); | |
1059 | assert_eq!(to_string(f, -0.195, Minus, 0), "-0"); | |
1060 | assert_eq!(to_string(f, -0.195, MinusRaw, 0), "-0"); | |
1061 | assert_eq!(to_string(f, -0.195, MinusPlus, 0), "-0"); | |
1062 | assert_eq!(to_string(f, -0.195, MinusPlusRaw, 0), "-0"); | |
1063 | assert_eq!(to_string(f, 0.195, Minus, 1), "0.2"); | |
1064 | assert_eq!(to_string(f, 0.195, MinusRaw, 2), "0.20"); | |
1065 | assert_eq!(to_string(f, 0.195, MinusPlus, 3), "+0.195"); | |
1066 | assert_eq!(to_string(f, 0.195, MinusPlusRaw, 4), "+0.1950"); | |
1067 | assert_eq!(to_string(f, -0.195, Minus, 5), "-0.19500"); | |
1068 | assert_eq!(to_string(f, -0.195, MinusRaw, 6), "-0.195000"); | |
1069 | assert_eq!(to_string(f, -0.195, MinusPlus, 7), "-0.1950000"); | |
1070 | assert_eq!(to_string(f, -0.195, MinusPlusRaw, 8), "-0.19500000"); | |
1071 | ||
1072 | assert_eq!(to_string(f, 999.5, Minus, 0), "1000"); | |
1073 | assert_eq!(to_string(f, 999.5, Minus, 1), "999.5"); | |
1074 | assert_eq!(to_string(f, 999.5, Minus, 2), "999.50"); | |
1075 | assert_eq!(to_string(f, 999.5, Minus, 3), "999.500"); | |
1076 | assert_eq!(to_string(f, 999.5, Minus, 30), "999.500000000000000000000000000000"); | |
1077 | ||
1078 | assert_eq!(to_string(f, 0.5, Minus, 0), "1"); | |
1079 | assert_eq!(to_string(f, 0.5, Minus, 1), "0.5"); | |
1080 | assert_eq!(to_string(f, 0.5, Minus, 2), "0.50"); | |
1081 | assert_eq!(to_string(f, 0.5, Minus, 3), "0.500"); | |
1082 | ||
1083 | assert_eq!(to_string(f, 0.95, Minus, 0), "1"); | |
1084 | assert_eq!(to_string(f, 0.95, Minus, 1), "0.9"); // because it really is less than 0.95 | |
1085 | assert_eq!(to_string(f, 0.95, Minus, 2), "0.95"); | |
1086 | assert_eq!(to_string(f, 0.95, Minus, 3), "0.950"); | |
1087 | assert_eq!(to_string(f, 0.95, Minus, 10), "0.9500000000"); | |
1088 | assert_eq!(to_string(f, 0.95, Minus, 30), "0.949999999999999955591079014994"); | |
1089 | ||
1090 | assert_eq!(to_string(f, 0.095, Minus, 0), "0"); | |
1091 | assert_eq!(to_string(f, 0.095, Minus, 1), "0.1"); | |
1092 | assert_eq!(to_string(f, 0.095, Minus, 2), "0.10"); | |
1093 | assert_eq!(to_string(f, 0.095, Minus, 3), "0.095"); | |
1094 | assert_eq!(to_string(f, 0.095, Minus, 4), "0.0950"); | |
1095 | assert_eq!(to_string(f, 0.095, Minus, 10), "0.0950000000"); | |
1096 | assert_eq!(to_string(f, 0.095, Minus, 30), "0.095000000000000001110223024625"); | |
1097 | ||
1098 | assert_eq!(to_string(f, 0.0095, Minus, 0), "0"); | |
1099 | assert_eq!(to_string(f, 0.0095, Minus, 1), "0.0"); | |
1100 | assert_eq!(to_string(f, 0.0095, Minus, 2), "0.01"); | |
1101 | assert_eq!(to_string(f, 0.0095, Minus, 3), "0.009"); // really is less than 0.0095 | |
1102 | assert_eq!(to_string(f, 0.0095, Minus, 4), "0.0095"); | |
1103 | assert_eq!(to_string(f, 0.0095, Minus, 5), "0.00950"); | |
1104 | assert_eq!(to_string(f, 0.0095, Minus, 10), "0.0095000000"); | |
1105 | assert_eq!(to_string(f, 0.0095, Minus, 30), "0.009499999999999999764077607267"); | |
1106 | ||
1107 | assert_eq!(to_string(f, 7.5e-11, Minus, 0), "0"); | |
1108 | assert_eq!(to_string(f, 7.5e-11, Minus, 3), "0.000"); | |
1109 | assert_eq!(to_string(f, 7.5e-11, Minus, 10), "0.0000000001"); | |
1110 | assert_eq!(to_string(f, 7.5e-11, Minus, 11), "0.00000000007"); // ditto | |
1111 | assert_eq!(to_string(f, 7.5e-11, Minus, 12), "0.000000000075"); | |
1112 | assert_eq!(to_string(f, 7.5e-11, Minus, 13), "0.0000000000750"); | |
1113 | assert_eq!(to_string(f, 7.5e-11, Minus, 20), "0.00000000007500000000"); | |
1114 | assert_eq!(to_string(f, 7.5e-11, Minus, 30), "0.000000000074999999999999999501"); | |
1115 | ||
1116 | assert_eq!(to_string(f, 1.0e25, Minus, 0), "10000000000000000905969664"); | |
1117 | assert_eq!(to_string(f, 1.0e25, Minus, 1), "10000000000000000905969664.0"); | |
1118 | assert_eq!(to_string(f, 1.0e25, Minus, 3), "10000000000000000905969664.000"); | |
1119 | ||
1120 | assert_eq!(to_string(f, 1.0e-6, Minus, 0), "0"); | |
1121 | assert_eq!(to_string(f, 1.0e-6, Minus, 3), "0.000"); | |
1122 | assert_eq!(to_string(f, 1.0e-6, Minus, 6), "0.000001"); | |
1123 | assert_eq!(to_string(f, 1.0e-6, Minus, 9), "0.000001000"); | |
1124 | assert_eq!(to_string(f, 1.0e-6, Minus, 12), "0.000001000000"); | |
1125 | assert_eq!(to_string(f, 1.0e-6, Minus, 22), "0.0000010000000000000000"); | |
1126 | assert_eq!(to_string(f, 1.0e-6, Minus, 23), "0.00000099999999999999995"); | |
1127 | assert_eq!(to_string(f, 1.0e-6, Minus, 24), "0.000000999999999999999955"); | |
1128 | assert_eq!(to_string(f, 1.0e-6, Minus, 25), "0.0000009999999999999999547"); | |
1129 | assert_eq!(to_string(f, 1.0e-6, Minus, 35), "0.00000099999999999999995474811182589"); | |
1130 | assert_eq!(to_string(f, 1.0e-6, Minus, 45), "0.000000999999999999999954748111825886258685614"); | |
dfeec247 | 1131 | assert_eq!( |
74b04a01 | 1132 | to_string(f, 1.0e-6, Minus, 55), |
dfeec247 XL |
1133 | "0.0000009999999999999999547481118258862586856139387236908" |
1134 | ); | |
1135 | assert_eq!( | |
74b04a01 | 1136 | to_string(f, 1.0e-6, Minus, 65), |
dfeec247 XL |
1137 | "0.00000099999999999999995474811182588625868561393872369080781936646" |
1138 | ); | |
1139 | assert_eq!( | |
74b04a01 | 1140 | to_string(f, 1.0e-6, Minus, 75), |
dfeec247 XL |
1141 | "0.000000999999999999999954748111825886258685613938723690807819366455078125000" |
1142 | ); | |
1143 | ||
74b04a01 XL |
1144 | assert_eq!(to_string(f, f32::MAX, Minus, 0), "340282346638528859811704183484516925440"); |
1145 | assert_eq!(to_string(f, f32::MAX, Minus, 1), "340282346638528859811704183484516925440.0"); | |
1146 | assert_eq!(to_string(f, f32::MAX, Minus, 2), "340282346638528859811704183484516925440.00"); | |
dfeec247 XL |
1147 | |
1148 | if cfg!(miri) { | |
1149 | // Miri is too slow | |
416331ca XL |
1150 | return; |
1151 | } | |
1152 | ||
3157f602 | 1153 | let minf32 = ldexp_f32(1.0, -149); |
74b04a01 XL |
1154 | assert_eq!(to_string(f, minf32, Minus, 0), "0"); |
1155 | assert_eq!(to_string(f, minf32, Minus, 1), "0.0"); | |
1156 | assert_eq!(to_string(f, minf32, Minus, 2), "0.00"); | |
1157 | assert_eq!(to_string(f, minf32, Minus, 4), "0.0000"); | |
1158 | assert_eq!(to_string(f, minf32, Minus, 8), "0.00000000"); | |
1159 | assert_eq!(to_string(f, minf32, Minus, 16), "0.0000000000000000"); | |
1160 | assert_eq!(to_string(f, minf32, Minus, 32), "0.00000000000000000000000000000000"); | |
dfeec247 | 1161 | assert_eq!( |
74b04a01 | 1162 | to_string(f, minf32, Minus, 64), |
dfeec247 XL |
1163 | "0.0000000000000000000000000000000000000000000014012984643248170709" |
1164 | ); | |
1165 | assert_eq!( | |
74b04a01 | 1166 | to_string(f, minf32, Minus, 128), |
dfeec247 XL |
1167 | "0.0000000000000000000000000000000000000000000014012984643248170709\ |
1168 | 2372958328991613128026194187651577175706828388979108268586060149" | |
1169 | ); | |
1170 | assert_eq!( | |
74b04a01 | 1171 | to_string(f, minf32, Minus, 256), |
dfeec247 | 1172 | "0.0000000000000000000000000000000000000000000014012984643248170709\ |
d9579d0f AL |
1173 | 2372958328991613128026194187651577175706828388979108268586060148\ |
1174 | 6638188362121582031250000000000000000000000000000000000000000000\ | |
dfeec247 XL |
1175 | 0000000000000000000000000000000000000000000000000000000000000000" |
1176 | ); | |
d9579d0f | 1177 | |
dfeec247 | 1178 | assert_eq!( |
74b04a01 | 1179 | to_string(f, f64::MAX, Minus, 0), |
dfeec247 | 1180 | "1797693134862315708145274237317043567980705675258449965989174768\ |
d9579d0f AL |
1181 | 0315726078002853876058955863276687817154045895351438246423432132\ |
1182 | 6889464182768467546703537516986049910576551282076245490090389328\ | |
1183 | 9440758685084551339423045832369032229481658085593321233482747978\ | |
dfeec247 XL |
1184 | 26204144723168738177180919299881250404026184124858368" |
1185 | ); | |
1186 | assert_eq!( | |
74b04a01 | 1187 | to_string(f, f64::MAX, Minus, 10), |
dfeec247 | 1188 | "1797693134862315708145274237317043567980705675258449965989174768\ |
d9579d0f AL |
1189 | 0315726078002853876058955863276687817154045895351438246423432132\ |
1190 | 6889464182768467546703537516986049910576551282076245490090389328\ | |
1191 | 9440758685084551339423045832369032229481658085593321233482747978\ | |
dfeec247 XL |
1192 | 26204144723168738177180919299881250404026184124858368.0000000000" |
1193 | ); | |
d9579d0f | 1194 | |
3157f602 | 1195 | let minf64 = ldexp_f64(1.0, -1074); |
74b04a01 XL |
1196 | assert_eq!(to_string(f, minf64, Minus, 0), "0"); |
1197 | assert_eq!(to_string(f, minf64, Minus, 1), "0.0"); | |
1198 | assert_eq!(to_string(f, minf64, Minus, 10), "0.0000000000"); | |
dfeec247 | 1199 | assert_eq!( |
74b04a01 | 1200 | to_string(f, minf64, Minus, 100), |
dfeec247 XL |
1201 | "0.0000000000000000000000000000000000000000000000000000000000000000\ |
1202 | 000000000000000000000000000000000000" | |
1203 | ); | |
1204 | assert_eq!( | |
74b04a01 | 1205 | to_string(f, minf64, Minus, 1000), |
dfeec247 | 1206 | "0.0000000000000000000000000000000000000000000000000000000000000000\ |
d9579d0f AL |
1207 | 0000000000000000000000000000000000000000000000000000000000000000\ |
1208 | 0000000000000000000000000000000000000000000000000000000000000000\ | |
1209 | 0000000000000000000000000000000000000000000000000000000000000000\ | |
1210 | 0000000000000000000000000000000000000000000000000000000000000000\ | |
1211 | 0004940656458412465441765687928682213723650598026143247644255856\ | |
1212 | 8250067550727020875186529983636163599237979656469544571773092665\ | |
1213 | 6710355939796398774796010781878126300713190311404527845817167848\ | |
1214 | 9821036887186360569987307230500063874091535649843873124733972731\ | |
1215 | 6961514003171538539807412623856559117102665855668676818703956031\ | |
1216 | 0624931945271591492455329305456544401127480129709999541931989409\ | |
1217 | 0804165633245247571478690147267801593552386115501348035264934720\ | |
1218 | 1937902681071074917033322268447533357208324319360923828934583680\ | |
1219 | 6010601150616980975307834227731832924790498252473077637592724787\ | |
1220 | 4656084778203734469699533647017972677717585125660551199131504891\ | |
dfeec247 XL |
1221 | 1014510378627381672509558373897335989937" |
1222 | ); | |
d9579d0f AL |
1223 | |
1224 | // very large output | |
74b04a01 XL |
1225 | assert_eq!(to_string(f, 0.0, Minus, 80000), format!("0.{:0>80000}", "")); |
1226 | assert_eq!(to_string(f, 1.0e1, Minus, 80000), format!("10.{:0>80000}", "")); | |
1227 | assert_eq!(to_string(f, 1.0e0, Minus, 80000), format!("1.{:0>80000}", "")); | |
dfeec247 | 1228 | assert_eq!( |
74b04a01 | 1229 | to_string(f, 1.0e-1, Minus, 80000), |
dfeec247 XL |
1230 | format!("0.1000000000000000055511151231257827021181583404541015625{:0>79945}", "") |
1231 | ); | |
1232 | assert_eq!( | |
74b04a01 | 1233 | to_string(f, 1.0e-20, Minus, 80000), |
dfeec247 XL |
1234 | format!( |
1235 | "0.0000000000000000000099999999999999994515327145420957165172950370\ | |
1236 | 2787392447107715776066783064379706047475337982177734375{:0>79881}", | |
1237 | "" | |
1238 | ) | |
1239 | ); | |
d9579d0f | 1240 | } |