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