Module: wine Branch: master Commit: 29288c0bc0ea724bf27ffa1e731e4d4b5b45643b URL: https://source.winehq.org/git/wine.git/?a=commit;h=29288c0bc0ea724bf27ffa1e7...
Author: Piotr Caban piotr@codeweavers.com Date: Thu Jul 23 15:38:46 2020 +0200
msvcrt: Fix rounding of numbers smaller than minimal subnormal.
Signed-off-by: Piotr Caban piotr@codeweavers.com Signed-off-by: Alexandre Julliard julliard@winehq.org
---
dlls/msvcrt/string.c | 28 +++++++++++++++------------- dlls/ucrtbase/tests/string.c | 2 ++ 2 files changed, 17 insertions(+), 13 deletions(-)
diff --git a/dlls/msvcrt/string.c b/dlls/msvcrt/string.c index 5b6d73626a..ab6747db5c 100644 --- a/dlls/msvcrt/string.c +++ b/dlls/msvcrt/string.c @@ -413,25 +413,21 @@ int fpnum_double(struct fpnum *fp, double *d) fp->m >>= 1; fp->exp++; } - - /* handle subnormal that falls into regular range due to rounding */ fp->exp += (1 << (EXP_BITS-1)) - 1; - if (!fp->exp && (fp->mod == FP_ROUND_UP || (fp->mod == FP_ROUND_EVEN && fp->m & 1))) - { - if (fp->m + 1 >= (ULONGLONG)1 << MANT_BITS) - { - fp->m++; - fp->m >>= 1; - fp->exp++; - fp->mod = FP_ROUND_DOWN; - } - }
/* handle subnormals */ if (fp->exp <= 0) + { + if (fp->m & 1 && fp->mod == FP_ROUND_ZERO) fp->mod = FP_ROUND_EVEN; + else if (fp->m & 1) fp->mod = FP_ROUND_UP; + else if (fp->mod != FP_ROUND_ZERO) fp->mod = FP_ROUND_DOWN; fp->m >>= 1; + } while(fp->m && fp->exp<0) { + if (fp->m & 1 && fp->mod == FP_ROUND_ZERO) fp->mod = FP_ROUND_EVEN; + else if (fp->m & 1) fp->mod = FP_ROUND_UP; + else if (fp->mod != FP_ROUND_ZERO) fp->mod = FP_ROUND_DOWN; fp->m >>= 1; fp->exp++; } @@ -440,7 +436,13 @@ int fpnum_double(struct fpnum *fp, double *d) if (fp->mod == FP_ROUND_UP || (fp->mod == FP_ROUND_EVEN && fp->m & 1)) { fp->m++; - if (fp->m >= (ULONGLONG)1 << MANT_BITS) + + /* handle subnormal that falls into regular range due to rounding */ + if (fp->m == (ULONGLONG)1 << (MANT_BITS - 1)) + { + fp->exp++; + } + else if (fp->m >= (ULONGLONG)1 << MANT_BITS) { fp->exp++; fp->m >>= 1; diff --git a/dlls/ucrtbase/tests/string.c b/dlls/ucrtbase/tests/string.c index 5857a02773..3a4b8b9f04 100644 --- a/dlls/ucrtbase/tests/string.c +++ b/dlls/ucrtbase/tests/string.c @@ -148,6 +148,8 @@ static void test_strtod(void) test_strtod_str("1.7976931348623158e+308", 1.7976931348623158e+308, 23); test_strtod_str("2.2250738585072014e-308", 2.2250738585072014e-308, 23); test_strtod_str("4.9406564584124654e-324", 4.9406564584124654e-324, 23); + test_strtod_str("2.48e-324", 4.9406564584124654e-324, 9); + test_strtod_str_errno("2.47e-324", 0, 9, ERANGE); }
static void test__memicmp(void)