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:
parent
a205633643
commit
0a0089fc11
Notes:
sideshowbarker
2024-07-18 08:50:21 +09:00
Author: https://github.com/dascandy Commit: https://github.com/SerenityOS/serenity/commit/0a0089fc11f Pull-request: https://github.com/SerenityOS/serenity/pull/8841 Reviewed-by: https://github.com/linusg ✅
1 changed files with 9 additions and 2 deletions
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue