LibC strtod: Reduce incremental error to nearly nothing

Instead of scaling by 1/10th N times, scale 10^N and then divide by
that. Avoid doing this beyond double-infinity. This decreases the
progressive error for numbers outside of integer range immensely. Not
a full 100% fix; there is still a single ULP difference detected by a
Javascript test
This commit is contained in:
Peter Bindels 2021-07-17 22:49:37 +02:00 committed by Linus Groh
parent a205633643
commit 0a0089fc11
Notes: sideshowbarker 2024-07-18 08:50:21 +09:00

View file

@ -646,9 +646,15 @@ double strtod(const char* str, char** endptr)
// TODO: If `exponent` is large, this could be made faster.
double value = digits.number();
double scale = 1;
if (exponent < 0) {
exponent = -exponent;
for (int i = 0; i < exponent; ++i) {
for (int i = 0; i < min(exponent, 300); ++i) {
scale *= base;
}
value /= scale;
for (int i = 300; i < exponent; i++) {
value /= base;
}
if (value == -0.0 || value == +0.0) {
@ -656,8 +662,9 @@ double strtod(const char* str, char** endptr)
}
} else if (exponent > 0) {
for (int i = 0; i < exponent; ++i) {
value *= base;
scale *= base;
}
value *= scale;
if (value == -__builtin_huge_val() || value == +__builtin_huge_val()) {
errno = ERANGE;
}