From b6fc4e13ae882d297d3b9768e7bb0f2de9c43cfc Mon Sep 17 00:00:00 2001 From: Daniella Barsony Date: Fri, 31 May 2019 08:31:36 +0200 Subject: [PATCH] Fix rounding issue (#2890) Fixes #2802 JerryScript-DCO-1.0-Signed-off-by: Daniella Barsony bella@inf.u-szeged.hu --- .../ecma/base/ecma-helpers-conversion.c | 19 ++++++++++-- tests/jerry/arithmetics-bignums.js | 29 ++++++++++++++++++- tests/jerry/regression-test-issue-2802.js | 15 ++++++++++ 3 files changed, 59 insertions(+), 4 deletions(-) create mode 100644 tests/jerry/regression-test-issue-2802.js diff --git a/jerry-core/ecma/base/ecma-helpers-conversion.c b/jerry-core/ecma/base/ecma-helpers-conversion.c index d40bbe1c1..3d4aa329c 100644 --- a/jerry-core/ecma/base/ecma-helpers-conversion.c +++ b/jerry-core/ecma/base/ecma-helpers-conversion.c @@ -46,9 +46,22 @@ typedef struct /** * Round high part of 128-bit integer to uint64_t + * + * @return rounded high to uint64_t */ -#define ECMA_UINT128_ROUND_HIGH_TO_UINT64(name) \ - (name.hi + (name.lo >> 63u)) +static uint64_t +ecma_round_high_to_uint64 (ecma_uint128_t *num_p) +{ + uint64_t masked_lo = num_p->lo & ~(1ULL << 63u); + uint64_t masked_hi = num_p->hi & 0x1; + + if ((num_p->lo >> 63u != 0) + && (masked_lo > 0 || masked_hi != 0)) + { + return (num_p->hi + 1); + } + return num_p->hi; +} /* ecma_round_high_to_uint64 */ /** * Check if 128-bit integer is zero @@ -650,7 +663,7 @@ ecma_utf8_string_to_number (const lit_utf8_byte_t *str_p, /**< utf-8 string */ JERRY_ASSERT (ECMA_UINT128_CLZ_MAX63 (fraction_uint128) == 11); - fraction_uint64 = ECMA_UINT128_ROUND_HIGH_TO_UINT64 (fraction_uint128); + fraction_uint64 = ecma_round_high_to_uint64 (&fraction_uint128); return ecma_number_make_from_sign_mantissa_and_exponent (sign, fraction_uint64, binary_exponent); #elif !ENABLED (JERRY_NUMBER_TYPE_FLOAT64) diff --git a/tests/jerry/arithmetics-bignums.js b/tests/jerry/arithmetics-bignums.js index 39ee7a3d2..ec694d075 100644 --- a/tests/jerry/arithmetics-bignums.js +++ b/tests/jerry/arithmetics-bignums.js @@ -23,8 +23,35 @@ assert(big == 2147483648); // overflow on 32bit numbers big++; assert(big == 2147483649); // overflow on 32bit numbers -assert ((1152921504606846976).toString() === "1152921504606847000") +assert ((1152921504606846976).toString() === "1152921504606847000"); assert (1.797693134862315808e+308 === Infinity); assert (9999999999999999 == 10000000000000000); + +assert((9007199254740993).toString() === "9007199254740992"); + +assert((9007199254740992).toString() === "9007199254740992"); + +assert((9007199254740994).toString() === "9007199254740994"); + +assert((1.00517e+21).toString() === "1.0051699999999999e+21"); + +assert((1.00001e+21).toString() === "1.0000099999999999e+21"); + +assert((9007199254740995).toString() === "9007199254740996"); + +assert((18014398509481989).toString() === "18014398509481988"); + +assert((18014398509481990).toString() === "18014398509481992"); + +assert((18014398509481991).toString() === "18014398509481992"); + +assert((18014398509481993).toString() === "18014398509481992"); + +assert((18014398509481994).toString() === "18014398509481992"); + +assert((18014398509481997).toString() === "18014398509481996"); + +assert((18014398509481998).toString() === "18014398509482000"); + diff --git a/tests/jerry/regression-test-issue-2802.js b/tests/jerry/regression-test-issue-2802.js new file mode 100644 index 000000000..c210c2f04 --- /dev/null +++ b/tests/jerry/regression-test-issue-2802.js @@ -0,0 +1,15 @@ +// Copyright JS Foundation and other contributors, http://js.foundation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +assert(2e23 == 1.9999999999999998e+23);