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