|
36 | 36 | /// https://doi.org/10.1145/2837614.2837654
|
37 | 37 | /// In particular, the Errol paper explored the impact of higher-precision
|
38 | 38 | /// fixed-width arithmetic on Grisu2 and showed a way to rapidly test
|
39 |
| -/// the correctness of such algorithms. |
| 39 | +/// the correctness of Grisu-style algorithms. |
40 | 40 | ///
|
41 | 41 | /// A few further improvements were inspired by the Ryu algorithm
|
42 | 42 | /// from Ulf Anders; "Ryū: fast float-to-string conversion", 2018.
|
|
53 | 53 | /// values on 32-bit processors, and higher-precision values on all
|
54 | 54 | /// processors, it is considerably faster.
|
55 | 55 | ///
|
56 |
| -/// * Always Accurate. Converting the decimal form back to binary |
57 |
| -/// will always yield exactly the same value. For the IEEE 754 |
58 |
| -/// formats, the round-trip will produce exactly the same bit |
59 |
| -/// pattern in memory. |
| 56 | +/// * Always Accurate. Except for NaNs, converting the decimal form |
| 57 | +/// back to binary will always yield an equal value. For the IEEE |
| 58 | +/// 754 formats, the round trip will produce exactly the same bit |
| 59 | +/// pattern in memory. This assumes, of course, that the conversion |
| 60 | +/// from text to binary uses a correctly-rounded algorithm such as |
| 61 | +/// Clinger 1990 or Eisel-Lemire 2021. |
60 | 62 | ///
|
61 | 63 | /// * Always Short. This always selects an accurate result with the
|
62 | 64 | /// minimum number of significant digits.
|
|
73 | 75 | /// * When present, a '.' is never the first or last character
|
74 | 76 | /// * There is a consecutive range of integer values that can be
|
75 | 77 | /// represented in any particular type (-2^54...2^54 for double).
|
76 |
| -/// Never use exponential form for integral numbers in this range. |
| 78 | +/// We do not use exponential form for integral numbers in this |
| 79 | +/// range. |
77 | 80 | /// * Generally follow existing practice: Don't use use exponential
|
78 | 81 | /// form for fractional values bigger than 10^-4; always write at
|
79 | 82 | /// least 2 digits for an exponent.
|
80 | 83 | /// * Apart from the above, we do prefer shorter output.
|
81 | 84 |
|
| 85 | +/// Note: If you want to compare performance of this implementation |
| 86 | +/// versus some others, keep in mind that this implementation does |
| 87 | +/// deliberately sacrifice some performance. Any attempt to compare |
| 88 | +/// the performance of this implementation to others should |
| 89 | +/// try to compensate for the following: |
| 90 | +/// * The output ergonomics described above do take some time. |
| 91 | +/// It would be faster to always emit the form "123456e-78" |
| 92 | +// (See `finishFormatting()`) |
| 93 | +/// * The implementations in published papers generally include |
| 94 | +/// large tables with every power of 10 computed out. We've |
| 95 | +/// factored these tables down to conserve code size, which |
| 96 | +/// requires some additional work to reconstruct the needed power |
| 97 | +/// of 10. (See the `intervalContainingPowerOf10_*` functions) |
| 98 | + |
82 | 99 | ///
|
83 | 100 | /// This Swift implementation was ported from an earlier C version;
|
84 | 101 | /// the output is exactly the same in all cases.
|
|
90 | 107 | /// implementation to ensure that no unsafety actually occurs. For
|
91 | 108 | /// Float32, that testing was exhaustive -- we verified all 4
|
92 | 109 | /// billion possible Float32 values.
|
93 |
| -/// * The Swift code uses an idiom of building up to 8 ASCII characters |
| 110 | +/// * The Swift code uses an idiom of building up to 8 digit characters |
94 | 111 | /// in a UInt64 and then writing the whole block to memory.
|
95 | 112 | /// * The Swift version is slightly faster than the C version;
|
96 | 113 | /// mostly thanks to various minor algorithmic tweaks that were
|
@@ -348,6 +365,7 @@ fileprivate func _Float16ToASCII(
|
348 | 365 | // Exhaustive testing shows that the only input value
|
349 | 366 | // affected by this is 0.015625 == 2^-6, which
|
350 | 367 | // incorrectly prints as "0.01562" without this fix.
|
| 368 | + // With this, it prints correctly as "0.01563" |
351 | 369 | if t < lDigit || (t == lDigit && l > 0) {
|
352 | 370 | t += 1
|
353 | 371 | }
|
|
0 commit comments