Improve float number handling and conversion (#4820)
Fixes #4739. JerryScript-DCO-1.0-Signed-off-by: Dániel Bátyai dbatyai@inf.u-szeged.hu
This commit is contained in:
@@ -1386,112 +1386,34 @@ typedef struct
|
||||
#define ECMA_PROPERTY_FLAGS_MASK \
|
||||
((uint16_t) (JERRY_PROP_IS_CONFIGURABLE | JERRY_PROP_IS_ENUMERABLE | JERRY_PROP_IS_WRITABLE))
|
||||
|
||||
#if !JERRY_NUMBER_TYPE_FLOAT64
|
||||
/**
|
||||
* Description of an ecma-number
|
||||
*/
|
||||
typedef float ecma_number_t;
|
||||
|
||||
/**
|
||||
* It makes possible to read/write an ecma_number_t as uint32_t without strict aliasing rule violation.
|
||||
*/
|
||||
typedef union
|
||||
{
|
||||
ecma_number_t as_ecma_number_t;
|
||||
uint32_t as_uint32_t;
|
||||
} ecma_number_accessor_t;
|
||||
|
||||
#define DOUBLE_TO_ECMA_NUMBER_T(value) (ecma_number_t) (value)
|
||||
|
||||
/**
|
||||
* Maximum number of significant digits that ecma-number can store
|
||||
*/
|
||||
#define ECMA_NUMBER_MAX_DIGITS (9)
|
||||
|
||||
/**
|
||||
* Width of sign field
|
||||
*
|
||||
* See also:
|
||||
* IEEE-754 2008, 3.6, Table 3.5
|
||||
*/
|
||||
#define ECMA_NUMBER_SIGN_WIDTH (1)
|
||||
|
||||
/**
|
||||
* Width of biased exponent field
|
||||
*
|
||||
* See also:
|
||||
* IEEE-754 2008, 3.6, Table 3.5
|
||||
*/
|
||||
#define ECMA_NUMBER_BIASED_EXP_WIDTH (8)
|
||||
|
||||
/**
|
||||
* Width of fraction field
|
||||
*
|
||||
* See also:
|
||||
* IEEE-754 2008, 3.6, Table 3.5
|
||||
*/
|
||||
#define ECMA_NUMBER_FRACTION_WIDTH (23)
|
||||
#elif JERRY_NUMBER_TYPE_FLOAT64
|
||||
/**
|
||||
* Description of an ecma-number
|
||||
*/
|
||||
#if JERRY_NUMBER_TYPE_FLOAT64
|
||||
typedef double ecma_number_t;
|
||||
|
||||
/**
|
||||
* It makes possible to read/write an ecma_number_t as uint64_t without strict aliasing rule violation.
|
||||
*/
|
||||
typedef union
|
||||
{
|
||||
ecma_number_t as_ecma_number_t;
|
||||
uint64_t as_uint64_t;
|
||||
} ecma_number_accessor_t;
|
||||
|
||||
#define DOUBLE_TO_ECMA_NUMBER_T(value) value
|
||||
|
||||
/**
|
||||
* Maximum number of significant digits that ecma-number can store
|
||||
*/
|
||||
#define ECMA_NUMBER_MAX_DIGITS (19)
|
||||
|
||||
/**
|
||||
* Width of sign field
|
||||
*
|
||||
* See also:
|
||||
* IEEE-754 2008, 3.6, Table 3.5
|
||||
*/
|
||||
#define ECMA_NUMBER_SIGN_WIDTH (1)
|
||||
|
||||
/**
|
||||
* Width of biased exponent field
|
||||
*
|
||||
* See also:
|
||||
* IEEE-754 2008, 3.6, Table 3.5
|
||||
*/
|
||||
#define ECMA_NUMBER_BIASED_EXP_WIDTH (11)
|
||||
|
||||
/**
|
||||
* Width of fraction field
|
||||
*
|
||||
* See also:
|
||||
* IEEE-754 2008, 3.6, Table 3.5
|
||||
*/
|
||||
#define ECMA_NUMBER_FRACTION_WIDTH (52)
|
||||
#else /* !JERRY_NUMBER_TYPE_FLOAT64 */
|
||||
typedef float ecma_number_t;
|
||||
#endif /* !JERRY_NUMBER_TYPE_FLOAT64 */
|
||||
|
||||
/**
|
||||
* Convert double to an ecma-number.
|
||||
*/
|
||||
#define DOUBLE_TO_ECMA_NUMBER_T(value) ((ecma_number_t) (value))
|
||||
|
||||
/**
|
||||
* Value '0' of ecma_number_t
|
||||
*/
|
||||
#define ECMA_NUMBER_ZERO ((ecma_number_t) 0)
|
||||
#define ECMA_NUMBER_ZERO ((ecma_number_t) 0.0f)
|
||||
|
||||
/**
|
||||
* Value '1' of ecma_number_t
|
||||
*/
|
||||
#define ECMA_NUMBER_ONE ((ecma_number_t) 1)
|
||||
#define ECMA_NUMBER_ONE ((ecma_number_t) 1.0f)
|
||||
|
||||
/**
|
||||
* Value '2' of ecma_number_t
|
||||
*/
|
||||
#define ECMA_NUMBER_TWO ((ecma_number_t) 2)
|
||||
#define ECMA_NUMBER_TWO ((ecma_number_t) 2.0f)
|
||||
|
||||
/**
|
||||
* Value '0.5' of ecma_number_t
|
||||
@@ -1501,117 +1423,7 @@ typedef union
|
||||
/**
|
||||
* Value '-1' of ecma_number_t
|
||||
*/
|
||||
#define ECMA_NUMBER_MINUS_ONE ((ecma_number_t) -1)
|
||||
|
||||
#if !JERRY_NUMBER_TYPE_FLOAT64
|
||||
/**
|
||||
* Number.MIN_VALUE (i.e., the smallest positive value of ecma-number)
|
||||
*
|
||||
* See also: ECMA_262 v5, 15.7.3.3
|
||||
*/
|
||||
#define ECMA_NUMBER_MIN_VALUE (FLT_MIN)
|
||||
/**
|
||||
* Number.MAX_VALUE (i.e., the maximum value of ecma-number)
|
||||
*
|
||||
* See also: ECMA_262 v5, 15.7.3.2
|
||||
*/
|
||||
#define ECMA_NUMBER_MAX_VALUE (FLT_MAX)
|
||||
/**
|
||||
* Number.EPSILON
|
||||
*
|
||||
* See also: ECMA_262 v6, 20.1.2.1
|
||||
*/
|
||||
#define ECMA_NUMBER_EPSILON ((ecma_number_t) 1.1920928955078125e-7)
|
||||
|
||||
/**
|
||||
* Number.MAX_SAFE_INTEGER
|
||||
*
|
||||
* See also: ECMA_262 v6, 20.1.2.6
|
||||
*/
|
||||
#define ECMA_NUMBER_MAX_SAFE_INTEGER ((ecma_number_t) 0xFFFFFF)
|
||||
|
||||
/**
|
||||
* Number.MIN_SAFE_INTEGER
|
||||
*
|
||||
* See also: ECMA_262 v6, 20.1.2.8
|
||||
*/
|
||||
#define ECMA_NUMBER_MIN_SAFE_INTEGER ((ecma_number_t) -0xFFFFFF)
|
||||
#elif JERRY_NUMBER_TYPE_FLOAT64
|
||||
/**
|
||||
* Number.MAX_VALUE (i.e., the maximum value of ecma-number)
|
||||
*
|
||||
* See also: ECMA_262 v5, 15.7.3.2
|
||||
*/
|
||||
#define ECMA_NUMBER_MAX_VALUE ((ecma_number_t) 1.7976931348623157e+308)
|
||||
|
||||
/**
|
||||
* Number.MIN_VALUE (i.e., the smallest positive value of ecma-number)
|
||||
*
|
||||
* See also: ECMA_262 v5, 15.7.3.3
|
||||
*/
|
||||
#define ECMA_NUMBER_MIN_VALUE ((ecma_number_t) 5e-324)
|
||||
|
||||
/**
|
||||
* Number.EPSILON
|
||||
*
|
||||
* See also: ECMA_262 v6, 20.1.2.1
|
||||
*/
|
||||
#define ECMA_NUMBER_EPSILON ((ecma_number_t) 2.2204460492503130808472633361816e-16)
|
||||
|
||||
/**
|
||||
* Number.MAX_SAFE_INTEGER
|
||||
*
|
||||
* See also: ECMA_262 v6, 20.1.2.6
|
||||
*/
|
||||
#define ECMA_NUMBER_MAX_SAFE_INTEGER ((ecma_number_t) 0x1FFFFFFFFFFFFF)
|
||||
|
||||
/**
|
||||
* Number.MIN_SAFE_INTEGER
|
||||
*
|
||||
* See also: ECMA_262 v6, 20.1.2.8
|
||||
*/
|
||||
#define ECMA_NUMBER_MIN_SAFE_INTEGER ((ecma_number_t) -0x1FFFFFFFFFFFFF)
|
||||
#endif /* !JERRY_NUMBER_TYPE_FLOAT64 */
|
||||
|
||||
/**
|
||||
* Euler number
|
||||
*/
|
||||
#define ECMA_NUMBER_E ((ecma_number_t) 2.7182818284590452354)
|
||||
|
||||
/**
|
||||
* Natural logarithm of 10
|
||||
*/
|
||||
#define ECMA_NUMBER_LN10 ((ecma_number_t) 2.302585092994046)
|
||||
|
||||
/**
|
||||
* Natural logarithm of 2
|
||||
*/
|
||||
#define ECMA_NUMBER_LN2 ((ecma_number_t) 0.6931471805599453)
|
||||
|
||||
/**
|
||||
* Logarithm base 2 of the Euler number
|
||||
*/
|
||||
#define ECMA_NUMBER_LOG2E ((ecma_number_t) 1.4426950408889634)
|
||||
|
||||
/**
|
||||
* Logarithm base 10 of the Euler number
|
||||
*/
|
||||
#define ECMA_NUMBER_LOG10E ((ecma_number_t) 0.4342944819032518)
|
||||
|
||||
/**
|
||||
* Pi number
|
||||
*/
|
||||
#define ECMA_NUMBER_PI ((ecma_number_t) 3.1415926535897932)
|
||||
|
||||
/**
|
||||
* Square root of 0.5
|
||||
*/
|
||||
#define ECMA_NUMBER_SQRT_1_2 ((ecma_number_t) 0.7071067811865476)
|
||||
|
||||
/**
|
||||
* Square root of 2
|
||||
*/
|
||||
#define ECMA_NUMBER_SQRT2 ((ecma_number_t) 1.4142135623730951)
|
||||
#define ECMA_NUMBER_MINUS_ONE ((ecma_number_t) -1.0f)
|
||||
|
||||
/**
|
||||
* Maximum number of characters in string representation of ecma-number
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include <math.h>
|
||||
|
||||
#include "ecma-globals.h"
|
||||
#include "ecma-helpers-number.h"
|
||||
#include "ecma-helpers.h"
|
||||
|
||||
#include "jrt-libc-includes.h"
|
||||
@@ -41,8 +42,8 @@
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint64_t lo; /**< low 64 bits */
|
||||
uint64_t hi; /**< high 64 bits */
|
||||
uint64_t lo; /**< low 64 bits */
|
||||
} ecma_uint128_t;
|
||||
|
||||
/**
|
||||
@@ -60,58 +61,58 @@ ecma_round_high_to_uint64 (ecma_uint128_t *num_p)
|
||||
{
|
||||
return (num_p->hi + 1);
|
||||
}
|
||||
|
||||
return num_p->hi;
|
||||
} /* ecma_round_high_to_uint64 */
|
||||
|
||||
/**
|
||||
* Check if 128-bit integer is zero
|
||||
* Left shift 128-bit integer by max 63 bits.
|
||||
*/
|
||||
#define ECMA_UINT128_IS_ZERO(name) (name.hi == 0 && name.lo == 0)
|
||||
static void JERRY_ATTR_ALWAYS_INLINE
|
||||
ecma_uint128_shift_left (ecma_uint128_t *num_p, int32_t shift)
|
||||
{
|
||||
num_p->hi = (num_p->hi << shift) | (num_p->lo >> (64 - shift));
|
||||
num_p->lo <<= shift;
|
||||
} /* ecma_uint128_shift_left */
|
||||
|
||||
/**
|
||||
* Left shift 128-bit integer by max 63 bits
|
||||
* Right shift 128-bit integer by max 63 bits.
|
||||
*/
|
||||
#define ECMA_UINT128_LEFT_SHIFT_MAX63(name, shift) \
|
||||
{ \
|
||||
name.hi = (name.hi << (shift)) | (name.lo >> (64 - (shift))); \
|
||||
name.lo <<= (shift); \
|
||||
}
|
||||
static void JERRY_ATTR_ALWAYS_INLINE
|
||||
ecma_uint128_shift_right (ecma_uint128_t *num_p, int32_t shift)
|
||||
{
|
||||
num_p->lo = (num_p->lo >> shift) | (num_p->hi << (64 - shift));
|
||||
num_p->hi >>= shift;
|
||||
} /* ecma_uint128_shift_right */
|
||||
|
||||
/**
|
||||
* Right shift 128-bit integer by max 63 bits
|
||||
* Add two 128-bit integer values and assign the result to the left one.
|
||||
*/
|
||||
#define ECMA_UINT128_RIGHT_SHIFT_MAX63(name, shift) \
|
||||
{ \
|
||||
name.lo = (name.lo >> (shift)) | (name.hi << (64 - (shift))); \
|
||||
name.hi >>= (shift); \
|
||||
}
|
||||
static void
|
||||
ecma_uint128_add (ecma_uint128_t *left_p, ecma_uint128_t *right_p)
|
||||
{
|
||||
left_p->hi += right_p->hi;
|
||||
left_p->lo += right_p->lo;
|
||||
|
||||
/**
|
||||
* Add 128-bit integer
|
||||
*/
|
||||
#define ECMA_UINT128_ADD(name_add_to, name_to_add) \
|
||||
{ \
|
||||
name_add_to.hi += name_to_add.hi; \
|
||||
name_add_to.lo += name_to_add.lo; \
|
||||
if (name_add_to.lo < name_to_add.lo) \
|
||||
{ \
|
||||
name_add_to.hi++; \
|
||||
} \
|
||||
if (left_p->lo < right_p->lo)
|
||||
{
|
||||
left_p->hi++;
|
||||
}
|
||||
} /* ecma_uint128_add */
|
||||
|
||||
/**
|
||||
* Multiply 128-bit integer by 10
|
||||
*/
|
||||
#define ECMA_UINT128_MUL10(name) \
|
||||
{ \
|
||||
ECMA_UINT128_LEFT_SHIFT_MAX63 (name, 1u); \
|
||||
\
|
||||
ecma_uint128_t name##_tmp = name; \
|
||||
\
|
||||
ECMA_UINT128_LEFT_SHIFT_MAX63 (name##_tmp, 2u); \
|
||||
\
|
||||
ECMA_UINT128_ADD (name, name##_tmp); \
|
||||
}
|
||||
static void
|
||||
ecma_uint128_mul10 (ecma_uint128_t *num_p)
|
||||
{
|
||||
ecma_uint128_shift_left (num_p, 1u);
|
||||
|
||||
ecma_uint128_t tmp = { .hi = num_p->hi, .lo = num_p->lo };
|
||||
ecma_uint128_shift_left (&tmp, 2u);
|
||||
|
||||
ecma_uint128_add (num_p, &tmp);
|
||||
} /* ecma_uint128_mul10 */
|
||||
|
||||
/**
|
||||
* Divide 128-bit integer by 10
|
||||
@@ -128,121 +129,122 @@ ecma_round_high_to_uint64 (ecma_uint128_t *num_p)
|
||||
*
|
||||
* Q = Q3 *2^96 + Q2 *2^64 + Q1 *2^32 + Q0 *2^0 // 128-bit quotient
|
||||
*/
|
||||
#define ECMA_UINT128_DIV10(name) \
|
||||
{ \
|
||||
/* estimation of reciprocal of 10, 128 bits right of the binary point (T1 == T2) */ \
|
||||
const uint64_t tenth_l = 0x9999999aul; \
|
||||
const uint64_t tenth_m = 0x99999999ul; \
|
||||
const uint64_t tenth_h = 0x19999999ul; \
|
||||
\
|
||||
uint64_t l0 = ((uint32_t) name.lo) * tenth_l; \
|
||||
uint64_t l1 = (name.lo >> 32u) * tenth_l; \
|
||||
uint64_t l2 = ((uint32_t) name.hi) * tenth_l; \
|
||||
uint64_t l3 = (name.hi >> 32u) * tenth_l; \
|
||||
uint64_t m0 = ((uint32_t) name.lo) * tenth_m; \
|
||||
uint64_t m1 = (name.lo >> 32u) * tenth_m; \
|
||||
uint64_t m2 = ((uint32_t) name.hi) * tenth_m; \
|
||||
uint64_t m3 = (name.hi >> 32u) * tenth_m; \
|
||||
uint64_t h0 = ((uint32_t) name.lo) * tenth_h; \
|
||||
uint64_t h1 = (name.lo >> 32u) * tenth_h; \
|
||||
uint64_t h2 = ((uint32_t) name.hi) * tenth_h; \
|
||||
uint64_t h3 = (name.hi >> 32u) * tenth_h; \
|
||||
\
|
||||
uint64_t q0 = l0 >> 32u; \
|
||||
q0 += (uint32_t) l1; \
|
||||
q0 += (uint32_t) m0; \
|
||||
\
|
||||
q0 >>= 32u; \
|
||||
q0 += l1 >> 32u; \
|
||||
q0 += m0 >> 32u; \
|
||||
q0 += (uint32_t) l2; \
|
||||
q0 += (uint32_t) m1; \
|
||||
q0 += (uint32_t) m0; \
|
||||
\
|
||||
q0 >>= 32u; \
|
||||
q0 += l2 >> 32u; \
|
||||
q0 += m1 >> 32u; \
|
||||
q0 += m0 >> 32u; \
|
||||
q0 += (uint32_t) l3; \
|
||||
q0 += (uint32_t) m2; \
|
||||
q0 += (uint32_t) m1; \
|
||||
q0 += (uint32_t) h0; \
|
||||
\
|
||||
q0 >>= 32u; \
|
||||
q0 += l3 >> 32u; \
|
||||
q0 += m2 >> 32u; \
|
||||
q0 += m1 >> 32u; \
|
||||
q0 += h0 >> 32u; \
|
||||
q0 += (uint32_t) m3; \
|
||||
q0 += (uint32_t) m2; \
|
||||
q0 += (uint32_t) h1; \
|
||||
\
|
||||
uint64_t q1 = q0 >> 32u; \
|
||||
q1 += m3 >> 32u; \
|
||||
q1 += m2 >> 32u; \
|
||||
q1 += h1 >> 32u; \
|
||||
q1 += (uint32_t) m3; \
|
||||
q1 += (uint32_t) h2; \
|
||||
\
|
||||
uint64_t q32 = q1 >> 32u; \
|
||||
q32 += m3 >> 32u; \
|
||||
q32 += h2 >> 32u; \
|
||||
q32 += h3; \
|
||||
\
|
||||
name.lo = (q1 << 32u) | ((uint32_t) q0); \
|
||||
name.hi = q32; \
|
||||
}
|
||||
static void
|
||||
ecma_uint128_div10 (ecma_uint128_t *num_p)
|
||||
{
|
||||
/* estimation of reciprocal of 10, 128 bits right of the binary point (T1 == T2) */
|
||||
const uint64_t tenth_l = 0x9999999aul;
|
||||
const uint64_t tenth_m = 0x99999999ul;
|
||||
const uint64_t tenth_h = 0x19999999ul;
|
||||
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
const uint64_t l0 = ((uint32_t) num_p->lo) * tenth_l;
|
||||
const uint64_t l1 = (num_p->lo >> 32u) * tenth_l;
|
||||
const uint64_t l2 = ((uint32_t) num_p->hi) * tenth_l;
|
||||
const uint64_t l3 = (num_p->hi >> 32u) * tenth_l;
|
||||
const uint64_t m0 = ((uint32_t) num_p->lo) * tenth_m;
|
||||
const uint64_t m1 = (num_p->lo >> 32u) * tenth_m;
|
||||
const uint64_t m2 = ((uint32_t) num_p->hi) * tenth_m;
|
||||
const uint64_t m3 = (num_p->hi >> 32u) * tenth_m;
|
||||
const uint64_t h0 = ((uint32_t) num_p->lo) * tenth_h;
|
||||
const uint64_t h1 = (num_p->lo >> 32u) * tenth_h;
|
||||
const uint64_t h2 = ((uint32_t) num_p->hi) * tenth_h;
|
||||
const uint64_t h3 = (num_p->hi >> 32u) * tenth_h;
|
||||
|
||||
/**
|
||||
* Count leading zeros in the topmost 64 bits of a 128-bit integer.
|
||||
*/
|
||||
#define ECMA_UINT128_CLZ_MAX63(name) __builtin_clzll (name.hi)
|
||||
uint64_t q0 = l0 >> 32u;
|
||||
q0 += (uint32_t) l1;
|
||||
q0 += (uint32_t) m0;
|
||||
|
||||
/**
|
||||
* Count leading zeros in the topmost 4 bits of a 128-bit integer.
|
||||
*/
|
||||
#define ECMA_UINT128_CLZ_MAX4(name) __builtin_clzll (name.hi)
|
||||
q0 >>= 32u;
|
||||
q0 += l1 >> 32u;
|
||||
q0 += m0 >> 32u;
|
||||
q0 += (uint32_t) l2;
|
||||
q0 += (uint32_t) m1;
|
||||
q0 += (uint32_t) m0;
|
||||
|
||||
#else /* !__GNUC__ && !__clang__ */
|
||||
q0 >>= 32u;
|
||||
q0 += l2 >> 32u;
|
||||
q0 += m1 >> 32u;
|
||||
q0 += m0 >> 32u;
|
||||
q0 += (uint32_t) l3;
|
||||
q0 += (uint32_t) m2;
|
||||
q0 += (uint32_t) m1;
|
||||
q0 += (uint32_t) h0;
|
||||
|
||||
q0 >>= 32u;
|
||||
q0 += l3 >> 32u;
|
||||
q0 += m2 >> 32u;
|
||||
q0 += m1 >> 32u;
|
||||
q0 += h0 >> 32u;
|
||||
q0 += (uint32_t) m3;
|
||||
q0 += (uint32_t) m2;
|
||||
q0 += (uint32_t) h1;
|
||||
|
||||
uint64_t q1 = q0 >> 32u;
|
||||
q1 += m3 >> 32u;
|
||||
q1 += m2 >> 32u;
|
||||
q1 += h1 >> 32u;
|
||||
q1 += (uint32_t) m3;
|
||||
q1 += (uint32_t) h2;
|
||||
|
||||
uint64_t q32 = q1 >> 32u;
|
||||
q32 += m3 >> 32u;
|
||||
q32 += h2 >> 32u;
|
||||
q32 += h3;
|
||||
|
||||
num_p->lo = (q1 << 32u) | ((uint32_t) q0);
|
||||
num_p->hi = q32;
|
||||
} /* ecma_uint128_div10 */
|
||||
|
||||
/**
|
||||
* Count leading zeros in a 64-bit integer. The behaviour is undefined for 0.
|
||||
*
|
||||
* @return number of leading zeros.
|
||||
*/
|
||||
static inline int JERRY_ATTR_ALWAYS_INLINE
|
||||
inline static int JERRY_ATTR_CONST
|
||||
ecma_uint64_clz (uint64_t n) /**< integer to count leading zeros in */
|
||||
{
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
return __builtin_clzll (n);
|
||||
#else /* !defined (__GNUC__) && !defined (__clang__) */
|
||||
JERRY_ASSERT (n != 0);
|
||||
|
||||
int cnt = 0;
|
||||
uint64_t one = 0x8000000000000000ull;
|
||||
|
||||
while ((n & one) == 0)
|
||||
{
|
||||
cnt++;
|
||||
one >>= 1;
|
||||
}
|
||||
|
||||
return cnt;
|
||||
#endif /* !defined (__GNUC__) && !defined (__clang__) */
|
||||
} /* ecma_uint64_clz */
|
||||
|
||||
/**
|
||||
* Number of leading zeros in 4-bit integers.
|
||||
* Count leading zeros in the top 4 bits of a 64-bit integer.
|
||||
*
|
||||
* @return number of leading zeros in top 4 bits.
|
||||
*/
|
||||
static const uint8_t ecma_uint4_clz[] = { 4, 3, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
inline static int JERRY_ATTR_ALWAYS_INLINE JERRY_ATTR_CONST
|
||||
ecma_uint64_clz_top4 (uint64_t n) /**< integer to count leading zeros in */
|
||||
{
|
||||
static const uint8_t ecma_uint4_clz[] = { 4, 3, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
return ecma_uint4_clz[n >> 60];
|
||||
} /* ecma_uint64_clz */
|
||||
|
||||
/**
|
||||
* Count leading zeros in the topmost 64 bits of a 128-bit integer.
|
||||
* Shift required to clear 4 bits of a 64-bit integer.
|
||||
*
|
||||
* @return 0-4
|
||||
*/
|
||||
#define ECMA_UINT128_CLZ_MAX63(name) ecma_uint64_clz (name.hi)
|
||||
inline static int JERRY_ATTR_ALWAYS_INLINE JERRY_ATTR_CONST
|
||||
ecma_uint64_normalize_shift (uint64_t n) /**< integer to count leading zeros in */
|
||||
{
|
||||
static const uint8_t ecma_uint4_shift[] = { 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4 };
|
||||
|
||||
/**
|
||||
* Count leading zeros in the topmost 4 bits of a 128-bit integer.
|
||||
*/
|
||||
#define ECMA_UINT128_CLZ_MAX4(name) ecma_uint4_clz[name.hi >> 60]
|
||||
|
||||
#endif /* __GNUC__ || __clang__ */
|
||||
return ecma_uint4_shift[n >> 60];
|
||||
} /* ecma_uint64_normalize_shift */
|
||||
|
||||
/**
|
||||
* @}
|
||||
@@ -285,72 +287,58 @@ static const uint8_t ecma_uint4_clz[] = { 4, 3, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0,
|
||||
* @return NaN - if the conversion fails
|
||||
* converted number - otherwise
|
||||
*/
|
||||
static ecma_number_t
|
||||
ecma_number_t
|
||||
ecma_utf8_string_to_number_by_radix (const lit_utf8_byte_t *str_p, /**< utf-8 string */
|
||||
const lit_utf8_byte_t *end_p, /**< end of utf-8 string */
|
||||
uint32_t radix) /**< radix */
|
||||
const lit_utf8_size_t string_size, /**< end of utf-8 string */
|
||||
uint32_t radix, /**< radix */
|
||||
uint32_t options) /**< option flags */
|
||||
{
|
||||
#if JERRY_ESNEXT
|
||||
bool allow_underscore = (radix & ECMA_CONVERSION_ALLOW_UNDERSCORE);
|
||||
radix &= (uint32_t) ~ECMA_CONVERSION_ALLOW_UNDERSCORE;
|
||||
#endif /* JERRY_ESNEXT */
|
||||
bool allow_underscore = (options & ECMA_CONVERSION_ALLOW_UNDERSCORE);
|
||||
#else /* !JERRY_ESNEXT */
|
||||
JERRY_UNUSED (options);
|
||||
#endif /* !JERRY_ESNEXT */
|
||||
|
||||
JERRY_ASSERT (radix == 2 || radix == 8 || radix == 16);
|
||||
JERRY_ASSERT (*str_p == LIT_CHAR_0);
|
||||
|
||||
const lit_utf8_byte_t *end_p = str_p + string_size;
|
||||
|
||||
/* Skip leading zero */
|
||||
str_p++;
|
||||
|
||||
if (radix != 8 || LEXER_TO_ASCII_LOWERCASE (*str_p) == LIT_CHAR_LOWERCASE_O)
|
||||
{
|
||||
/* Skip radix specifier */
|
||||
str_p++;
|
||||
}
|
||||
|
||||
ecma_number_t num = ECMA_NUMBER_ZERO;
|
||||
|
||||
#if JERRY_ESNEXT
|
||||
if (radix <= 8)
|
||||
while (str_p < end_p)
|
||||
{
|
||||
lit_code_point_t upper_limit = LIT_CHAR_0 + radix;
|
||||
lit_utf8_byte_t digit = *str_p++;
|
||||
|
||||
for (const lit_utf8_byte_t *iter_p = str_p; iter_p <= end_p; iter_p++)
|
||||
{
|
||||
int32_t digit_value;
|
||||
|
||||
if (*iter_p >= LIT_CHAR_0 && *iter_p < upper_limit)
|
||||
{
|
||||
digit_value = (*iter_p - LIT_CHAR_0);
|
||||
}
|
||||
else
|
||||
{
|
||||
return ecma_number_make_nan ();
|
||||
}
|
||||
|
||||
num = num * radix + (ecma_number_t) digit_value;
|
||||
}
|
||||
|
||||
return num;
|
||||
}
|
||||
#endif /* JERRY_ESNEXT */
|
||||
|
||||
for (const lit_utf8_byte_t *iter_p = str_p; iter_p <= end_p; iter_p++)
|
||||
{
|
||||
int32_t digit_value;
|
||||
|
||||
if (*iter_p >= LIT_CHAR_0 && *iter_p <= LIT_CHAR_9)
|
||||
{
|
||||
digit_value = (*iter_p - LIT_CHAR_0);
|
||||
}
|
||||
else if (*iter_p >= LIT_CHAR_LOWERCASE_A && *iter_p <= LIT_CHAR_LOWERCASE_F)
|
||||
{
|
||||
digit_value = 10 + (*iter_p - LIT_CHAR_LOWERCASE_A);
|
||||
}
|
||||
else if (*iter_p >= LIT_CHAR_UPPERCASE_A && *iter_p <= LIT_CHAR_UPPERCASE_F)
|
||||
{
|
||||
digit_value = 10 + (*iter_p - LIT_CHAR_UPPERCASE_A);
|
||||
}
|
||||
#if JERRY_ESNEXT
|
||||
else if (*iter_p == LIT_CHAR_UNDERSCORE && allow_underscore)
|
||||
if (digit == LIT_CHAR_UNDERSCORE && allow_underscore)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
#endif /* JERRY_ESNEXT */
|
||||
else
|
||||
|
||||
if (!lit_char_is_hex_digit (digit))
|
||||
{
|
||||
return ecma_number_make_nan ();
|
||||
}
|
||||
|
||||
num = num * (ecma_number_t) radix + (ecma_number_t) digit_value;
|
||||
uint32_t value = lit_char_hex_to_int (digit);
|
||||
|
||||
if (value >= radix)
|
||||
{
|
||||
return ecma_number_make_nan ();
|
||||
}
|
||||
|
||||
num = num * radix + value;
|
||||
}
|
||||
|
||||
return num;
|
||||
@@ -370,45 +358,15 @@ ecma_utf8_string_to_number (const lit_utf8_byte_t *str_p, /**< utf-8 string */
|
||||
lit_utf8_size_t str_size, /**< string size */
|
||||
uint32_t options) /**< allowing underscore option bit */
|
||||
{
|
||||
/* TODO: Check license issues */
|
||||
ecma_string_trim_helper (&str_p, &str_size);
|
||||
const lit_utf8_byte_t *end_p = str_p + str_size;
|
||||
|
||||
if (str_size == 0)
|
||||
{
|
||||
return ECMA_NUMBER_ZERO;
|
||||
}
|
||||
|
||||
ecma_string_trim_helper (&str_p, &str_size);
|
||||
const lit_utf8_byte_t *end_p = str_p + (str_size - 1);
|
||||
|
||||
if (str_size < 1)
|
||||
{
|
||||
return ECMA_NUMBER_ZERO;
|
||||
}
|
||||
|
||||
if (end_p >= str_p + 2 && str_p[0] == LIT_CHAR_0)
|
||||
{
|
||||
switch (LEXER_TO_ASCII_LOWERCASE (str_p[1]))
|
||||
{
|
||||
case LIT_CHAR_LOWERCASE_X:
|
||||
{
|
||||
return ecma_utf8_string_to_number_by_radix (str_p + 2, end_p, 16 | options);
|
||||
}
|
||||
case LIT_CHAR_LOWERCASE_O:
|
||||
{
|
||||
return ecma_utf8_string_to_number_by_radix (str_p + 2, end_p, 8 | options);
|
||||
}
|
||||
case LIT_CHAR_LOWERCASE_B:
|
||||
{
|
||||
return ecma_utf8_string_to_number_by_radix (str_p + 2, end_p, 2 | options);
|
||||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool sign = false; /* positive */
|
||||
bool sign = false;
|
||||
|
||||
if (*str_p == LIT_CHAR_PLUS)
|
||||
{
|
||||
@@ -416,122 +374,117 @@ ecma_utf8_string_to_number (const lit_utf8_byte_t *str_p, /**< utf-8 string */
|
||||
}
|
||||
else if (*str_p == LIT_CHAR_MINUS)
|
||||
{
|
||||
sign = true; /* negative */
|
||||
|
||||
sign = true;
|
||||
str_p++;
|
||||
}
|
||||
|
||||
if (str_p > end_p)
|
||||
if (str_p + 2 < end_p && str_p[0] == LIT_CHAR_0)
|
||||
{
|
||||
return ecma_number_make_nan ();
|
||||
uint8_t radix = lit_char_to_radix (str_p[1]);
|
||||
|
||||
if (radix != 10)
|
||||
{
|
||||
return ecma_utf8_string_to_number_by_radix (str_p, str_size, radix, options);
|
||||
}
|
||||
}
|
||||
|
||||
/* Checking if significant part of parse string is equal to "Infinity" */
|
||||
const lit_utf8_byte_t *infinity_zt_str_p = lit_get_magic_string_utf8 (LIT_MAGIC_STRING_INFINITY_UL);
|
||||
/* Check if string is equal to "Infinity". */
|
||||
const lit_utf8_byte_t *infinity_str_p = lit_get_magic_string_utf8 (LIT_MAGIC_STRING_INFINITY_UL);
|
||||
const lit_utf8_size_t infinity_length = lit_get_magic_string_size (LIT_MAGIC_STRING_INFINITY_UL);
|
||||
|
||||
JERRY_ASSERT (strlen ((const char *) infinity_zt_str_p) == 8);
|
||||
|
||||
if ((end_p - str_p) == (8 - 1) && memcmp (infinity_zt_str_p, str_p, 8) == 0)
|
||||
if ((lit_utf8_size_t) (end_p - str_p) == infinity_length && memcmp (infinity_str_p, str_p, infinity_length) == 0)
|
||||
{
|
||||
return ecma_number_make_infinity (sign);
|
||||
}
|
||||
|
||||
uint64_t fraction_uint64 = 0;
|
||||
uint32_t digits = 0;
|
||||
int32_t e = 0;
|
||||
bool digit_seen = false;
|
||||
uint64_t significand = 0;
|
||||
uint32_t digit_count = 0;
|
||||
int32_t decimal_exponent = 0;
|
||||
bool has_significand = false;
|
||||
|
||||
/* Parsing digits before dot (or before end of digits part if there is no dot in number) */
|
||||
while (str_p <= end_p)
|
||||
/* Parsing integer part */
|
||||
while (str_p < end_p)
|
||||
{
|
||||
int32_t digit_value;
|
||||
|
||||
if (*str_p >= LIT_CHAR_0 && *str_p <= LIT_CHAR_9)
|
||||
{
|
||||
digit_seen = true;
|
||||
digit_value = (*str_p - LIT_CHAR_0);
|
||||
}
|
||||
#if JERRY_ESNEXT
|
||||
else if (*str_p == LIT_CHAR_UNDERSCORE && (options & ECMA_CONVERSION_ALLOW_UNDERSCORE))
|
||||
if (*str_p == LIT_CHAR_UNDERSCORE && (options & ECMA_CONVERSION_ALLOW_UNDERSCORE))
|
||||
{
|
||||
str_p++;
|
||||
continue;
|
||||
}
|
||||
#endif /* JERRY_ESNEXT */
|
||||
else
|
||||
|
||||
if (!lit_char_is_decimal_digit (*str_p))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (digits != 0 || digit_value != 0)
|
||||
has_significand = true;
|
||||
uint32_t digit_value = (uint32_t) (*str_p++ - LIT_CHAR_0);
|
||||
|
||||
if (digit_count == 0 && digit_value == 0)
|
||||
{
|
||||
if (digits < ECMA_NUMBER_MAX_DIGITS)
|
||||
{
|
||||
fraction_uint64 = fraction_uint64 * 10 + (uint32_t) digit_value;
|
||||
digits++;
|
||||
}
|
||||
else
|
||||
{
|
||||
e++;
|
||||
}
|
||||
/* Leading zeros are omitted. */
|
||||
continue;
|
||||
}
|
||||
|
||||
str_p++;
|
||||
if (digit_count >= ECMA_NUMBER_MAX_DIGITS)
|
||||
{
|
||||
decimal_exponent++;
|
||||
continue;
|
||||
}
|
||||
|
||||
significand = significand * 10 + digit_value;
|
||||
digit_count++;
|
||||
}
|
||||
|
||||
if (str_p <= end_p && *str_p == LIT_CHAR_DOT)
|
||||
/* Parse fraction part */
|
||||
if (str_p < end_p && *str_p == LIT_CHAR_DOT)
|
||||
{
|
||||
str_p++;
|
||||
|
||||
if (!digit_seen && str_p > end_p)
|
||||
while (str_p < end_p)
|
||||
{
|
||||
return ecma_number_make_nan ();
|
||||
}
|
||||
|
||||
/* Parsing number's part that is placed after dot */
|
||||
while (str_p <= end_p)
|
||||
{
|
||||
int32_t digit_value;
|
||||
|
||||
if (*str_p >= LIT_CHAR_0 && *str_p <= LIT_CHAR_9)
|
||||
{
|
||||
digit_seen = true;
|
||||
digit_value = (*str_p - LIT_CHAR_0);
|
||||
}
|
||||
else if (*str_p == LIT_CHAR_UNDERSCORE && (options & ECMA_CONVERSION_ALLOW_UNDERSCORE))
|
||||
#if JERRY_ESNEXT
|
||||
if (*str_p == LIT_CHAR_UNDERSCORE && (options & ECMA_CONVERSION_ALLOW_UNDERSCORE))
|
||||
{
|
||||
str_p++;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
#endif /* JERRY_ESNEXT */
|
||||
|
||||
if (!lit_char_is_decimal_digit (*str_p))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (digits < ECMA_NUMBER_MAX_DIGITS)
|
||||
{
|
||||
if (digits != 0 || digit_value != 0)
|
||||
{
|
||||
fraction_uint64 = fraction_uint64 * 10 + (uint32_t) digit_value;
|
||||
digits++;
|
||||
}
|
||||
has_significand = true;
|
||||
uint32_t digit_value = (uint32_t) (*str_p++ - LIT_CHAR_0);
|
||||
|
||||
e--;
|
||||
if (digit_count == 0 && digit_value == 0)
|
||||
{
|
||||
/* Leading zeros are omitted. */
|
||||
decimal_exponent--;
|
||||
continue;
|
||||
}
|
||||
|
||||
str_p++;
|
||||
if (digit_count < ECMA_NUMBER_MAX_DIGITS)
|
||||
{
|
||||
significand = significand * 10 + digit_value;
|
||||
digit_count++;
|
||||
decimal_exponent--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Parsing exponent literal */
|
||||
int32_t e_in_lit = 0;
|
||||
bool e_in_lit_sign = false;
|
||||
|
||||
if (str_p <= end_p && (*str_p == LIT_CHAR_LOWERCASE_E || *str_p == LIT_CHAR_UPPERCASE_E))
|
||||
/* Parsing exponent */
|
||||
if (str_p < end_p && LEXER_TO_ASCII_LOWERCASE (*str_p) == LIT_CHAR_LOWERCASE_E)
|
||||
{
|
||||
str_p++;
|
||||
|
||||
if (!digit_seen || str_p > end_p)
|
||||
int32_t exponent = 0;
|
||||
int32_t exponent_sign = 1;
|
||||
|
||||
if (str_p >= end_p)
|
||||
{
|
||||
return ecma_number_make_nan ();
|
||||
}
|
||||
@@ -542,81 +495,53 @@ ecma_utf8_string_to_number (const lit_utf8_byte_t *str_p, /**< utf-8 string */
|
||||
}
|
||||
else if (*str_p == LIT_CHAR_MINUS)
|
||||
{
|
||||
e_in_lit_sign = true;
|
||||
exponent_sign = -1;
|
||||
str_p++;
|
||||
}
|
||||
|
||||
if (str_p > end_p)
|
||||
if (str_p >= end_p || !lit_char_is_decimal_digit (*str_p))
|
||||
{
|
||||
return ecma_number_make_nan ();
|
||||
}
|
||||
|
||||
while (str_p <= end_p)
|
||||
while (str_p < end_p)
|
||||
{
|
||||
int32_t digit_value;
|
||||
|
||||
if (*str_p >= LIT_CHAR_0 && *str_p <= LIT_CHAR_9)
|
||||
{
|
||||
digit_value = (*str_p - LIT_CHAR_0);
|
||||
}
|
||||
#if JERRY_ESNEXT
|
||||
else if (*str_p == LIT_CHAR_UNDERSCORE && (options & ECMA_CONVERSION_ALLOW_UNDERSCORE))
|
||||
if (*str_p == LIT_CHAR_UNDERSCORE && (options & ECMA_CONVERSION_ALLOW_UNDERSCORE))
|
||||
{
|
||||
str_p++;
|
||||
continue;
|
||||
}
|
||||
#endif /* JERRY_ESNEXT */
|
||||
else
|
||||
|
||||
if (!lit_char_is_decimal_digit (*str_p))
|
||||
{
|
||||
return ecma_number_make_nan ();
|
||||
break;
|
||||
}
|
||||
|
||||
e_in_lit = e_in_lit * 10 + digit_value;
|
||||
int32_t e_check = e + (int32_t) digits - 1 + (e_in_lit_sign ? -e_in_lit : e_in_lit);
|
||||
int32_t digit_value = (*str_p++ - LIT_CHAR_0);
|
||||
exponent = exponent * 10 + digit_value;
|
||||
|
||||
if (e_check > NUMBER_MAX_DECIMAL_EXPONENT)
|
||||
if (exponent_sign * exponent > NUMBER_MAX_DECIMAL_EXPONENT)
|
||||
{
|
||||
return ecma_number_make_infinity (sign);
|
||||
}
|
||||
else if (e_check < NUMBER_MIN_DECIMAL_EXPONENT)
|
||||
|
||||
if (exponent_sign * exponent < NUMBER_MIN_DECIMAL_EXPONENT)
|
||||
{
|
||||
return sign ? -ECMA_NUMBER_ZERO : ECMA_NUMBER_ZERO;
|
||||
}
|
||||
|
||||
str_p++;
|
||||
}
|
||||
|
||||
decimal_exponent += exponent_sign * exponent;
|
||||
}
|
||||
|
||||
/* Adding value of exponent literal to exponent value */
|
||||
if (e_in_lit_sign)
|
||||
{
|
||||
e -= e_in_lit;
|
||||
}
|
||||
else
|
||||
{
|
||||
e += e_in_lit;
|
||||
}
|
||||
|
||||
bool e_sign;
|
||||
|
||||
if (e < 0)
|
||||
{
|
||||
e_sign = true;
|
||||
e = -e;
|
||||
}
|
||||
else
|
||||
{
|
||||
e_sign = false;
|
||||
}
|
||||
|
||||
if (str_p <= end_p)
|
||||
if (!has_significand || str_p < end_p)
|
||||
{
|
||||
return ecma_number_make_nan ();
|
||||
}
|
||||
|
||||
JERRY_ASSERT (str_p == end_p + 1);
|
||||
|
||||
if (fraction_uint64 == 0)
|
||||
if (significand == 0)
|
||||
{
|
||||
return sign ? -ECMA_NUMBER_ZERO : ECMA_NUMBER_ZERO;
|
||||
}
|
||||
@@ -627,85 +552,93 @@ ecma_utf8_string_to_number (const lit_utf8_byte_t *str_p, /**< utf-8 string */
|
||||
*
|
||||
* Normalized: |4 bits zero|124-bit mantissa with highest bit set to 1|
|
||||
*/
|
||||
ecma_uint128_t fraction_uint128 = { 0, fraction_uint64 };
|
||||
ecma_uint128_t significand_uint128 = { .hi = significand, .lo = 0 };
|
||||
|
||||
/* Normalizing mantissa */
|
||||
int shift = 4 - ECMA_UINT128_CLZ_MAX63 (fraction_uint128);
|
||||
int shift = 4 - ecma_uint64_clz (significand_uint128.hi);
|
||||
|
||||
if (shift < 0)
|
||||
{
|
||||
ECMA_UINT128_LEFT_SHIFT_MAX63 (fraction_uint128, -shift);
|
||||
ecma_uint128_shift_left (&significand_uint128, -shift);
|
||||
}
|
||||
else
|
||||
{
|
||||
ECMA_UINT128_RIGHT_SHIFT_MAX63 (fraction_uint128, shift);
|
||||
ecma_uint128_shift_right (&significand_uint128, shift);
|
||||
}
|
||||
int32_t binary_exponent = 1 + shift;
|
||||
|
||||
if (!e_sign)
|
||||
int32_t binary_exponent = ECMA_NUMBER_FRACTION_WIDTH + shift;
|
||||
|
||||
while (decimal_exponent > 0)
|
||||
{
|
||||
/* positive or zero decimal exponent */
|
||||
JERRY_ASSERT (e >= 0);
|
||||
JERRY_ASSERT (ecma_uint64_clz (significand_uint128.hi) == 4);
|
||||
|
||||
while (e > 0)
|
||||
{
|
||||
JERRY_ASSERT (ECMA_UINT128_CLZ_MAX63 (fraction_uint128) == 4);
|
||||
ecma_uint128_mul10 (&significand_uint128);
|
||||
decimal_exponent--;
|
||||
|
||||
ECMA_UINT128_MUL10 (fraction_uint128);
|
||||
/* Re-normalizing mantissa */
|
||||
shift = ecma_uint64_normalize_shift (significand_uint128.hi);
|
||||
JERRY_ASSERT (shift >= 0 && shift <= 4);
|
||||
|
||||
e--;
|
||||
|
||||
/* Normalizing mantissa */
|
||||
shift = 4 - ECMA_UINT128_CLZ_MAX4 (fraction_uint128);
|
||||
JERRY_ASSERT (shift >= 0);
|
||||
ECMA_UINT128_RIGHT_SHIFT_MAX63 (fraction_uint128, shift);
|
||||
binary_exponent += shift;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* negative decimal exponent */
|
||||
JERRY_ASSERT (e != 0);
|
||||
|
||||
while (e > 0)
|
||||
{
|
||||
/* Denormalizing mantissa, moving highest 1 to bit 127 */
|
||||
shift = ECMA_UINT128_CLZ_MAX4 (fraction_uint128);
|
||||
JERRY_ASSERT (shift <= 4);
|
||||
ECMA_UINT128_LEFT_SHIFT_MAX63 (fraction_uint128, shift);
|
||||
binary_exponent -= shift;
|
||||
|
||||
JERRY_ASSERT (!ECMA_UINT128_IS_ZERO (fraction_uint128));
|
||||
|
||||
ECMA_UINT128_DIV10 (fraction_uint128);
|
||||
|
||||
e--;
|
||||
}
|
||||
|
||||
/* Normalizing mantissa */
|
||||
shift = 4 - ECMA_UINT128_CLZ_MAX4 (fraction_uint128);
|
||||
JERRY_ASSERT (shift >= 0);
|
||||
ECMA_UINT128_RIGHT_SHIFT_MAX63 (fraction_uint128, shift);
|
||||
ecma_uint128_shift_right (&significand_uint128, shift);
|
||||
binary_exponent += shift;
|
||||
|
||||
JERRY_ASSERT (ECMA_UINT128_CLZ_MAX63 (fraction_uint128) == 4);
|
||||
}
|
||||
|
||||
JERRY_ASSERT (!ECMA_UINT128_IS_ZERO (fraction_uint128));
|
||||
JERRY_ASSERT (ECMA_UINT128_CLZ_MAX63 (fraction_uint128) == 4);
|
||||
while (decimal_exponent < 0)
|
||||
{
|
||||
/* Denormalizing mantissa, moving highest 1 to bit 127 */
|
||||
JERRY_ASSERT (ecma_uint64_clz (significand_uint128.hi) <= 4);
|
||||
shift = ecma_uint64_clz_top4 (significand_uint128.hi);
|
||||
JERRY_ASSERT (shift >= 0 && shift <= 4);
|
||||
|
||||
ecma_uint128_shift_left (&significand_uint128, shift);
|
||||
binary_exponent -= shift;
|
||||
|
||||
ecma_uint128_div10 (&significand_uint128);
|
||||
decimal_exponent++;
|
||||
}
|
||||
|
||||
/*
|
||||
* Preparing mantissa for conversion to 52-bit representation, converting it to:
|
||||
*
|
||||
* |11 zero bits|1|116 mantissa bits|
|
||||
*/
|
||||
ECMA_UINT128_RIGHT_SHIFT_MAX63 (fraction_uint128, 7u);
|
||||
binary_exponent += 7;
|
||||
JERRY_ASSERT (ecma_uint64_clz (significand_uint128.hi) <= 4);
|
||||
shift = 11 - ecma_uint64_clz_top4 (significand_uint128.hi);
|
||||
ecma_uint128_shift_right (&significand_uint128, shift);
|
||||
binary_exponent += shift;
|
||||
|
||||
JERRY_ASSERT (ECMA_UINT128_CLZ_MAX63 (fraction_uint128) == 11);
|
||||
JERRY_ASSERT (ecma_uint64_clz (significand_uint128.hi) == 11);
|
||||
|
||||
fraction_uint64 = ecma_round_high_to_uint64 (&fraction_uint128);
|
||||
binary_exponent += ECMA_NUMBER_EXPONENT_BIAS;
|
||||
|
||||
return ecma_number_make_from_sign_mantissa_and_exponent (sign, fraction_uint64, binary_exponent);
|
||||
/* Handle denormal numbers */
|
||||
if (binary_exponent < 1)
|
||||
{
|
||||
ecma_uint128_shift_right (&significand_uint128, -binary_exponent + 1);
|
||||
binary_exponent = 0;
|
||||
}
|
||||
|
||||
significand = ecma_round_high_to_uint64 (&significand_uint128);
|
||||
|
||||
if (significand >= 1ull << (ECMA_NUMBER_FRACTION_WIDTH + 1))
|
||||
{
|
||||
/* Rounding carried over to the most significant bit, re-normalize.
|
||||
* No need to shift mantissa right, as the low 52 bits will be 0 regardless. */
|
||||
binary_exponent++;
|
||||
}
|
||||
|
||||
if (binary_exponent >= ((1 << ECMA_NUMBER_BIASED_EXP_WIDTH) - 1))
|
||||
{
|
||||
return ecma_number_make_infinity (sign);
|
||||
}
|
||||
|
||||
/* Mask low 52 bits. */
|
||||
significand &= ((1ull << ECMA_NUMBER_FRACTION_WIDTH) - 1);
|
||||
|
||||
JERRY_ASSERT (binary_exponent < (1 << ECMA_NUMBER_BIASED_EXP_WIDTH) - 1);
|
||||
JERRY_ASSERT (significand < (1ull << ECMA_NUMBER_FRACTION_WIDTH));
|
||||
|
||||
return ecma_number_create (sign, (uint32_t) binary_exponent, significand);
|
||||
#elif !JERRY_NUMBER_TYPE_FLOAT64
|
||||
/* Less precise conversion */
|
||||
ecma_number_t num = (ecma_number_t) (uint32_t) fraction_uint64;
|
||||
@@ -791,7 +724,7 @@ ecma_number_to_uint32 (ecma_number_t num) /**< ecma-number */
|
||||
|
||||
if (abs_num >= num_2_pow_32)
|
||||
{
|
||||
num_in_uint32_range = ecma_number_calc_remainder (abs_num, num_2_pow_32);
|
||||
num_in_uint32_range = ecma_number_remainder (abs_num, num_2_pow_32);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -940,8 +873,6 @@ ecma_number_to_utf8_string (ecma_number_t num, /**< ecma-number */
|
||||
return (lit_utf8_size_t) (dst_p - buffer_p);
|
||||
}
|
||||
|
||||
JERRY_ASSERT (ecma_number_get_next (ecma_number_get_prev (num)) == num);
|
||||
|
||||
/* 5. */
|
||||
uint32_t num_uint32 = ecma_number_to_uint32 (num);
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,245 @@
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
#ifndef ECMA_HELPERS_NUMBER_H
|
||||
#define ECMA_HELPERS_NUMBER_H
|
||||
|
||||
#include "ecma-globals.h"
|
||||
|
||||
#include "config.h"
|
||||
|
||||
/**
|
||||
* Binary representation of an ecma-number
|
||||
*/
|
||||
#if JERRY_NUMBER_TYPE_FLOAT64
|
||||
typedef uint64_t ecma_binary_num_t;
|
||||
#else /* !JERRY_NUMBER_TYPE_FLOAT64 */
|
||||
typedef uint32_t ecma_binary_num_t;
|
||||
#endif /* !JERRY_NUMBER_TYPE_FLOAT64 */
|
||||
|
||||
/**
|
||||
* Makes it possible to read/write the binary representation of an ecma_number_t
|
||||
* without strict aliasing rule violation.
|
||||
*/
|
||||
typedef union
|
||||
{
|
||||
ecma_number_t as_number; /**< ecma-number */
|
||||
ecma_binary_num_t as_binary; /**< binary representation */
|
||||
} ecma_number_accessor_t;
|
||||
|
||||
ecma_binary_num_t ecma_number_to_binary (ecma_number_t number);
|
||||
ecma_number_t ecma_number_from_binary (ecma_binary_num_t binary);
|
||||
|
||||
bool ecma_number_sign (ecma_binary_num_t binary);
|
||||
uint32_t ecma_number_biased_exp (ecma_binary_num_t binary);
|
||||
uint64_t ecma_number_fraction (ecma_binary_num_t binary);
|
||||
ecma_number_t ecma_number_create (bool sign, uint32_t biased_exp, uint64_t fraction);
|
||||
|
||||
/**
|
||||
* Maximum number of significant decimal digits that an ecma-number can store
|
||||
*/
|
||||
#if JERRY_NUMBER_TYPE_FLOAT64
|
||||
#define ECMA_NUMBER_MAX_DIGITS (19)
|
||||
#else /* !JERRY_NUMBER_TYPE_FLOAT64 */
|
||||
#define ECMA_NUMBER_MAX_DIGITS (9)
|
||||
#endif /* !JERRY_NUMBER_TYPE_FLOAT64 */
|
||||
|
||||
/**
|
||||
* Width of sign field
|
||||
*
|
||||
* See also:
|
||||
* IEEE-754 2008, 3.6, Table 3.5
|
||||
*/
|
||||
#define ECMA_NUMBER_SIGN_WIDTH (1)
|
||||
|
||||
/**
|
||||
* Width of biased exponent field
|
||||
*
|
||||
* See also:
|
||||
* IEEE-754 2008, 3.6, Table 3.5
|
||||
*/
|
||||
#if JERRY_NUMBER_TYPE_FLOAT64
|
||||
#define ECMA_NUMBER_BIASED_EXP_WIDTH (11)
|
||||
#else /* !JERRY_NUMBER_TYPE_FLOAT64 */
|
||||
#define ECMA_NUMBER_BIASED_EXP_WIDTH (8)
|
||||
#endif /* !JERRY_NUMBER_TYPE_FLOAT64 */
|
||||
|
||||
/**
|
||||
* Exponent bias
|
||||
*/
|
||||
#if JERRY_NUMBER_TYPE_FLOAT64
|
||||
#define ECMA_NUMBER_EXPONENT_BIAS (1023)
|
||||
#else /* !JERRY_NUMBER_TYPE_FLOAT64 */
|
||||
#define ECMA_NUMBER_EXPONENT_BIAS (127)
|
||||
#endif /* !JERRY_NUMBER_TYPE_FLOAT64 */
|
||||
|
||||
/**
|
||||
* Width of fraction field
|
||||
*
|
||||
* See also:
|
||||
* IEEE-754 2008, 3.6, Table 3.5
|
||||
*/
|
||||
#if JERRY_NUMBER_TYPE_FLOAT64
|
||||
#define ECMA_NUMBER_FRACTION_WIDTH (52)
|
||||
#else /* !JERRY_NUMBER_TYPE_FLOAT64 */
|
||||
#define ECMA_NUMBER_FRACTION_WIDTH (23)
|
||||
#endif /* !JERRY_NUMBER_TYPE_FLOAT64 */
|
||||
|
||||
/**
|
||||
* Sign bit in ecma-numbers
|
||||
*/
|
||||
#if JERRY_NUMBER_TYPE_FLOAT64
|
||||
#define ECMA_NUMBER_SIGN_BIT 0x8000000000000000ull
|
||||
#else /* !JERRY_NUMBER_TYPE_FLOAT64 */
|
||||
#define ECMA_NUMBER_SIGN_BIT 0x7f800000u;
|
||||
#endif /* !JERRY_NUMBER_TYPE_FLOAT64 */
|
||||
|
||||
/**
|
||||
* Binary representation of an IEEE-754 QNaN value.
|
||||
*/
|
||||
#if JERRY_NUMBER_TYPE_FLOAT64
|
||||
#define ECMA_NUMBER_BINARY_QNAN 0x7ff8000000000000ull
|
||||
#else /* !JERRY_NUMBER_TYPE_FLOAT64 */
|
||||
#define ECMA_NUMBER_BINARY_QNAN 0x7fc00000u
|
||||
#endif /* JERRY_NUMBER_TYPE_FLOAT64 */
|
||||
|
||||
/**
|
||||
* Binary representation of an IEEE-754 Infinity value.
|
||||
*/
|
||||
#if JERRY_NUMBER_TYPE_FLOAT64
|
||||
#define ECMA_NUMBER_BINARY_INF 0x7ff0000000000000ull
|
||||
#else /* !JERRY_NUMBER_TYPE_FLOAT64 */
|
||||
#define ECMA_NUMBER_BINARY_INF 0x7f800000u
|
||||
#endif /* JERRY_NUMBER_TYPE_FLOAT64 */
|
||||
|
||||
/**
|
||||
* Binary representation of an IEEE-754 zero value.
|
||||
*/
|
||||
#define ECMA_NUMBER_BINARY_ZERO 0x0ull
|
||||
|
||||
/**
|
||||
* Number.MIN_VALUE (i.e., the smallest positive value of ecma-number)
|
||||
*
|
||||
* See also: ECMA_262 v5, 15.7.3.3
|
||||
*/
|
||||
#if JERRY_NUMBER_TYPE_FLOAT64
|
||||
#define ECMA_NUMBER_MIN_VALUE ((ecma_number_t) 5e-324)
|
||||
#else /* !JERRY_NUMBER_TYPE_FLOAT64 */
|
||||
#define ECMA_NUMBER_MIN_VALUE (FLT_MIN)
|
||||
#endif /* JERRY_NUMBER_TYPE_FLOAT64 */
|
||||
|
||||
/**
|
||||
* Number.MAX_VALUE (i.e., the maximum value of ecma-number)
|
||||
*
|
||||
* See also: ECMA_262 v5, 15.7.3.2
|
||||
*/
|
||||
#if JERRY_NUMBER_TYPE_FLOAT64
|
||||
#define ECMA_NUMBER_MAX_VALUE ((ecma_number_t) 1.7976931348623157e+308)
|
||||
#else /* !JERRY_NUMBER_TYPE_FLOAT64 */
|
||||
#define ECMA_NUMBER_MAX_VALUE (FLT_MAX)
|
||||
#endif /* JERRY_NUMBER_TYPE_FLOAT64 */
|
||||
|
||||
/**
|
||||
* Number.EPSILON
|
||||
*
|
||||
* See also: ECMA_262 v6, 20.1.2.1
|
||||
*/
|
||||
#if JERRY_NUMBER_TYPE_FLOAT64
|
||||
#define ECMA_NUMBER_EPSILON ((ecma_number_t) 2.2204460492503130808472633361816e-16)
|
||||
#else /* !JERRY_NUMBER_TYPE_FLOAT64 */
|
||||
#define ECMA_NUMBER_EPSILON ((ecma_number_t) 1.1920928955078125e-7)
|
||||
#endif /* JERRY_NUMBER_TYPE_FLOAT64 */
|
||||
|
||||
/**
|
||||
* Number.MAX_SAFE_INTEGER
|
||||
*
|
||||
* See also: ECMA_262 v6, 20.1.2.6
|
||||
*/
|
||||
#if JERRY_NUMBER_TYPE_FLOAT64
|
||||
#define ECMA_NUMBER_MAX_SAFE_INTEGER ((ecma_number_t) 0x1FFFFFFFFFFFFF)
|
||||
#else /* !JERRY_NUMBER_TYPE_FLOAT64 */
|
||||
#define ECMA_NUMBER_MAX_SAFE_INTEGER ((ecma_number_t) 0xFFFFFF)
|
||||
#endif /* JERRY_NUMBER_TYPE_FLOAT64 */
|
||||
|
||||
/**
|
||||
* Number.MIN_SAFE_INTEGER
|
||||
*
|
||||
* See also: ECMA_262 v6, 20.1.2.8
|
||||
*/
|
||||
#if JERRY_NUMBER_TYPE_FLOAT64
|
||||
#define ECMA_NUMBER_MIN_SAFE_INTEGER ((ecma_number_t) -0x1FFFFFFFFFFFFF)
|
||||
#else /* !JERRY_NUMBER_TYPE_FLOAT64 */
|
||||
#define ECMA_NUMBER_MIN_SAFE_INTEGER ((ecma_number_t) -0xFFFFFF)
|
||||
#endif /* JERRY_NUMBER_TYPE_FLOAT64 */
|
||||
|
||||
/**
|
||||
* Number.MAX_VALUE exponent part
|
||||
*/
|
||||
#if JERRY_NUMBER_TYPE_FLOAT64
|
||||
#define NUMBER_MAX_DECIMAL_EXPONENT 308
|
||||
#else /* !JERRY_NUMBER_TYPE_FLOAT64 */
|
||||
#define NUMBER_MAX_DECIMAL_EXPONENT 38
|
||||
#endif /* JERRY_NUMBER_TYPE_FLOAT64 */
|
||||
|
||||
/**
|
||||
* Number.MIN_VALUE exponent part
|
||||
*/
|
||||
#if JERRY_NUMBER_TYPE_FLOAT64
|
||||
#define NUMBER_MIN_DECIMAL_EXPONENT -324
|
||||
#else /* !JERRY_NUMBER_TYPE_FLOAT64 */
|
||||
#define NUMBER_MIN_DECIMAL_EXPONENT -45
|
||||
#endif /* JERRY_NUMBER_TYPE_FLOAT64 */
|
||||
|
||||
/**
|
||||
* Euler number
|
||||
*/
|
||||
#define ECMA_NUMBER_E ((ecma_number_t) 2.7182818284590452354)
|
||||
|
||||
/**
|
||||
* Natural logarithm of 10
|
||||
*/
|
||||
#define ECMA_NUMBER_LN10 ((ecma_number_t) 2.302585092994046)
|
||||
|
||||
/**
|
||||
* Natural logarithm of 2
|
||||
*/
|
||||
#define ECMA_NUMBER_LN2 ((ecma_number_t) 0.6931471805599453)
|
||||
|
||||
/**
|
||||
* Logarithm base 2 of the Euler number
|
||||
*/
|
||||
#define ECMA_NUMBER_LOG2E ((ecma_number_t) 1.4426950408889634)
|
||||
|
||||
/**
|
||||
* Logarithm base 10 of the Euler number
|
||||
*/
|
||||
#define ECMA_NUMBER_LOG10E ((ecma_number_t) 0.4342944819032518)
|
||||
|
||||
/**
|
||||
* Pi number
|
||||
*/
|
||||
#define ECMA_NUMBER_PI ((ecma_number_t) 3.1415926535897932)
|
||||
|
||||
/**
|
||||
* Square root of 0.5
|
||||
*/
|
||||
#define ECMA_NUMBER_SQRT_1_2 ((ecma_number_t) 0.7071067811865476)
|
||||
|
||||
/**
|
||||
* Square root of 2
|
||||
*/
|
||||
#define ECMA_NUMBER_SQRT2 ((ecma_number_t) 1.4142135623730951)
|
||||
|
||||
#endif /* !ECMA_HELPERS_NUMBER_H */
|
||||
@@ -18,6 +18,7 @@
|
||||
#include "ecma-exceptions.h"
|
||||
#include "ecma-gc.h"
|
||||
#include "ecma-globals.h"
|
||||
#include "ecma-helpers-number.h"
|
||||
#include "ecma-helpers.h"
|
||||
|
||||
#include "jcontext.h"
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include "ecma-function-object.h"
|
||||
#include "ecma-gc.h"
|
||||
#include "ecma-globals.h"
|
||||
#include "ecma-helpers-number.h"
|
||||
#include "ecma-helpers.h"
|
||||
|
||||
#include "jrt-bit-fields.h"
|
||||
@@ -536,7 +537,7 @@ ecma_make_float_value (ecma_number_t *ecma_num_p) /**< pointer to the float numb
|
||||
*
|
||||
* @return ecma-value
|
||||
*/
|
||||
extern inline ecma_value_t JERRY_ATTR_ALWAYS_INLINE
|
||||
extern inline ecma_value_t JERRY_ATTR_ALWAYS_INLINE JERRY_ATTR_CONST
|
||||
ecma_make_nan_value (void)
|
||||
{
|
||||
return ecma_create_float_number (ecma_number_make_nan ());
|
||||
@@ -550,13 +551,7 @@ ecma_make_nan_value (void)
|
||||
static inline bool JERRY_ATTR_CONST JERRY_ATTR_ALWAYS_INLINE
|
||||
ecma_is_number_equal_to_positive_zero (ecma_number_t ecma_number) /**< number */
|
||||
{
|
||||
ecma_number_accessor_t u;
|
||||
u.as_ecma_number_t = ecma_number;
|
||||
#if !JERRY_NUMBER_TYPE_FLOAT64
|
||||
return u.as_uint32_t == 0;
|
||||
#else /* JERRY_NUMBER_TYPE_FLOAT64 */
|
||||
return u.as_uint64_t == 0;
|
||||
#endif /* !JERRY_NUMBER_TYPE_FLOAT64 */
|
||||
return ecma_number_to_binary (ecma_number) == ECMA_NUMBER_BINARY_ZERO;
|
||||
} /* ecma_is_number_equal_to_positive_zero */
|
||||
|
||||
/**
|
||||
|
||||
@@ -394,8 +394,6 @@ ecma_string_t *ecma_stringbuilder_finalize (ecma_stringbuilder_t *builder_p);
|
||||
void ecma_stringbuilder_destroy (ecma_stringbuilder_t *builder_p);
|
||||
|
||||
/* ecma-helpers-number.c */
|
||||
ecma_number_t ecma_number_pack (bool sign, uint32_t biased_exp, uint64_t fraction);
|
||||
void ecma_number_unpack (ecma_number_t num, bool *sign_p, uint32_t *biased_exp_p, uint64_t *fraction_p);
|
||||
ecma_number_t ecma_number_make_nan (void);
|
||||
ecma_number_t ecma_number_make_infinity (bool sign);
|
||||
bool ecma_number_is_nan (ecma_number_t num);
|
||||
@@ -403,11 +401,10 @@ bool ecma_number_is_negative (ecma_number_t num);
|
||||
bool ecma_number_is_zero (ecma_number_t num);
|
||||
bool ecma_number_is_infinity (ecma_number_t num);
|
||||
bool ecma_number_is_finite (ecma_number_t num);
|
||||
ecma_number_t ecma_number_make_from_sign_mantissa_and_exponent (bool sign, uint64_t mantissa, int32_t exponent);
|
||||
ecma_number_t ecma_number_get_prev (ecma_number_t num);
|
||||
ecma_number_t ecma_number_get_next (ecma_number_t num);
|
||||
ecma_number_t ecma_number_trunc (ecma_number_t num);
|
||||
ecma_number_t ecma_number_calc_remainder (ecma_number_t left_num, ecma_number_t right_num);
|
||||
ecma_number_t ecma_number_remainder (ecma_number_t left_num, ecma_number_t right_num);
|
||||
ecma_number_t ecma_number_pow (ecma_number_t x, ecma_number_t y);
|
||||
ecma_value_t
|
||||
ecma_number_parse_int (const lit_utf8_byte_t *string_buff, lit_utf8_size_t string_buff_size, ecma_value_t radix);
|
||||
@@ -538,6 +535,10 @@ bool ecma_delete_native_pointer_property (ecma_object_t *obj_p, const jerry_obje
|
||||
|
||||
/* ecma-helpers-conversion.c */
|
||||
ecma_number_t ecma_utf8_string_to_number (const lit_utf8_byte_t *str_p, lit_utf8_size_t str_size, uint32_t option);
|
||||
ecma_number_t ecma_utf8_string_to_number_by_radix (const lit_utf8_byte_t *str_p,
|
||||
lit_utf8_size_t str_size,
|
||||
uint32_t radix,
|
||||
uint32_t option);
|
||||
lit_utf8_size_t ecma_uint32_to_utf8_string (uint32_t value, lit_utf8_byte_t *out_buffer_p, lit_utf8_size_t buffer_size);
|
||||
uint32_t ecma_number_to_uint32 (ecma_number_t num);
|
||||
int32_t ecma_number_to_int32 (ecma_number_t num);
|
||||
|
||||
Reference in New Issue
Block a user