Improving precision of number to zt-string conversion, adding search for the shortest representation of number during the conversion.

This commit is contained in:
Ruben Ayrapetyan
2014-10-24 19:15:31 +04:00
parent 4f68e43b7d
commit e4629cca51
5 changed files with 326 additions and 161 deletions
+6
View File
@@ -160,6 +160,7 @@ else
OPTION_LIBC := raw
endif
# float64 mode
ifeq ($(filter float64,$(TARGET_MODS)), float64)
ifeq ($(OPTION_MCU),enable)
$(error MCU target doesn\'t support float64)
@@ -170,6 +171,11 @@ else
OPTION_FLOAT64 := disable
endif
# Enabling float64 mode for unittests
ifeq ($(filter-out $(TESTS_TARGET),$(TARGET_MODE)),)
OPTION_FLOAT64 := enable
endif
ifeq ($(filter sanitize,$(TARGET_MODS)), sanitize)
ifeq ($(OPTION_LIBC),musl)
$(error ASAN and LIBC_MUSL are mutually exclusive)
+2 -2
View File
@@ -527,7 +527,7 @@ typedef float ecma_number_t;
/**
* Maximum number of significant digits that ecma-number can store
*/
#define ECMA_NUMBER_MAX_DIGITS (10u)
#define ECMA_NUMBER_MAX_DIGITS (9)
#elif CONFIG_ECMA_NUMBER_TYPE == CONFIG_ECMA_NUMBER_FLOAT64
/**
* Description of an ecma-number
@@ -537,7 +537,7 @@ typedef double ecma_number_t;
/**
* Maximum number of significant digits that ecma-number can store
*/
#define ECMA_NUMBER_MAX_DIGITS (18u)
#define ECMA_NUMBER_MAX_DIGITS (18)
#endif /* CONFIG_ECMA_NUMBER_TYPE == CONFIG_ECMA_NUMBER_FLOAT64 */
/**
+300 -141
View File
@@ -78,19 +78,44 @@
uint64_var = (name[2] << 32u) | (name[1] + ((name[0] >> 31u) != 0 ? 1 : 0)); \
}
/**
* Copy middle and low parts of 96-bit integer to specified uint64_t variable
*/
#define ECMA_NUMBER_CONVERSION_96BIT_INTEGER_ROUND_MIDDLE_AND_LOW_TO_UINT64(name, uint64_var) \
{ \
ECMA_NUMBER_CONVERSION_96BIT_INTEGER_CHECK_PARTS_ARE_32BIT (name); \
uint64_var = (name[1] << 32u) | (name[0]); \
}
/**
* Check if specified 96-bit integers are equal
*/
#define ECMA_NUMBER_CONVERSION_96BIT_INTEGER_ARE_EQUAL(name1, name2) \
((name1)[0] == (name2[0]) \
&& (name1)[1] == (name2[1]) \
&& (name1)[2] == (name2[2]))
/**
* Check if bits [lowest_bit, 96) are zero
*/
#define ECMA_NUMBER_CONVERSION_96BIT_INTEGER_IS_BIT_MASK_ZERO(name, lowest_bit) \
#define ECMA_NUMBER_CONVERSION_96BIT_INTEGER_IS_HIGH_BIT_MASK_ZERO(name, lowest_bit) \
((lowest_bit) >= 64 ? ((name[2] >> ((lowest_bit) - 64)) == 0) : \
((lowest_bit) >= 32 ? (name[2] == 0 && ((name[1] >> ((lowest_bit) - 32)) == 0)) : \
(name[2] == 0 && name[1] == 0 && ((name[0] >> (lowest_bit)) == 0))))
/**
* Check if bits [0, highest_bit] are zero
*/
#define ECMA_NUMBER_CONVERSION_96BIT_INTEGER_IS_LOW_BIT_MASK_ZERO(name, highest_bit) \
((highest_bit >= 64) ? (name[1] == 0 && name[0] == 0 && (((uint32_t) name[2] << (95 - (highest_bit))) == 0)) : \
((highest_bit >= 32) ? (name[0] == 0 && (((uint32_t) name[1] << (63 - (highest_bit))) == 0)) : \
(((uint32_t) name[0] << (31 - (highest_bit))) == 0)))
/**
* Check if 96-bit integer is zero
*/
#define ECMA_NUMBER_CONVERSION_96BIT_INTEGER_IS_ZERO(name) \
ECMA_NUMBER_CONVERSION_96BIT_INTEGER_IS_BIT_MASK_ZERO (name, 0)
ECMA_NUMBER_CONVERSION_96BIT_INTEGER_IS_HIGH_BIT_MASK_ZERO (name, 0)
/**
* Shift 96-bit integer one bit left
@@ -125,7 +150,23 @@
}
/**
* Add to 96-bit integers
* Increment 96-bit integer
*/
#define ECMA_NUMBER_CONVERSION_96BIT_INTEGER_INC(name) \
{ \
ECMA_NUMBER_CONVERSION_96BIT_INTEGER_CHECK_PARTS_ARE_32BIT (name); \
\
name [0] += 1ull; \
name [1] += (name [0] >> 32u); \
name [0] = (uint32_t) name [0]; \
name [2] += (name [1] >> 32u); \
name [1] = (uint32_t) name [1]; \
\
ECMA_NUMBER_CONVERSION_96BIT_INTEGER_CHECK_PARTS_ARE_32BIT (name); \
}
/**
* Add 96-bit integer
*/
#define ECMA_NUMBER_CONVERSION_96BIT_INTEGER_ADD(name_add_to, name_to_add) \
{ \
@@ -144,6 +185,28 @@
ECMA_NUMBER_CONVERSION_96BIT_INTEGER_CHECK_PARTS_ARE_32BIT (name_to_add); \
}
/**
* Multiply 96-bit integer by 10
*/
#define ECMA_NUMBER_CONVERSION_96BIT_INTEGER_MUL_10(name) \
{ \
ECMA_NUMBER_CONVERSION_96BIT_INTEGER_CHECK_PARTS_ARE_32BIT (name); \
\
/* fraction_uint96 = (fraction_uint96 << 3) + (fraction_uint96 << 1) or fraction_uint96 *= 10 */ \
ECMA_NUMBER_CONVERSION_96BIT_INTEGER_LEFT_SHIFT (name); \
\
ECMA_NUMBER_CONVERSION_96BIT_INTEGER (name ## _tmp); \
\
ECMA_NUMBER_CONVERSION_96BIT_INTEGER_COPY (name ## _tmp, name); \
\
ECMA_NUMBER_CONVERSION_96BIT_INTEGER_LEFT_SHIFT (name ## _tmp); \
ECMA_NUMBER_CONVERSION_96BIT_INTEGER_LEFT_SHIFT (name ## _tmp); \
\
ECMA_NUMBER_CONVERSION_96BIT_INTEGER_ADD (name, name ## _tmp); \
\
ECMA_NUMBER_CONVERSION_96BIT_INTEGER_CHECK_PARTS_ARE_32BIT (name); \
}
/**
* Divide 96-bit integer by 10
*/
@@ -507,9 +570,9 @@ ecma_zt_string_to_number (const ecma_char_t *str_p) /**< zero-terminated string
0ull);
/* Normalizing mantissa */
JERRY_ASSERT (ECMA_NUMBER_CONVERSION_96BIT_INTEGER_IS_BIT_MASK_ZERO (fraction_uint96, 92));
JERRY_ASSERT (ECMA_NUMBER_CONVERSION_96BIT_INTEGER_IS_HIGH_BIT_MASK_ZERO (fraction_uint96, 92));
while (ECMA_NUMBER_CONVERSION_96BIT_INTEGER_IS_BIT_MASK_ZERO (fraction_uint96, 91))
while (ECMA_NUMBER_CONVERSION_96BIT_INTEGER_IS_HIGH_BIT_MASK_ZERO (fraction_uint96, 91))
{
ECMA_NUMBER_CONVERSION_96BIT_INTEGER_LEFT_SHIFT (fraction_uint96);
binary_exponent--;
@@ -524,30 +587,20 @@ ecma_zt_string_to_number (const ecma_char_t *str_p) /**< zero-terminated string
while (e > 0)
{
JERRY_ASSERT (ECMA_NUMBER_CONVERSION_96BIT_INTEGER_IS_BIT_MASK_ZERO (fraction_uint96, 92));
JERRY_ASSERT (ECMA_NUMBER_CONVERSION_96BIT_INTEGER_IS_HIGH_BIT_MASK_ZERO (fraction_uint96, 92));
/* fraction_uint96 = (fraction_uint96 << 3) + (fraction_uint96 << 1) or fraction_uint96 *= 10 */
ECMA_NUMBER_CONVERSION_96BIT_INTEGER_LEFT_SHIFT (fraction_uint96);
ECMA_NUMBER_CONVERSION_96BIT_INTEGER (fraction_uint96_tmp);
ECMA_NUMBER_CONVERSION_96BIT_INTEGER_COPY (fraction_uint96_tmp, fraction_uint96);
ECMA_NUMBER_CONVERSION_96BIT_INTEGER_LEFT_SHIFT (fraction_uint96_tmp);
ECMA_NUMBER_CONVERSION_96BIT_INTEGER_LEFT_SHIFT (fraction_uint96_tmp);
ECMA_NUMBER_CONVERSION_96BIT_INTEGER_ADD (fraction_uint96, fraction_uint96_tmp);
ECMA_NUMBER_CONVERSION_96BIT_INTEGER_MUL_10 (fraction_uint96);
e--;
/* Normalizing mantissa */
while (!ECMA_NUMBER_CONVERSION_96BIT_INTEGER_IS_BIT_MASK_ZERO (fraction_uint96, 92))
while (!ECMA_NUMBER_CONVERSION_96BIT_INTEGER_IS_HIGH_BIT_MASK_ZERO (fraction_uint96, 92))
{
ECMA_NUMBER_CONVERSION_96BIT_INTEGER_RIGHT_SHIFT (fraction_uint96);
binary_exponent++;
}
while (ECMA_NUMBER_CONVERSION_96BIT_INTEGER_IS_BIT_MASK_ZERO (fraction_uint96, 91))
while (ECMA_NUMBER_CONVERSION_96BIT_INTEGER_IS_HIGH_BIT_MASK_ZERO (fraction_uint96, 91))
{
ECMA_NUMBER_CONVERSION_96BIT_INTEGER_LEFT_SHIFT (fraction_uint96);
@@ -565,7 +618,7 @@ ecma_zt_string_to_number (const ecma_char_t *str_p) /**< zero-terminated string
while (e > 0)
{
/* Denormalizing mantissa, moving highest 1 to 95-bit */
while (ECMA_NUMBER_CONVERSION_96BIT_INTEGER_IS_BIT_MASK_ZERO (fraction_uint96, 95))
while (ECMA_NUMBER_CONVERSION_96BIT_INTEGER_IS_HIGH_BIT_MASK_ZERO (fraction_uint96, 95))
{
ECMA_NUMBER_CONVERSION_96BIT_INTEGER_LEFT_SHIFT (fraction_uint96);
@@ -580,13 +633,13 @@ ecma_zt_string_to_number (const ecma_char_t *str_p) /**< zero-terminated string
}
/* Normalizing mantissa */
while (!ECMA_NUMBER_CONVERSION_96BIT_INTEGER_IS_BIT_MASK_ZERO (fraction_uint96, 92))
while (!ECMA_NUMBER_CONVERSION_96BIT_INTEGER_IS_HIGH_BIT_MASK_ZERO (fraction_uint96, 92))
{
ECMA_NUMBER_CONVERSION_96BIT_INTEGER_RIGHT_SHIFT (fraction_uint96);
binary_exponent++;
}
while (ECMA_NUMBER_CONVERSION_96BIT_INTEGER_IS_BIT_MASK_ZERO (fraction_uint96, 91))
while (ECMA_NUMBER_CONVERSION_96BIT_INTEGER_IS_HIGH_BIT_MASK_ZERO (fraction_uint96, 91))
{
ECMA_NUMBER_CONVERSION_96BIT_INTEGER_LEFT_SHIFT (fraction_uint96);
@@ -597,20 +650,20 @@ ecma_zt_string_to_number (const ecma_char_t *str_p) /**< zero-terminated string
}
JERRY_ASSERT (!ECMA_NUMBER_CONVERSION_96BIT_INTEGER_IS_ZERO (fraction_uint96));
JERRY_ASSERT (ECMA_NUMBER_CONVERSION_96BIT_INTEGER_IS_BIT_MASK_ZERO (fraction_uint96, 92));
JERRY_ASSERT (ECMA_NUMBER_CONVERSION_96BIT_INTEGER_IS_HIGH_BIT_MASK_ZERO (fraction_uint96, 92));
/*
* Preparing mantissa for conversion to 52-bit representation, converting it to:
*
* |12 zero bits|84 mantissa bits|
*/
while (!ECMA_NUMBER_CONVERSION_96BIT_INTEGER_IS_BIT_MASK_ZERO (fraction_uint96, 84 + 1))
while (!ECMA_NUMBER_CONVERSION_96BIT_INTEGER_IS_HIGH_BIT_MASK_ZERO (fraction_uint96, 84 + 1))
{
ECMA_NUMBER_CONVERSION_96BIT_INTEGER_RIGHT_SHIFT (fraction_uint96);
binary_exponent++;
}
while (ECMA_NUMBER_CONVERSION_96BIT_INTEGER_IS_BIT_MASK_ZERO (fraction_uint96, 84))
while (ECMA_NUMBER_CONVERSION_96BIT_INTEGER_IS_HIGH_BIT_MASK_ZERO (fraction_uint96, 84))
{
ECMA_NUMBER_CONVERSION_96BIT_INTEGER_LEFT_SHIFT (fraction_uint96);
@@ -619,7 +672,7 @@ ecma_zt_string_to_number (const ecma_char_t *str_p) /**< zero-terminated string
JERRY_ASSERT (!ECMA_NUMBER_CONVERSION_96BIT_INTEGER_IS_ZERO (fraction_uint96));
}
JERRY_ASSERT (ECMA_NUMBER_CONVERSION_96BIT_INTEGER_IS_BIT_MASK_ZERO (fraction_uint96, 84 + 1));
JERRY_ASSERT (ECMA_NUMBER_CONVERSION_96BIT_INTEGER_IS_HIGH_BIT_MASK_ZERO (fraction_uint96, 84 + 1));
ECMA_NUMBER_CONVERSION_96BIT_INTEGER_ROUND_HIGH_AND_MIDDLE_TO_UINT64 (fraction_uint96, fraction_uint64);
@@ -740,6 +793,209 @@ ecma_number_to_int32 (ecma_number_t value) /**< unsigned 32-bit integer value */
return (int32_t) value;
} /* ecma_number_to_int32 */
/**
* Calculate s, n and k parameters for specified ecma-number according to ECMA-262 v5, 9.8.1, item 5
*/
static void
ecma_number_to_zt_string_calc_number_params (ecma_number_t num, /**< ecma-number */
uint64_t *out_digits_p, /**< out: digits */
int32_t *out_digits_num_p, /**< out: number of digits */
int32_t *out_decimal_exp_p) /**< out: decimal exponent */
{
ECMA_NUMBER_CONVERSION_96BIT_INTEGER (fraction_uint96);
#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];
for (uint32_t i = 0;
i <= 1;
i++)
{
uint64_t fraction_uint64;
int32_t binary_exponent;
int32_t dot_shift;
int32_t decimal_exp = 0;
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)
{
/* Lowest binary fraction that should round to fraction_uint64 */
ECMA_NUMBER_CONVERSION_96BIT_INTEGER_INIT (fraction_uint96,
(fraction_uint64 - 1ull) >> 60u,
((fraction_uint64 - 1ull) << 4u) >> 32u,
((fraction_uint64 - 1ull) << 36u) >> 32u | 0x8u);
}
else
{
/* Highest binary fraction that should round to fraction_uint64 */
ECMA_NUMBER_CONVERSION_96BIT_INTEGER_INIT (fraction_uint96,
(fraction_uint64) >> 60u,
((fraction_uint64) << 4u) >> 32u,
((fraction_uint64) << 36u) >> 32u | 0x7u);
}
binary_exponent -= 4;
/* Converting binary exponent to decimal exponent */
if (binary_exponent > 0)
{
while (binary_exponent > 0)
{
if (!ECMA_NUMBER_CONVERSION_96BIT_INTEGER_IS_HIGH_BIT_MASK_ZERO (fraction_uint96, 92))
{
ECMA_NUMBER_CONVERSION_96BIT_INTEGER_INC (fraction_uint96);
ECMA_NUMBER_CONVERSION_96BIT_INTEGER_RIGHT_SHIFT (fraction_uint96);
binary_exponent++;
}
else
{
ECMA_NUMBER_CONVERSION_96BIT_INTEGER (fraction_uint96_tmp);
ECMA_NUMBER_CONVERSION_96BIT_INTEGER_COPY (fraction_uint96_tmp, fraction_uint96);
ECMA_NUMBER_CONVERSION_96BIT_INTEGER_DIV_10 (fraction_uint96_tmp);
ECMA_NUMBER_CONVERSION_96BIT_INTEGER_MUL_10 (fraction_uint96_tmp);
if (!ECMA_NUMBER_CONVERSION_96BIT_INTEGER_ARE_EQUAL (fraction_uint96, fraction_uint96_tmp)
&& ECMA_NUMBER_CONVERSION_96BIT_INTEGER_IS_HIGH_BIT_MASK_ZERO (fraction_uint96, 91))
{
ECMA_NUMBER_CONVERSION_96BIT_INTEGER_LEFT_SHIFT (fraction_uint96);
binary_exponent--;
}
else
{
ECMA_NUMBER_CONVERSION_96BIT_INTEGER_DIV_10 (fraction_uint96);
decimal_exp++;
}
}
}
}
else if (binary_exponent < 0)
{
while (binary_exponent < 0)
{
if (ECMA_NUMBER_CONVERSION_96BIT_INTEGER_IS_LOW_BIT_MASK_ZERO (fraction_uint96, 0)
|| !ECMA_NUMBER_CONVERSION_96BIT_INTEGER_IS_HIGH_BIT_MASK_ZERO (fraction_uint96, 92))
{
ECMA_NUMBER_CONVERSION_96BIT_INTEGER_RIGHT_SHIFT (fraction_uint96);
binary_exponent++;
}
else
{
ECMA_NUMBER_CONVERSION_96BIT_INTEGER_MUL_10 (fraction_uint96);
decimal_exp--;
}
}
}
#if CONFIG_ECMA_NUMBER_TYPE == CONFIG_ECMA_NUMBER_FLOAT64
uint64_t digits, t;
/* While fraction doesn't fit to 64-bit integer, divide it by 10
and simultaneously increment decimal exponent */
while (!ECMA_NUMBER_CONVERSION_96BIT_INTEGER_IS_HIGH_BIT_MASK_ZERO (fraction_uint96, 64))
{
ECMA_NUMBER_CONVERSION_96BIT_INTEGER_DIV_10 (fraction_uint96);
decimal_exp++;
}
#elif CONFIG_ECMA_NUMBER_TYPE == CONFIG_ECMA_NUMBER_FLOAT32
uint32_t digits, t;
while (!ECMA_NUMBER_CONVERSION_96BIT_INTEGER_IS_HIGH_BIT_MASK_ZERO (fraction_uint96, 32))
{
ECMA_NUMBER_CONVERSION_96BIT_INTEGER_DIV_10 (fraction_uint96);
decimal_exp++;
}
#endif /* CONFIG_ECMA_NUMBER_TYPE == CONFIG_ECMA_NUMBER_FLOAT32 */
uint64_t digits_uint64;
int32_t digits_num = 0;
ECMA_NUMBER_CONVERSION_96BIT_INTEGER_ROUND_MIDDLE_AND_LOW_TO_UINT64 (fraction_uint96, digits_uint64);
#if CONFIG_ECMA_NUMBER_TYPE == CONFIG_ECMA_NUMBER_FLOAT64
digits = digits_uint64;
#elif CONFIG_ECMA_NUMBER_TYPE == CONFIG_ECMA_NUMBER_FLOAT32
digits = (uint32_t) digits_uint64;
JERRY_ASSERT (digits == digits_uint64);
#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 (n[i] - k[i] > n[1 - i] - k[1 - i])
{
JERRY_ASSERT (s[i] * 10 > s[i]);
s[i] *= 10;
k[i]++;
}
}
JERRY_ASSERT (s[1] > s[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];
} /* ecma_number_to_zt_string_calc_number_params */
/**
* Convert ecma-number to zero-terminated string
*
@@ -757,8 +1013,6 @@ ecma_number_to_zt_string (ecma_number_t num, /**< ecma-number */
ecma_char_t *buffer_p, /**< buffer for zt-string */
ssize_t buffer_size) /**< size of buffer */
{
FIXME (Conversion precision);
const ecma_char_t digits[10] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' };
const ecma_char_t e_chars [2] = { 'e', 'E' };
const ecma_char_t plus_char = '+';
@@ -801,14 +1055,6 @@ ecma_number_to_zt_string (ecma_number_t num, /**< ecma-number */
else
{
// 5.
#if CONFIG_ECMA_NUMBER_TYPE == CONFIG_ECMA_NUMBER_FLOAT32
#define LL_T uint32_t
#define LL_MAX_DIGITS 10
#elif CONFIG_ECMA_NUMBER_TYPE == CONFIG_ECMA_NUMBER_FLOAT64
#define LL_T uint64_t
#define LL_MAX_DIGITS 18
#endif /* CONFIG_ECMA_NUMBER_TYPE == CONFIG_ECMA_NUMBER_FLOAT64 */
uint32_t num_uint32 = ecma_number_to_uint32 (num);
if (ecma_uint32_to_number (num_uint32) == num)
{
@@ -817,116 +1063,29 @@ ecma_number_to_zt_string (ecma_number_t num, /**< ecma-number */
else
{
uint64_t fraction_uint64;
LL_T fraction;
int32_t exponent;
int32_t dot_shift;
int32_t decimal_exp = 0;
int32_t binary_exponent;
dot_shift = ecma_number_get_fraction_and_exponent (num, &fraction_uint64, &exponent);
ecma_number_get_fraction_and_exponent (num, &fraction_uint64, &binary_exponent);
fraction = (LL_T) fraction_uint64;
JERRY_ASSERT (fraction == fraction_uint64);
if (exponent != 0)
{
ecma_number_t t = 1.0f;
bool do_divide;
if (exponent < 0)
{
do_divide = true;
while (exponent <= 0)
{
t *= 2.0f;
exponent++;
if (t >= 10.0f)
{
t /= 10.0f;
decimal_exp--;
}
JERRY_ASSERT (t < 10.0f);
}
while (t > 1.0f)
{
exponent--;
t /= 2.0f;
}
}
else
{
do_divide = false;
while (exponent >= 0)
{
t *= 2.0f;
exponent--;
if (t >= 10.0f)
{
t /= 10.0f;
decimal_exp++;
}
JERRY_ASSERT (t < 10.0f);
}
while (t > 2.0f)
{
exponent++;
t /= 2.0f;
}
}
if (do_divide)
{
fraction = (LL_T) ((ecma_number_t) fraction / t);
}
else
{
fraction = (LL_T) ((ecma_number_t) fraction * t);
}
}
LL_T s;
/* mantissa */
uint64_t s_uint64;
/* decimal exponent */
int32_t n;
/* number of digits in k */
int32_t k;
if (exponent > 0)
{
fraction <<= exponent;
}
else
{
fraction >>= -exponent;
}
ecma_number_to_zt_string_calc_number_params (num,
&s_uint64,
&k,
&n);
const int32_t int_part_shift = dot_shift;
const LL_T frac_part_mask = ((((LL_T)1) << int_part_shift) - 1);
#if CONFIG_ECMA_NUMBER_TYPE == CONFIG_ECMA_NUMBER_FLOAT64
uint64_t s = s_uint64;
#elif CONFIG_ECMA_NUMBER_TYPE == CONFIG_ECMA_NUMBER_FLOAT32
uint32_t s = (uint32_t) s_uint64;
LL_T int_part = fraction >> int_part_shift;
LL_T frac_part = fraction & frac_part_mask;
s = int_part;
k = 1;
n = decimal_exp + 1;
JERRY_ASSERT (int_part < 10);
while (k < LL_MAX_DIGITS
&& frac_part != 0)
{
frac_part *= 10;
LL_T new_frac_part = frac_part & frac_part_mask;
LL_T digit = (frac_part - new_frac_part) >> int_part_shift;
s = s * 10 + digit;
k++;
frac_part = new_frac_part;
}
JERRY_ASSERT (s == s_uint64);
#endif /* CONFIG_ECMA_NUMBER_TYPE == CONFIG_ECMA_NUMBER_FLOAT32 */
// 6.
if (k <= n && n <= 21)
@@ -969,7 +1128,7 @@ ecma_number_to_zt_string (ecma_number_t num, /**< ecma-number */
s /= 10;
}
}
else if (-6 <= n && n <= 0)
else if (-6 < n && n <= 0)
{
// 8.
dst_p += k - n + 1 + 1;
@@ -1039,7 +1198,7 @@ ecma_number_to_zt_string (ecma_number_t num, /**< ecma-number */
{
t_mod /= 10;
JERRY_ASSERT (t_mod != 0);
JERRY_ASSERT (t != 0);
}
while (t_mod != 0)
+10 -10
View File
@@ -32,8 +32,8 @@ main( int __unused argc,
(const ecma_char_t*) "1",
(const ecma_char_t*) "0.5",
(const ecma_char_t*) "12345",
(const ecma_char_t*) "12345.12209",
(const ecma_char_t*) "1.401298403e-45",
(const ecma_char_t*) "12345.123",
(const ecma_char_t*) "1e-45",
(const ecma_char_t*) "-2.5e+38",
(const ecma_char_t*) "NaN",
(const ecma_char_t*) "Infinity",
@@ -44,17 +44,17 @@ main( int __unused argc,
const ecma_number_t nums[] =
{
1.0f,
0.5f,
12345.0f,
12345.123f,
1.0e-45f,
-2.5e+38f,
1.0,
0.5,
12345.0,
12345.123,
1.0e-45,
-2.5e+38,
NAN,
INFINITY,
-INFINITY,
+0.0f,
-0.0f
+0.0,
-0.0
};
for (uint32_t i = 0;
+8 -8
View File
@@ -51,12 +51,12 @@ main( int __unused argc,
const ecma_number_t nums[] =
{
1.0f,
0.5f,
12345.0f,
1.0e-45f,
-2.5e+38f,
-2.5e+38f,
1.0,
0.5,
12345.0,
1.0e-45,
-2.5e+38,
-2.5e+38,
NAN,
NAN,
NAN,
@@ -67,8 +67,8 @@ main( int __unused argc,
NAN,
INFINITY,
-INFINITY,
+0.0f,
-0.0f
+0.0,
-0.0
};
for (uint32_t i = 0;