From 69624e4de22f67e7e817d7a1e152c68982e17d38 Mon Sep 17 00:00:00 2001 From: Ruben Ayrapetyan Date: Mon, 27 Oct 2014 15:29:17 +0300 Subject: [PATCH] Fixing search of shortest representation in ecma_number_to_zt_string. Fixing right shift operation for big integers. --- src/libecmaobjects/ecma-helpers-conversion.c | 374 +++++++++++-------- src/libecmaobjects/ecma-helpers-number.c | 105 +++++- src/libecmaobjects/ecma-helpers.h | 2 + 3 files changed, 306 insertions(+), 175 deletions(-) diff --git a/src/libecmaobjects/ecma-helpers-conversion.c b/src/libecmaobjects/ecma-helpers-conversion.c index 211352b92..ac7dcc089 100644 --- a/src/libecmaobjects/ecma-helpers-conversion.c +++ b/src/libecmaobjects/ecma-helpers-conversion.c @@ -45,6 +45,11 @@ */ #define ECMA_NUMBER_CONVERSION_128BIT_INTEGER(name) uint64_t name[4] = { 0, 0, 0, 0 } +/** + * Declare 128-bit in-out argument integer. + */ +#define ECMA_NUMBER_CONVERSION_128BIT_INTEGER_ARG(name) uint64_t name[4] + /** * Initialize 128-bit integer with given 32-bit parts */ @@ -78,7 +83,7 @@ #define ECMA_NUMBER_CONVERSION_128BIT_INTEGER_ROUND_HIGH_AND_MIDDLE_TO_UINT64(name, uint64_var) \ { \ ECMA_NUMBER_CONVERSION_128BIT_INTEGER_CHECK_PARTS_ARE_32BIT (name); \ - uint64_var = (name[3] << 32u) | (name[2] + ((name[1] >> 31u) != 0 ? 1 : 0)); \ + uint64_var = ((name[3] << 32u) | (name[2])) + (((name[1] >> 31u) != 0 ? 1 : 0)); \ } /** @@ -842,6 +847,70 @@ ecma_number_to_int32 (ecma_number_t value) /**< unsigned 32-bit integer value */ return (int32_t) (uint32_t) value; } /* ecma_number_to_int32 */ +/** + * Perform conversion of binary representation of number to decimal representation with decimal exponent + */ +static void +ecma_number_to_zt_string_to_decimal (ECMA_NUMBER_CONVERSION_128BIT_INTEGER_ARG (fraction_uint128), /**< mantissa */ + int32_t binary_exponent, /**< binary exponent */ + int32_t *out_decimal_exp_p) /**< out: decimal exponent */ +{ + int32_t decimal_exp = 0; + + if (binary_exponent > 0) + { + while (binary_exponent > 0) + { + if (!ECMA_NUMBER_CONVERSION_128BIT_INTEGER_IS_HIGH_BIT_MASK_ZERO (fraction_uint128, 124)) + { + ECMA_NUMBER_CONVERSION_128BIT_INTEGER_INC (fraction_uint128); + ECMA_NUMBER_CONVERSION_128BIT_INTEGER_RIGHT_SHIFT (fraction_uint128); + binary_exponent++; + } + else + { + ECMA_NUMBER_CONVERSION_128BIT_INTEGER (fraction_uint128_tmp); + ECMA_NUMBER_CONVERSION_128BIT_INTEGER_COPY (fraction_uint128_tmp, fraction_uint128); + ECMA_NUMBER_CONVERSION_128BIT_INTEGER_DIV_10 (fraction_uint128_tmp); + ECMA_NUMBER_CONVERSION_128BIT_INTEGER_MUL_10 (fraction_uint128_tmp); + + if (!ECMA_NUMBER_CONVERSION_128BIT_INTEGER_ARE_EQUAL (fraction_uint128, fraction_uint128_tmp) + && ECMA_NUMBER_CONVERSION_128BIT_INTEGER_IS_HIGH_BIT_MASK_ZERO (fraction_uint128, 123)) + { + ECMA_NUMBER_CONVERSION_128BIT_INTEGER_LEFT_SHIFT (fraction_uint128); + binary_exponent--; + } + else + { + ECMA_NUMBER_CONVERSION_128BIT_INTEGER_DIV_10 (fraction_uint128); + decimal_exp++; + } + } + } + } + else if (binary_exponent < 0) + { + while (binary_exponent < 0) + { + if (ECMA_NUMBER_CONVERSION_128BIT_INTEGER_IS_LOW_BIT_MASK_ZERO (fraction_uint128, 0) + || !ECMA_NUMBER_CONVERSION_128BIT_INTEGER_IS_HIGH_BIT_MASK_ZERO (fraction_uint128, 124)) + { + ECMA_NUMBER_CONVERSION_128BIT_INTEGER_RIGHT_SHIFT (fraction_uint128); + + binary_exponent++; + } + else + { + ECMA_NUMBER_CONVERSION_128BIT_INTEGER_MUL_10 (fraction_uint128); + + decimal_exp--; + } + } + } + + *out_decimal_exp_p = decimal_exp; +} /* ecma_number_to_zt_string_to_decimal */ + /** * Calculate s, n and k parameters for specified ecma-number according to ECMA-262 v5, 9.8.1, item 5 */ @@ -851,200 +920,169 @@ ecma_number_to_zt_string_calc_number_params (ecma_number_t num, /**< ecma-number int32_t *out_digits_num_p, /**< out: number of digits */ int32_t *out_decimal_exp_p) /**< out: decimal exponent */ { + JERRY_ASSERT (!ecma_number_is_nan (num)); + JERRY_ASSERT (!ecma_number_is_zero (num)); + JERRY_ASSERT (!ecma_number_is_infinity (num)); + + ecma_number_t num_m1 = ecma_number_get_prev (num); + ecma_number_t num_p1 = ecma_number_get_next (num); + ECMA_NUMBER_CONVERSION_128BIT_INTEGER (fraction_uint128); + ECMA_NUMBER_CONVERSION_128BIT_INTEGER (fraction_uint128_m1); + ECMA_NUMBER_CONVERSION_128BIT_INTEGER (fraction_uint128_p1); -#if CONFIG_ECMA_NUMBER_TYPE == CONFIG_ECMA_NUMBER_FLOAT32 - uint32_t s[2]; -#elif CONFIG_ECMA_NUMBER_TYPE == CONFIG_ECMA_NUMBER_FLOAT64 - uint64_t s[2]; -#endif /* CONFIG_ECMA_NUMBER_TYPE == CONFIG_ECMA_NUMBER_FLOAT64 */ - int32_t k[2]; - int32_t n[2]; + uint64_t fraction_uint64, fraction_uint64_m1, fraction_uint64_p1; + int32_t binary_exponent, binary_exponent_m1, binary_exponent_p1; + int32_t decimal_exp, decimal_exp_m1, decimal_exp_p1; + int32_t dot_shift, dot_shift_m1, dot_shift_p1; - for (uint32_t i = 0; - i <= 1; - i++) + dot_shift_m1 = ecma_number_get_fraction_and_exponent (num_m1, &fraction_uint64_m1, &binary_exponent_m1); + dot_shift = ecma_number_get_fraction_and_exponent (num, &fraction_uint64, &binary_exponent); + dot_shift_p1 = ecma_number_get_fraction_and_exponent (num_p1, &fraction_uint64_p1, &binary_exponent_p1); + + binary_exponent_m1 -= dot_shift_m1; + binary_exponent -= dot_shift; + binary_exponent_p1 -= dot_shift_p1; + + ECMA_NUMBER_CONVERSION_128BIT_INTEGER_INIT (fraction_uint128, + 0ull, + 0ull, + (fraction_uint64) >> 32u, + ((fraction_uint64) << 32u) >> 32u); + ECMA_NUMBER_CONVERSION_128BIT_INTEGER_INIT (fraction_uint128_m1, + 0ull, + 0ull, + (fraction_uint64_m1) >> 32u, + ((fraction_uint64_m1) << 32u) >> 32u); + ECMA_NUMBER_CONVERSION_128BIT_INTEGER_INIT (fraction_uint128_p1, + 0ull, + 0ull, + (fraction_uint64_p1) >> 32u, + ((fraction_uint64_p1) << 32u) >> 32u); + + ecma_number_to_zt_string_to_decimal (fraction_uint128, binary_exponent, &decimal_exp); + ecma_number_to_zt_string_to_decimal (fraction_uint128_m1, binary_exponent_m1, &decimal_exp_m1); + ecma_number_to_zt_string_to_decimal (fraction_uint128_p1, binary_exponent_p1, &decimal_exp_p1); + + if (ECMA_NUMBER_CONVERSION_128BIT_INTEGER_IS_ZERO (fraction_uint128_m1)) { - uint64_t fraction_uint64; - int32_t binary_exponent; - int32_t dot_shift; - int32_t decimal_exp = 0; + decimal_exp_m1 = decimal_exp; + } - dot_shift = ecma_number_get_fraction_and_exponent (num, &fraction_uint64, &binary_exponent); - - binary_exponent -= dot_shift; - - JERRY_ASSERT (fraction_uint64 != 0); - - if (i == 0) + while (decimal_exp != decimal_exp_m1 + || decimal_exp != decimal_exp_p1) + { + while (decimal_exp > decimal_exp_m1 + || decimal_exp > decimal_exp_p1) { - /* Lowest binary fraction that should round to fraction_uint64 */ - ECMA_NUMBER_CONVERSION_128BIT_INTEGER_INIT (fraction_uint128, - 0ull, - (fraction_uint64 - 1ull) >> 48u, - ((fraction_uint64 - 1ull) << 16u) >> 32u, - ((fraction_uint64 - 1ull) << 48u) >> 32u | 0x8000u); + ECMA_NUMBER_CONVERSION_128BIT_INTEGER_MUL_10 (fraction_uint128); + decimal_exp--; } - else + while (decimal_exp_m1 > decimal_exp + || decimal_exp_m1 > decimal_exp_p1) { - /* Highest binary fraction that should round to fraction_uint64 */ - ECMA_NUMBER_CONVERSION_128BIT_INTEGER_INIT (fraction_uint128, - 0ull, - (fraction_uint64) >> 48u, - ((fraction_uint64) << 16u) >> 32u, - ((fraction_uint64) << 48u) >> 32u | 0x7fffu); + ECMA_NUMBER_CONVERSION_128BIT_INTEGER_MUL_10 (fraction_uint128_m1); + decimal_exp_m1--; } - - binary_exponent -= 16; - - /* Converting binary exponent to decimal exponent */ - if (binary_exponent > 0) + while (decimal_exp_p1 > decimal_exp + || decimal_exp_p1 > decimal_exp_m1) { - while (binary_exponent > 0) - { - if (!ECMA_NUMBER_CONVERSION_128BIT_INTEGER_IS_HIGH_BIT_MASK_ZERO (fraction_uint128, 124)) - { - ECMA_NUMBER_CONVERSION_128BIT_INTEGER_INC (fraction_uint128); - ECMA_NUMBER_CONVERSION_128BIT_INTEGER_RIGHT_SHIFT (fraction_uint128); - binary_exponent++; - } - else - { - ECMA_NUMBER_CONVERSION_128BIT_INTEGER (fraction_uint128_tmp); - ECMA_NUMBER_CONVERSION_128BIT_INTEGER_COPY (fraction_uint128_tmp, fraction_uint128); - ECMA_NUMBER_CONVERSION_128BIT_INTEGER_DIV_10 (fraction_uint128_tmp); - ECMA_NUMBER_CONVERSION_128BIT_INTEGER_MUL_10 (fraction_uint128_tmp); - - if (!ECMA_NUMBER_CONVERSION_128BIT_INTEGER_ARE_EQUAL (fraction_uint128, fraction_uint128_tmp) - && ECMA_NUMBER_CONVERSION_128BIT_INTEGER_IS_HIGH_BIT_MASK_ZERO (fraction_uint128, 123)) - { - ECMA_NUMBER_CONVERSION_128BIT_INTEGER_LEFT_SHIFT (fraction_uint128); - binary_exponent--; - } - else - { - ECMA_NUMBER_CONVERSION_128BIT_INTEGER_DIV_10 (fraction_uint128); - decimal_exp++; - } - } - } + ECMA_NUMBER_CONVERSION_128BIT_INTEGER_MUL_10 (fraction_uint128_p1); + decimal_exp_p1--; } - else if (binary_exponent < 0) - { - while (binary_exponent < 0) - { - if (ECMA_NUMBER_CONVERSION_128BIT_INTEGER_IS_LOW_BIT_MASK_ZERO (fraction_uint128, 0) - || !ECMA_NUMBER_CONVERSION_128BIT_INTEGER_IS_HIGH_BIT_MASK_ZERO (fraction_uint128, 124)) - { - ECMA_NUMBER_CONVERSION_128BIT_INTEGER_RIGHT_SHIFT (fraction_uint128); + } - binary_exponent++; - } - else - { - ECMA_NUMBER_CONVERSION_128BIT_INTEGER_MUL_10 (fraction_uint128); + ECMA_NUMBER_CONVERSION_128BIT_INTEGER_ADD (fraction_uint128_m1, fraction_uint128); + ECMA_NUMBER_CONVERSION_128BIT_INTEGER_RIGHT_SHIFT (fraction_uint128_m1); - decimal_exp--; - } - } - } + ECMA_NUMBER_CONVERSION_128BIT_INTEGER_ADD (fraction_uint128_p1, fraction_uint128); + ECMA_NUMBER_CONVERSION_128BIT_INTEGER_RIGHT_SHIFT (fraction_uint128_p1); + /* While fraction doesn't fit to integer, divide it by 10 + and simultaneously increment decimal exponent */ #if CONFIG_ECMA_NUMBER_TYPE == CONFIG_ECMA_NUMBER_FLOAT64 - uint64_t digits, t; + uint64_t digits_min, digits_max; - /* While fraction doesn't fit to 64-bit integer, divide it by 10 - and simultaneously increment decimal exponent */ - while (!ECMA_NUMBER_CONVERSION_128BIT_INTEGER_IS_HIGH_BIT_MASK_ZERO (fraction_uint128, 64)) - { - ECMA_NUMBER_CONVERSION_128BIT_INTEGER_DIV_10 (fraction_uint128); - decimal_exp++; - } + while (!ECMA_NUMBER_CONVERSION_128BIT_INTEGER_IS_HIGH_BIT_MASK_ZERO (fraction_uint128_m1, 63)) + { + ECMA_NUMBER_CONVERSION_128BIT_INTEGER_DIV_10 (fraction_uint128_m1); + decimal_exp_m1++; + } + while (!ECMA_NUMBER_CONVERSION_128BIT_INTEGER_IS_HIGH_BIT_MASK_ZERO (fraction_uint128_p1, 63)) + { + ECMA_NUMBER_CONVERSION_128BIT_INTEGER_DIV_10 (fraction_uint128_p1); + decimal_exp_p1++; + } + + ECMA_NUMBER_CONVERSION_128BIT_INTEGER_ROUND_MIDDLE_AND_LOW_TO_UINT64 (fraction_uint128_m1, digits_min); + ECMA_NUMBER_CONVERSION_128BIT_INTEGER_ROUND_MIDDLE_AND_LOW_TO_UINT64 (fraction_uint128_p1, digits_max); + + digits_min++; #elif CONFIG_ECMA_NUMBER_TYPE == CONFIG_ECMA_NUMBER_FLOAT32 - uint32_t digits, t; + uint64_t digits_uint64; + uint32_t digits_min, digits_max; - while (!ECMA_NUMBER_CONVERSION_128BIT_INTEGER_IS_HIGH_BIT_MASK_ZERO (fraction_uint128, 32)) - { - ECMA_NUMBER_CONVERSION_128BIT_INTEGER_DIV_10 (fraction_uint128); - decimal_exp++; - } + while (!ECMA_NUMBER_CONVERSION_128BIT_INTEGER_IS_HIGH_BIT_MASK_ZERO (fraction_uint128_m1, 31)) + { + ECMA_NUMBER_CONVERSION_128BIT_INTEGER_DIV_10 (fraction_uint128_m1); + decimal_exp_m1++; + } + while (!ECMA_NUMBER_CONVERSION_128BIT_INTEGER_IS_HIGH_BIT_MASK_ZERO (fraction_uint128_p1, 31)) + { + ECMA_NUMBER_CONVERSION_128BIT_INTEGER_DIV_10 (fraction_uint128_p1); + decimal_exp_p1++; + } + + ECMA_NUMBER_CONVERSION_128BIT_INTEGER_ROUND_MIDDLE_AND_LOW_TO_UINT64 (fraction_uint128_m1, digits_uint64); + digits_min = (uint32_t) digits_uint64 + 1; + + ECMA_NUMBER_CONVERSION_128BIT_INTEGER_ROUND_MIDDLE_AND_LOW_TO_UINT64 (fraction_uint128_p1, digits_uint64); + digits_max = (uint32_t) digits_uint64; #endif /* CONFIG_ECMA_NUMBER_TYPE == CONFIG_ECMA_NUMBER_FLOAT32 */ - uint64_t digits_uint64; - int32_t digits_num = 0; + if (decimal_exp_m1 < decimal_exp_p1) + { + JERRY_ASSERT (decimal_exp_m1 == decimal_exp_p1 - 1); - ECMA_NUMBER_CONVERSION_128BIT_INTEGER_ROUND_MIDDLE_AND_LOW_TO_UINT64 (fraction_uint128, digits_uint64); + digits_min /= 10; + decimal_exp_m1++; + } + else if (decimal_exp_m1 > decimal_exp_p1) + { + JERRY_ASSERT (decimal_exp_m1 == decimal_exp_p1 + 1); + digits_max /= 10; + decimal_exp_p1++; + } + + JERRY_ASSERT (digits_max >= digits_min); + + while (digits_min / 10 != digits_max / 10) + { + digits_min /= 10; + digits_max /= 10; + decimal_exp_m1++; + decimal_exp_p1++; + } + + uint64_t digits = (digits_min + digits_max + 1) / 2; + int32_t digits_num = 0; #if CONFIG_ECMA_NUMBER_TYPE == CONFIG_ECMA_NUMBER_FLOAT64 - digits = digits_uint64; + uint64_t t = digits; #elif CONFIG_ECMA_NUMBER_TYPE == CONFIG_ECMA_NUMBER_FLOAT32 - digits = (uint32_t) digits_uint64; - - JERRY_ASSERT (digits == digits_uint64); + uint32_t t = (uint32_t) digits; #endif /* CONFIG_ECMA_NUMBER_TYPE == CONFIG_ECMA_NUMBER_FLOAT32 */ - - /* Calculate number of digits in the number */ - t = digits; - while (t != 0) - { - if (digits_num < ECMA_NUMBER_MAX_DIGITS) - { - digits_num++; - } - else - { - if (t < 10) - { - digits += 5; - } - - digits /= 10; - } - - t /= 10; - - decimal_exp++; - } - - /* Saving bound values */ - s[i] = digits; - k[i] = digits_num; - n[i] = decimal_exp; - } - - /* Making bound values' digit sets to be of one length */ - for (uint32_t i = 0; i <= 1; i++) + while (t != 0) { - while (n[i] - k[i] > n[1 - i] - k[1 - i]) - { - JERRY_ASSERT (s[i] * 10 > s[i]); - - s[i] *= 10; - k[i]++; - } + t /= 10; + digits_num++; } - JERRY_ASSERT (s[1] > s[0]); + JERRY_ASSERT (digits_num > 0); - while (s[0] / 10 != s[1] / 10) - { - s[0] /= 10; - s[1] /= 10; - k[0]--; - k[1]--; - } - - /* Rounding up */ - if (k[0] == k[1]) - { - *out_digits_p = (s[0] + s[1] + 1) / 2; - } - else - { - *out_digits_p = s[1]; - } - - *out_digits_num_p = k[1]; - *out_decimal_exp_p = n[1]; + *out_digits_p = digits; + *out_digits_num_p = digits_num; + *out_decimal_exp_p = decimal_exp_p1 + digits_num; } /* ecma_number_to_zt_string_calc_number_params */ /** @@ -1105,6 +1143,10 @@ ecma_number_to_zt_string (ecma_number_t num, /**< ecma-number */ } else { + ecma_number_t p = ecma_number_get_prev (num); + ecma_number_t q = ecma_number_get_next (p); + JERRY_ASSERT (q == num); + // 5. uint32_t num_uint32 = ecma_number_to_uint32 (num); if (ecma_uint32_to_number (num_uint32) == num) diff --git a/src/libecmaobjects/ecma-helpers-number.c b/src/libecmaobjects/ecma-helpers-number.c index bf4143bf2..9a774fcb0 100644 --- a/src/libecmaobjects/ecma-helpers-number.c +++ b/src/libecmaobjects/ecma-helpers-number.c @@ -401,8 +401,6 @@ ecma_number_get_fraction_and_exponent (ecma_number_t num, /**< ecma-number */ int32_t *out_exponent_p) /**< out: exponent of the number */ { JERRY_ASSERT (!ecma_number_is_nan (num)); - JERRY_ASSERT (!ecma_number_is_zero (num)); - JERRY_ASSERT (!ecma_number_is_infinity (num)); uint32_t biased_exp = ecma_number_get_biased_exponent_field (num); uint64_t fraction = ecma_number_get_fraction_field (num); @@ -411,15 +409,30 @@ ecma_number_get_fraction_and_exponent (ecma_number_t num, /**< ecma-number */ if (unlikely (biased_exp == 0)) { /* IEEE-754 2008, 3.4, d */ - exponent = 1 - ecma_number_exponent_bias; - - while (!(fraction & (1ull << ECMA_NUMBER_FRACTION_WIDTH))) + if (ecma_number_is_zero (num)) { - JERRY_ASSERT (fraction != 0); - - fraction <<= 1; - exponent--; + exponent = -ecma_number_exponent_bias; } + else + { + exponent = 1 - ecma_number_exponent_bias; + + while (!(fraction & (1ull << ECMA_NUMBER_FRACTION_WIDTH))) + { + JERRY_ASSERT (fraction != 0); + + fraction <<= 1; + exponent--; + } + } + } + else if (ecma_number_is_infinity (num)) + { + /* The fraction and exponent should round to infinity */ + exponent = (int32_t) biased_exp - ecma_number_exponent_bias; + + JERRY_ASSERT ((fraction & (1ull << ECMA_NUMBER_FRACTION_WIDTH)) == 0); + fraction |= 1ull << ECMA_NUMBER_FRACTION_WIDTH; } else { @@ -540,6 +553,80 @@ ecma_number_make_from_sign_mantissa_and_exponent (bool sign, /**< true - for neg mantissa); } /* ecma_number_make_from_sign_mantissa_and_exponent */ +/** + * Get previous representable ecma-number + * + * @return maximum ecma-number that is less compared to passed argument + */ +ecma_number_t +ecma_number_get_prev (ecma_number_t num) /**< ecma-number */ +{ + JERRY_ASSERT (!ecma_number_is_nan (num)); + JERRY_ASSERT (!ecma_number_is_zero (num)); + + if (ecma_number_is_negative (num)) + { + return ecma_number_negate (ecma_number_get_next (num)); + } + + uint32_t biased_exp = ecma_number_get_biased_exponent_field (num); + uint64_t fraction = ecma_number_get_fraction_field (num); + + if (fraction == 0 && biased_exp != 0) + { + fraction = (1ull << ECMA_NUMBER_FRACTION_WIDTH) - 1; + + biased_exp--; + } + else + { + fraction--; + } + + return ecma_number_pack (false, + biased_exp, + fraction); +} /* ecma_number_get_prev */ + +/** + * Get next representable ecma-number + * + * @return minimum ecma-number that is greater compared to passed argument + */ +ecma_number_t +ecma_number_get_next (ecma_number_t num) /**< ecma-number */ +{ + JERRY_ASSERT (!ecma_number_is_nan (num)); + JERRY_ASSERT (!ecma_number_is_infinity (num)); + + if (ecma_number_is_negative (num)) + { + return ecma_number_negate (ecma_number_get_prev (num)); + } + + uint32_t biased_exp = ecma_number_get_biased_exponent_field (num); + uint64_t fraction = ecma_number_get_fraction_field (num); + + fraction |= (1ull << ECMA_NUMBER_FRACTION_WIDTH); + + fraction++; + + if ((fraction & (1ull << ECMA_NUMBER_FRACTION_WIDTH)) == 0) + { + fraction >>= 1; + + biased_exp++; + } + + JERRY_ASSERT (fraction & (1ull << ECMA_NUMBER_FRACTION_WIDTH)); + + fraction &= ~(1ull << ECMA_NUMBER_FRACTION_WIDTH); + + return ecma_number_pack (false, + biased_exp, + fraction); +} /* ecma_number_get_next */ + /** * Negate ecma-number * diff --git a/src/libecmaobjects/ecma-helpers.h b/src/libecmaobjects/ecma-helpers.h index 48a3a09ea..4d28c04b9 100644 --- a/src/libecmaobjects/ecma-helpers.h +++ b/src/libecmaobjects/ecma-helpers.h @@ -148,6 +148,8 @@ extern ecma_number_t ecma_number_make_from_sign_mantissa_and_exponent (bool sign, uint64_t mantissa, int32_t exponent); +extern ecma_number_t ecma_number_get_prev (ecma_number_t num); +extern ecma_number_t ecma_number_get_next (ecma_number_t num); extern ecma_number_t ecma_number_negate (ecma_number_t num); extern ecma_number_t ecma_number_trunc (ecma_number_t num); extern ecma_number_t ecma_number_add (ecma_number_t left_num, ecma_number_t right_num);