1pub const MAX: usize = 32;
67
68const FRACMASK: u64 = 0x000F_FFFF_FFFF_FFFF;
69const EXPMASK: u64 = 0x7FF0_0000_0000_0000;
70const HIDDENBIT: u64 = 0x0010_0000_0000_0000;
71const SIGNMASK: u64 = 0x8000_0000_0000_0000;
72const EXPBIAS: i32 = 1023 + 52;
73
74const TENS: [u64; 20] = [
76 10_000_000_000_000_000_000,
77 1_000_000_000_000_000_000,
78 100_000_000_000_000_000,
79 10_000_000_000_000_000,
80 1_000_000_000_000_000,
81 100_000_000_000_000,
82 10_000_000_000_000,
83 1_000_000_000_000,
84 100_000_000_000,
85 10_000_000_000,
86 1_000_000_000,
87 100_000_000,
88 10_000_000,
89 1_000_000,
90 100_000,
91 10_000,
92 1_000,
93 100,
94 10,
95 1,
96];
97
98#[derive(Clone, Copy)]
103struct Fp {
104 frac: u64,
105 exp: i32,
106}
107
108const NPOWERS: i32 = 87;
109const STEPPOWERS: i32 = 8;
110const FIRSTPOWER: i32 = -348;
111const EXPMAX: i32 = -32;
112const EXPMIN: i32 = -60;
113
114static POWERS_TEN: [Fp; 87] = [
121 Fp {
122 frac: 18054884314459144840,
123 exp: -1220,
124 },
125 Fp {
126 frac: 13451937075301367670,
127 exp: -1193,
128 },
129 Fp {
130 frac: 10022474136428063862,
131 exp: -1166,
132 },
133 Fp {
134 frac: 14934650266808366570,
135 exp: -1140,
136 },
137 Fp {
138 frac: 11127181549972568877,
139 exp: -1113,
140 },
141 Fp {
142 frac: 16580792590934885855,
143 exp: -1087,
144 },
145 Fp {
146 frac: 12353653155963782858,
147 exp: -1060,
148 },
149 Fp {
150 frac: 18408377700990114895,
151 exp: -1034,
152 },
153 Fp {
154 frac: 13715310171984221708,
155 exp: -1007,
156 },
157 Fp {
158 frac: 10218702384817765436,
159 exp: -980,
160 },
161 Fp {
162 frac: 15227053142812498563,
163 exp: -954,
164 },
165 Fp {
166 frac: 11345038669416679861,
167 exp: -927,
168 },
169 Fp {
170 frac: 16905424996341287883,
171 exp: -901,
172 },
173 Fp {
174 frac: 12595523146049147757,
175 exp: -874,
176 },
177 Fp {
178 frac: 9384396036005875287,
179 exp: -847,
180 },
181 Fp {
182 frac: 13983839803942852151,
183 exp: -821,
184 },
185 Fp {
186 frac: 10418772551374772303,
187 exp: -794,
188 },
189 Fp {
190 frac: 15525180923007089351,
191 exp: -768,
192 },
193 Fp {
194 frac: 11567161174868858868,
195 exp: -741,
196 },
197 Fp {
198 frac: 17236413322193710309,
199 exp: -715,
200 },
201 Fp {
202 frac: 12842128665889583758,
203 exp: -688,
204 },
205 Fp {
206 frac: 9568131466127621947,
207 exp: -661,
208 },
209 Fp {
210 frac: 14257626930069360058,
211 exp: -635,
212 },
213 Fp {
214 frac: 10622759856335341974,
215 exp: -608,
216 },
217 Fp {
218 frac: 15829145694278690180,
219 exp: -582,
220 },
221 Fp {
222 frac: 11793632577567316726,
223 exp: -555,
224 },
225 Fp {
226 frac: 17573882009934360870,
227 exp: -529,
228 },
229 Fp {
230 frac: 13093562431584567480,
231 exp: -502,
232 },
233 Fp {
234 frac: 9755464219737475723,
235 exp: -475,
236 },
237 Fp {
238 frac: 14536774485912137811,
239 exp: -449,
240 },
241 Fp {
242 frac: 10830740992659433045,
243 exp: -422,
244 },
245 Fp {
246 frac: 16139061738043178685,
247 exp: -396,
248 },
249 Fp {
250 frac: 12024538023802026127,
251 exp: -369,
252 },
253 Fp {
254 frac: 17917957937422433684,
255 exp: -343,
256 },
257 Fp {
258 frac: 13349918974505688015,
259 exp: -316,
260 },
261 Fp {
262 frac: 9946464728195732843,
263 exp: -289,
264 },
265 Fp {
266 frac: 14821387422376473014,
267 exp: -263,
268 },
269 Fp {
270 frac: 11042794154864902060,
271 exp: -236,
272 },
273 Fp {
274 frac: 16455045573212060422,
275 exp: -210,
276 },
277 Fp {
278 frac: 12259964326927110867,
279 exp: -183,
280 },
281 Fp {
282 frac: 18268770466636286478,
283 exp: -157,
284 },
285 Fp {
286 frac: 13611294676837538539,
287 exp: -130,
288 },
289 Fp {
290 frac: 10141204801825835212,
291 exp: -103,
292 },
293 Fp {
294 frac: 15111572745182864684,
295 exp: -77,
296 },
297 Fp {
298 frac: 11258999068426240000,
299 exp: -50,
300 },
301 Fp {
302 frac: 16777216000000000000,
303 exp: -24,
304 },
305 Fp {
306 frac: 12500000000000000000,
307 exp: 3,
308 },
309 Fp {
310 frac: 9313225746154785156,
311 exp: 30,
312 },
313 Fp {
314 frac: 13877787807814456755,
315 exp: 56,
316 },
317 Fp {
318 frac: 10339757656912845936,
319 exp: 83,
320 },
321 Fp {
322 frac: 15407439555097886824,
323 exp: 109,
324 },
325 Fp {
326 frac: 11479437019748901445,
327 exp: 136,
328 },
329 Fp {
330 frac: 17105694144590052135,
331 exp: 162,
332 },
333 Fp {
334 frac: 12744735289059618216,
335 exp: 189,
336 },
337 Fp {
338 frac: 9495567745759798747,
339 exp: 216,
340 },
341 Fp {
342 frac: 14149498560666738074,
343 exp: 242,
344 },
345 Fp {
346 frac: 10542197943230523224,
347 exp: 269,
348 },
349 Fp {
350 frac: 15709099088952724970,
351 exp: 295,
352 },
353 Fp {
354 frac: 11704190886730495818,
355 exp: 322,
356 },
357 Fp {
358 frac: 17440603504673385349,
359 exp: 348,
360 },
361 Fp {
362 frac: 12994262207056124023,
363 exp: 375,
364 },
365 Fp {
366 frac: 9681479787123295682,
367 exp: 402,
368 },
369 Fp {
370 frac: 14426529090290212157,
371 exp: 428,
372 },
373 Fp {
374 frac: 10748601772107342003,
375 exp: 455,
376 },
377 Fp {
378 frac: 16016664761464807395,
379 exp: 481,
380 },
381 Fp {
382 frac: 11933345169920330789,
383 exp: 508,
384 },
385 Fp {
386 frac: 17782069995880619868,
387 exp: 534,
388 },
389 Fp {
390 frac: 13248674568444952270,
391 exp: 561,
392 },
393 Fp {
394 frac: 9871031767461413346,
395 exp: 588,
396 },
397 Fp {
398 frac: 14708983551653345445,
399 exp: 614,
400 },
401 Fp {
402 frac: 10959046745042015199,
403 exp: 641,
404 },
405 Fp {
406 frac: 16330252207878254650,
407 exp: 667,
408 },
409 Fp {
410 frac: 12166986024289022870,
411 exp: 694,
412 },
413 Fp {
414 frac: 18130221999122236476,
415 exp: 720,
416 },
417 Fp {
418 frac: 13508068024458167312,
419 exp: 747,
420 },
421 Fp {
422 frac: 10064294952495520794,
423 exp: 774,
424 },
425 Fp {
426 frac: 14996968138956309548,
427 exp: 800,
428 },
429 Fp {
430 frac: 11173611982879273257,
431 exp: 827,
432 },
433 Fp {
434 frac: 16649979327439178909,
435 exp: 853,
436 },
437 Fp {
438 frac: 12405201291620119593,
439 exp: 880,
440 },
441 Fp {
442 frac: 9242595204427927429,
443 exp: 907,
444 },
445 Fp {
446 frac: 13772540099066387757,
447 exp: 933,
448 },
449 Fp {
450 frac: 10261342003245940623,
451 exp: 960,
452 },
453 Fp {
454 frac: 15290591125556738113,
455 exp: 986,
456 },
457 Fp {
458 frac: 11392378155556871081,
459 exp: 1013,
460 },
461 Fp {
462 frac: 16975966327722178521,
463 exp: 1039,
464 },
465 Fp {
466 frac: 12648080533535911531,
467 exp: 1066,
468 },
469];
470
471fn find_cachedpow10(exp: i32, k: &mut i32) -> Fp {
477 const ONE_LOG_TEN: f64 = 0.30102999566398114;
478
479 let approx = (-((exp + NPOWERS) as f64) * ONE_LOG_TEN) as i32;
480 let mut idx = (approx - FIRSTPOWER) / STEPPOWERS;
481
482 loop {
483 let current = exp + POWERS_TEN[idx as usize].exp + 64;
484 if current < EXPMIN {
485 idx += 1;
486 continue;
487 }
488 if current > EXPMAX {
489 idx -= 1;
490 continue;
491 }
492 *k = FIRSTPOWER + idx * STEPPOWERS;
493 return POWERS_TEN[idx as usize];
494 }
495}
496
497fn build_fp(d: f64) -> Fp {
499 let bits = d.to_bits();
500 let mut fp = Fp {
501 frac: bits & FRACMASK,
502 exp: ((bits & EXPMASK) >> 52) as i32,
503 };
504 if fp.exp != 0 {
505 fp.frac += HIDDENBIT;
506 fp.exp -= EXPBIAS;
507 } else {
508 fp.exp = -EXPBIAS + 1;
509 }
510 fp
511}
512
513fn normalize(fp: &mut Fp) {
516 while fp.frac & HIDDENBIT == 0 {
517 fp.frac <<= 1;
518 fp.exp -= 1;
519 }
520 let shift = 64 - 52 - 1;
521 fp.frac <<= shift;
522 fp.exp -= shift;
523}
524
525fn get_normalized_boundaries(fp: &Fp, lower: &mut Fp, upper: &mut Fp) {
528 upper.frac = (fp.frac << 1) + 1;
529 upper.exp = fp.exp - 1;
530
531 while upper.frac & (HIDDENBIT << 1) == 0 {
532 upper.frac <<= 1;
533 upper.exp -= 1;
534 }
535
536 let u_shift = 64 - 52 - 2;
537 upper.frac <<= u_shift;
538 upper.exp -= u_shift;
539
540 let l_shift = if fp.frac == HIDDENBIT { 2 } else { 1 };
543
544 lower.frac = (fp.frac << l_shift) - 1;
545 lower.exp = fp.exp - l_shift;
546
547 lower.frac <<= lower.exp - upper.exp;
548 lower.exp = upper.exp;
549}
550
551fn multiply(a: &Fp, b: &Fp) -> Fp {
553 const LOMASK: u64 = 0x0000_0000_FFFF_FFFF;
554
555 let ah_bl = (a.frac >> 32).wrapping_mul(b.frac & LOMASK);
556 let al_bh = (a.frac & LOMASK).wrapping_mul(b.frac >> 32);
557 let al_bl = (a.frac & LOMASK).wrapping_mul(b.frac & LOMASK);
558 let ah_bh = (a.frac >> 32).wrapping_mul(b.frac >> 32);
559
560 let mut tmp = (ah_bl & LOMASK)
561 .wrapping_add(al_bh & LOMASK)
562 .wrapping_add(al_bl >> 32);
563 tmp = tmp.wrapping_add(1u64 << 31);
565
566 Fp {
567 frac: ah_bh
568 .wrapping_add(ah_bl >> 32)
569 .wrapping_add(al_bh >> 32)
570 .wrapping_add(tmp >> 32),
571 exp: a.exp + b.exp + 64,
572 }
573}
574
575fn round_digit(digits: &mut [u8; 18], ndigits: usize, delta: u64, rem: u64, kappa: u64, frac: u64) {
577 let mut rem = rem;
578 while rem < frac
579 && delta.wrapping_sub(rem) >= kappa
580 && (rem.wrapping_add(kappa) < frac
581 || frac.wrapping_sub(rem) > rem.wrapping_add(kappa).wrapping_sub(frac))
582 {
583 digits[ndigits - 1] -= 1;
584 rem = rem.wrapping_add(kappa);
585 }
586}
587
588fn generate_digits(fp: &Fp, upper: &Fp, lower: &Fp, digits: &mut [u8; 18], k: &mut i32) -> usize {
595 let wfrac = upper.frac.wrapping_sub(fp.frac);
596 let mut delta = upper.frac.wrapping_sub(lower.frac);
597
598 let shift = (-upper.exp) as u32;
599 let one_frac = 1u64 << shift;
600
601 let mut part1 = upper.frac >> shift;
602 let mut part2 = upper.frac & (one_frac - 1);
603
604 let mut idx = 0usize;
605 let mut kappa: i32 = 10;
606
607 let mut divp = 10usize;
609 while kappa > 0 {
610 let div = TENS[divp];
611 let digit = part1 / div;
612
613 if digit != 0 || idx != 0 {
614 digits[idx] = b'0' + digit as u8;
615 idx += 1;
616 }
617
618 part1 -= digit * div;
619 kappa -= 1;
620
621 let tmp = (part1.wrapping_shl(shift)).wrapping_add(part2);
622 if tmp <= delta {
623 *k += kappa;
624 round_digit(digits, idx, delta, tmp, div.wrapping_shl(shift), wfrac);
625 return idx;
626 }
627 divp += 1;
628 }
629
630 let mut unit = 18usize;
631 loop {
632 part2 = part2.wrapping_mul(10);
633 delta = delta.wrapping_mul(10);
634 kappa -= 1;
635
636 let digit = part2 >> shift;
637 if digit != 0 || idx != 0 {
638 digits[idx] = b'0' + digit as u8;
639 idx += 1;
640 }
641
642 part2 &= one_frac - 1;
643 if part2 < delta {
644 *k += kappa;
645 round_digit(
646 digits,
647 idx,
648 delta,
649 part2,
650 one_frac,
651 wfrac.wrapping_mul(TENS[unit]),
652 );
653 return idx;
654 }
655 unit -= 1;
656 }
657}
658
659fn grisu2(d: f64, digits: &mut [u8; 18], k: &mut i32) -> usize {
661 let mut w = build_fp(d);
662
663 let mut lower = Fp { frac: 0, exp: 0 };
664 let mut upper = Fp { frac: 0, exp: 0 };
665 get_normalized_boundaries(&w, &mut lower, &mut upper);
666
667 normalize(&mut w);
668
669 let mut cached_k = 0;
670 let cp = find_cachedpow10(upper.exp, &mut cached_k);
671
672 w = multiply(&w, &cp);
673 upper = multiply(&upper, &cp);
674 lower = multiply(&lower, &cp);
675
676 lower.frac = lower.frac.wrapping_add(1);
679 upper.frac = upper.frac.wrapping_sub(1);
680
681 *k = -cached_k;
682
683 generate_digits(&w, &upper, &lower, digits, k)
684}
685
686fn emit_digits(digits: &[u8; 18], ndigits: usize, dest: &mut [u8], k: i32, neg: bool) -> usize {
695 let mut ndigits = ndigits;
696 let mut exp = (k + ndigits as i32 - 1).abs();
697
698 if k >= 0 && exp < ndigits as i32 + 7 {
700 let zeros = k as usize;
701 dest[..ndigits].copy_from_slice(&digits[..ndigits]);
702 dest[ndigits..ndigits + zeros].fill(b'0');
703 return ndigits + zeros;
704 }
705
706 if k < 0 && (k > -7 || exp < 4) {
708 let offset = ndigits as i32 - k.abs();
709 if offset <= 0 {
710 let lead = (-offset) as usize;
711 dest[0] = b'0';
712 dest[1] = b'.';
713 dest[2..2 + lead].fill(b'0');
714 dest[lead + 2..lead + 2 + ndigits].copy_from_slice(&digits[..ndigits]);
715 return ndigits + 2 + lead;
716 }
717 let offset = offset as usize;
718 dest[..offset].copy_from_slice(&digits[..offset]);
719 dest[offset] = b'.';
720 dest[offset + 1..ndigits + 1].copy_from_slice(&digits[offset..ndigits]);
721 return ndigits + 1;
722 }
723
724 ndigits = ndigits.min(18 - usize::from(neg));
728
729 let mut idx = 0usize;
730 dest[idx] = digits[0];
731 idx += 1;
732
733 if ndigits > 1 {
734 dest[idx] = b'.';
735 idx += 1;
736 dest[idx..idx + ndigits - 1].copy_from_slice(&digits[1..ndigits]);
737 idx += ndigits - 1;
738 }
739
740 dest[idx] = b'e';
741 idx += 1;
742 dest[idx] = if k + ndigits as i32 - 1 < 0 {
743 b'-'
744 } else {
745 b'+'
746 };
747 idx += 1;
748
749 let mut cent = 0;
750 if exp > 99 {
751 cent = exp / 100;
752 dest[idx] = b'0' + cent as u8;
753 idx += 1;
754 exp -= cent * 100;
755 }
756 if exp > 9 {
757 let dec = exp / 10;
758 dest[idx] = b'0' + dec as u8;
759 idx += 1;
760 exp -= dec * 10;
761 } else if cent != 0 {
762 dest[idx] = b'0';
763 idx += 1;
764 }
765 dest[idx] = b'0' + (exp % 10) as u8;
766 idx + 1
767}
768
769pub fn dtoa(d: f64, dest: &mut [u8]) -> usize {
774 debug_assert!(dest.len() >= MAX);
775
776 let mut len = 0usize;
777 let neg = d.to_bits() & SIGNMASK != 0;
778 if neg {
779 dest[0] = b'-';
780 len = 1;
781 }
782
783 if d == 0.0 {
786 dest[len] = b'0';
787 return len + 1;
788 }
789 if d.is_nan() {
790 dest[len..len + 3].copy_from_slice(b"nan");
791 return len + 3;
792 }
793 if d.is_infinite() {
794 dest[len..len + 3].copy_from_slice(b"inf");
795 return len + 3;
796 }
797
798 let mut digits = [0u8; 18];
799 let mut k = 0i32;
800 let ndigits = grisu2(d, &mut digits, &mut k);
801
802 len + emit_digits(&digits, ndigits, &mut dest[len..], k, neg)
803}
804
805#[cfg(test)]
806mod tests {
807 use super::*;
808
809 fn text(d: f64) -> String {
810 let mut buf = [0u8; MAX];
811 let n = dtoa(d, &mut buf);
812 String::from_utf8(buf[..n].to_vec()).expect("digits are ascii")
813 }
814
815 #[test]
816 fn the_two_plain_forms_cover_the_ordinary_range() {
817 for (d, want) in [
819 (0.0, "0"),
820 (-0.0, "-0"),
821 (1.0, "1"),
822 (-1.0, "-1"),
823 (0.5, "0.5"),
824 (0.3, "0.3"),
825 (-0.3, "-0.3"),
826 (3.0e3, "3000"),
827 (1.5, "1.5"),
828 (1234.5678, "1234.5678"),
829 (0.001234, "0.001234"),
830 (core::f64::consts::PI, "3.141592653589793"),
831 (0.0001, "0.0001"),
832 ] {
833 assert_eq!(text(d), want, "{d}");
834 }
835 }
836
837 #[test]
838 fn a_large_or_small_magnitude_switches_to_an_exponent() {
839 for (d, want) in [
842 (1.0e15, "1e+15"),
846 (1.0e30, "1e+30"),
847 (-1.0e30, "-1e+30"),
848 (1.0e-7, "1e-7"),
849 (1.0e19, "1e+19"),
850 (1.0e100, "1e+100"),
851 (1.0e-100, "1e-100"),
852 (5.0e-324, "5e-324"),
853 (f64::MAX, "1.7976931348623157e+308"),
854 (f64::MIN_POSITIVE, "2.2250738585072014e-308"),
855 (1.2345678e-5, "1.2345678e-5"),
856 ] {
857 assert_eq!(text(d), want, "{d}");
858 }
859 }
860
861 #[test]
862 fn the_special_values_are_written_as_words() {
863 assert_eq!(text(f64::INFINITY), "inf");
864 assert_eq!(text(f64::NEG_INFINITY), "-inf");
865 assert_eq!(text(f64::NAN), "nan");
866 assert_eq!(text(-f64::NAN), "-nan");
867 }
868
869 #[test]
870 fn everything_written_reads_back_as_the_same_double() {
871 let mut state = 0x2545_F491_4F6C_DD1Du64;
876 let mut checked = 0u32;
877 for _ in 0..200_000 {
878 state ^= state << 13;
879 state ^= state >> 7;
880 state ^= state << 17;
881 let d = f64::from_bits(state);
882 if !d.is_finite() {
883 continue;
884 }
885 let s = text(d);
886 let back: f64 = s.parse().expect("what was written parses");
887 assert_eq!(back.to_bits(), d.to_bits(), "{s}");
888 checked += 1;
889 }
890 assert!(checked > 190_000, "only {checked} finite values");
891 }
892
893 #[test]
894 fn nothing_written_needs_more_room_than_the_buffer() {
895 let mut widest = 0usize;
896 let mut state = 0x9E37_79B9_7F4A_7C15u64;
897 for _ in 0..200_000 {
898 state ^= state << 13;
899 state ^= state >> 7;
900 state ^= state << 17;
901 let d = f64::from_bits(state);
902 if !d.is_finite() {
903 continue;
904 }
905 let mut buf = [0u8; MAX];
906 widest = widest.max(dtoa(d, &mut buf));
907 }
908 for d in [9.999999999999999e23, -9.999999999999999e23] {
910 let mut buf = [0u8; MAX];
911 widest = widest.max(dtoa(d, &mut buf));
912 }
913 assert!(widest <= MAX, "{widest} bytes needs more than {MAX}");
914 }
915}