mirror of
https://github.com/jerryscript-project/jerryscript.git
synced 2025-12-15 16:29:21 +00:00
There are some leftover global functions in the code that are not referenced at all anymore. These functions are removed by this patch. There are also some global functions that are only used in their own modules. These functions are made static by this patch. JerryScript-DCO-1.0-Signed-off-by: Akos Kiss akiss@inf.u-szeged.hu
687 lines
19 KiB
C
687 lines
19 KiB
C
/* 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.
|
|
*/
|
|
|
|
#include "ecma-globals.h"
|
|
#include "ecma-helpers.h"
|
|
|
|
/** \addtogroup ecma ECMA
|
|
* @{
|
|
*
|
|
* \addtogroup ecmahelpers Helpers for operations with ECMA data types
|
|
* @{
|
|
*/
|
|
|
|
JERRY_STATIC_ASSERT (sizeof (ecma_value_t) == sizeof (ecma_integer_value_t),
|
|
size_of_ecma_value_t_must_be_equal_to_the_size_of_ecma_integer_value_t);
|
|
|
|
JERRY_STATIC_ASSERT (ECMA_DIRECT_SHIFT == ECMA_VALUE_SHIFT + 1,
|
|
currently_directly_encoded_values_has_one_extra_flag);
|
|
|
|
JERRY_STATIC_ASSERT (((1 << (ECMA_DIRECT_SHIFT - 1)) | ECMA_TYPE_DIRECT) == ECMA_DIRECT_TYPE_SIMPLE_VALUE,
|
|
currently_directly_encoded_values_start_after_direct_type_simple_value);
|
|
/**
|
|
* Position of the sign bit in ecma-numbers
|
|
*/
|
|
#define ECMA_NUMBER_SIGN_POS (ECMA_NUMBER_FRACTION_WIDTH + \
|
|
ECMA_NUMBER_BIASED_EXP_WIDTH)
|
|
|
|
#if CONFIG_ECMA_NUMBER_TYPE == CONFIG_ECMA_NUMBER_FLOAT32
|
|
JERRY_STATIC_ASSERT (sizeof (ecma_number_t) == sizeof (uint32_t),
|
|
size_of_ecma_number_t_must_be_equal_to_4_bytes);
|
|
|
|
/**
|
|
* Packing sign, fraction and biased exponent to ecma-number
|
|
*
|
|
* @return ecma-number with specified sign, biased_exponent and fraction
|
|
*/
|
|
static ecma_number_t
|
|
ecma_number_pack (bool sign, /**< sign */
|
|
uint32_t biased_exp, /**< biased exponent */
|
|
uint64_t fraction) /**< fraction */
|
|
{
|
|
JERRY_ASSERT ((biased_exp & ~((1u << ECMA_NUMBER_BIASED_EXP_WIDTH) - 1)) == 0);
|
|
JERRY_ASSERT ((fraction & ~((1ull << ECMA_NUMBER_FRACTION_WIDTH) - 1)) == 0);
|
|
|
|
uint32_t packed_value = (((sign ? 1u : 0u) << ECMA_NUMBER_SIGN_POS) |
|
|
(biased_exp << ECMA_NUMBER_FRACTION_WIDTH) |
|
|
((uint32_t) fraction));
|
|
|
|
union
|
|
{
|
|
uint32_t u32_value;
|
|
ecma_number_t float_value;
|
|
} u;
|
|
|
|
u.u32_value = packed_value;
|
|
|
|
return u.float_value;
|
|
} /* ecma_number_pack */
|
|
|
|
/**
|
|
* Unpacking sign, fraction and biased exponent from ecma-number
|
|
*/
|
|
static void
|
|
ecma_number_unpack (ecma_number_t num, /**< ecma-number */
|
|
bool *sign_p, /**< [out] sign (optional) */
|
|
uint32_t *biased_exp_p, /**< [out] biased exponent (optional) */
|
|
uint64_t *fraction_p) /**< [out] fraction (optional) */
|
|
{
|
|
union
|
|
{
|
|
uint32_t u32_value;
|
|
ecma_number_t float_value;
|
|
} u;
|
|
|
|
u.float_value = num;
|
|
|
|
uint32_t packed_value = u.u32_value;
|
|
|
|
if (sign_p != NULL)
|
|
{
|
|
*sign_p = ((packed_value >> ECMA_NUMBER_SIGN_POS) != 0);
|
|
}
|
|
|
|
if (biased_exp_p != NULL)
|
|
{
|
|
*biased_exp_p = (((packed_value) & ~(1u << ECMA_NUMBER_SIGN_POS)) >> ECMA_NUMBER_FRACTION_WIDTH);
|
|
}
|
|
|
|
if (fraction_p != NULL)
|
|
{
|
|
*fraction_p = (packed_value & ((1u << ECMA_NUMBER_FRACTION_WIDTH) - 1));
|
|
}
|
|
} /* ecma_number_unpack */
|
|
|
|
/**
|
|
* Value used to calculate exponent from biased exponent
|
|
*
|
|
* See also:
|
|
* IEEE-754 2008, 3.6, Table 3.5
|
|
*/
|
|
const int32_t ecma_number_exponent_bias = 127;
|
|
|
|
#elif CONFIG_ECMA_NUMBER_TYPE == CONFIG_ECMA_NUMBER_FLOAT64
|
|
JERRY_STATIC_ASSERT (sizeof (ecma_number_t) == sizeof (uint64_t),
|
|
size_of_ecma_number_t_must_be_equal_to_8_bytes);
|
|
|
|
/**
|
|
* Packing sign, fraction and biased exponent to ecma-number
|
|
*
|
|
* @return ecma-number with specified sign, biased_exponent and fraction
|
|
*/
|
|
static ecma_number_t
|
|
ecma_number_pack (bool sign, /**< sign */
|
|
uint32_t biased_exp, /**< biased exponent */
|
|
uint64_t fraction) /**< fraction */
|
|
{
|
|
uint64_t packed_value = (((sign ? 1ull : 0ull) << ECMA_NUMBER_SIGN_POS) |
|
|
(((uint64_t) biased_exp) << ECMA_NUMBER_FRACTION_WIDTH) |
|
|
fraction);
|
|
|
|
JERRY_ASSERT ((biased_exp & ~((1u << ECMA_NUMBER_BIASED_EXP_WIDTH) - 1)) == 0);
|
|
JERRY_ASSERT ((fraction & ~((1ull << ECMA_NUMBER_FRACTION_WIDTH) - 1)) == 0);
|
|
|
|
union
|
|
{
|
|
uint64_t u64_value;
|
|
ecma_number_t float_value;
|
|
} u;
|
|
|
|
u.u64_value = packed_value;
|
|
|
|
return u.float_value;
|
|
} /* ecma_number_pack */
|
|
|
|
/**
|
|
* Unpacking sign, fraction and biased exponent from ecma-number
|
|
*/
|
|
static void
|
|
ecma_number_unpack (ecma_number_t num, /**< ecma-number */
|
|
bool *sign_p, /**< [out] sign (optional) */
|
|
uint32_t *biased_exp_p, /**< [out] biased exponent (optional) */
|
|
uint64_t *fraction_p) /**< [out] fraction (optional) */
|
|
{
|
|
union
|
|
{
|
|
uint64_t u64_value;
|
|
ecma_number_t float_value;
|
|
} u;
|
|
u.float_value = num;
|
|
|
|
uint64_t packed_value = u.u64_value;
|
|
|
|
if (sign_p != NULL)
|
|
{
|
|
*sign_p = ((packed_value >> ECMA_NUMBER_SIGN_POS) != 0);
|
|
}
|
|
|
|
if (biased_exp_p != NULL)
|
|
{
|
|
*biased_exp_p = (uint32_t) (((packed_value) & ~(1ull << ECMA_NUMBER_SIGN_POS)) >> ECMA_NUMBER_FRACTION_WIDTH);
|
|
}
|
|
|
|
if (fraction_p != NULL)
|
|
{
|
|
*fraction_p = (packed_value & ((1ull << ECMA_NUMBER_FRACTION_WIDTH) - 1));
|
|
}
|
|
} /* ecma_number_unpack */
|
|
|
|
/**
|
|
* Value used to calculate exponent from biased exponent
|
|
*
|
|
* See also:
|
|
* IEEE-754 2008, 3.6, Table 3.5
|
|
*/
|
|
const int32_t ecma_number_exponent_bias = 1023;
|
|
|
|
#endif /* CONFIG_ECMA_NUMBER_TYPE == CONFIG_ECMA_NUMBER_FLOAT32 */
|
|
|
|
/**
|
|
* Get fraction of number
|
|
*
|
|
* @return normalized fraction field of number
|
|
*/
|
|
static uint64_t
|
|
ecma_number_get_fraction_field (ecma_number_t num) /**< ecma-number */
|
|
{
|
|
uint64_t fraction;
|
|
|
|
ecma_number_unpack (num, NULL, NULL, &fraction);
|
|
|
|
return fraction;
|
|
} /* ecma_number_get_fraction_field */
|
|
|
|
/**
|
|
* Get exponent of number
|
|
*
|
|
* @return exponent corresponding to normalized fraction of number
|
|
*/
|
|
static uint32_t
|
|
ecma_number_get_biased_exponent_field (ecma_number_t num) /**< ecma-number */
|
|
{
|
|
uint32_t biased_exp;
|
|
|
|
ecma_number_unpack (num, NULL, &biased_exp, NULL);
|
|
|
|
return biased_exp;
|
|
} /* ecma_number_get_biased_exponent_field */
|
|
|
|
/**
|
|
* Get sign bit of number
|
|
*
|
|
* @return 0 or 1 - value of sign bit
|
|
*/
|
|
static uint32_t
|
|
ecma_number_get_sign_field (ecma_number_t num) /**< ecma-number */
|
|
{
|
|
bool sign;
|
|
|
|
ecma_number_unpack (num, &sign, NULL, NULL);
|
|
|
|
return sign;
|
|
} /* ecma_number_get_sign_field */
|
|
|
|
/**
|
|
* Check if ecma-number is NaN
|
|
*
|
|
* @return true - if biased exponent is filled with 1 bits and
|
|
fraction is filled with anything but not all zero bits,
|
|
* false - otherwise
|
|
*/
|
|
inline bool JERRY_ATTR_ALWAYS_INLINE
|
|
ecma_number_is_nan (ecma_number_t num) /**< ecma-number */
|
|
{
|
|
bool is_nan = (num != num);
|
|
|
|
#ifndef JERRY_NDEBUG
|
|
uint32_t biased_exp = ecma_number_get_biased_exponent_field (num);
|
|
uint64_t fraction = ecma_number_get_fraction_field (num);
|
|
|
|
/* IEEE-754 2008, 3.4, a */
|
|
bool is_nan_ieee754 = ((biased_exp == (1u << ECMA_NUMBER_BIASED_EXP_WIDTH) - 1)
|
|
&& (fraction != 0));
|
|
|
|
JERRY_ASSERT (is_nan == is_nan_ieee754);
|
|
#endif /* !JERRY_NDEBUG */
|
|
|
|
return is_nan;
|
|
} /* ecma_number_is_nan */
|
|
|
|
/**
|
|
* Make a NaN.
|
|
*
|
|
* @return NaN value
|
|
*/
|
|
ecma_number_t
|
|
ecma_number_make_nan (void)
|
|
{
|
|
return ecma_number_pack (false,
|
|
(1u << ECMA_NUMBER_BIASED_EXP_WIDTH) - 1u,
|
|
1u);
|
|
} /* ecma_number_make_nan */
|
|
|
|
/**
|
|
* Make an Infinity.
|
|
*
|
|
* @return if !sign - +Infinity value,
|
|
* else - -Infinity value.
|
|
*/
|
|
ecma_number_t
|
|
ecma_number_make_infinity (bool sign) /**< true - for negative Infinity,
|
|
false - for positive Infinity */
|
|
{
|
|
return ecma_number_pack (sign,
|
|
(1u << ECMA_NUMBER_BIASED_EXP_WIDTH) - 1u,
|
|
0u);
|
|
} /* ecma_number_make_infinity */
|
|
|
|
/**
|
|
* Check if ecma-number is negative
|
|
*
|
|
* @return true - if sign bit of ecma-number is set
|
|
* false - otherwise
|
|
*/
|
|
inline bool JERRY_ATTR_ALWAYS_INLINE
|
|
ecma_number_is_negative (ecma_number_t num) /**< ecma-number */
|
|
{
|
|
JERRY_ASSERT (!ecma_number_is_nan (num));
|
|
|
|
/* IEEE-754 2008, 3.4 */
|
|
return (ecma_number_get_sign_field (num) != 0);
|
|
} /* ecma_number_is_negative */
|
|
|
|
/**
|
|
* Check if ecma-number is zero
|
|
*
|
|
* @return true - if fraction is zero and biased exponent is zero,
|
|
* false - otherwise
|
|
*/
|
|
bool
|
|
ecma_number_is_zero (ecma_number_t num) /**< ecma-number */
|
|
{
|
|
JERRY_ASSERT (!ecma_number_is_nan (num));
|
|
|
|
bool is_zero = (num == ECMA_NUMBER_ZERO);
|
|
|
|
#ifndef JERRY_NDEBUG
|
|
/* IEEE-754 2008, 3.4, e */
|
|
bool is_zero_ieee754 = (ecma_number_get_fraction_field (num) == 0
|
|
&& ecma_number_get_biased_exponent_field (num) == 0);
|
|
|
|
JERRY_ASSERT (is_zero == is_zero_ieee754);
|
|
#endif /* !JERRY_NDEBUG */
|
|
|
|
return is_zero;
|
|
} /* ecma_number_is_zero */
|
|
|
|
/**
|
|
* Check if number is infinity
|
|
*
|
|
* @return true - if biased exponent is filled with 1 bits and
|
|
* fraction is filled with zero bits,
|
|
* false - otherwise
|
|
*/
|
|
bool
|
|
ecma_number_is_infinity (ecma_number_t num) /**< ecma-number */
|
|
{
|
|
JERRY_ASSERT (!ecma_number_is_nan (num));
|
|
|
|
uint32_t biased_exp = ecma_number_get_biased_exponent_field (num);
|
|
uint64_t fraction = ecma_number_get_fraction_field (num);
|
|
|
|
/* IEEE-754 2008, 3.4, b */
|
|
return ((biased_exp == (1u << ECMA_NUMBER_BIASED_EXP_WIDTH) - 1)
|
|
&& (fraction == 0));
|
|
} /* ecma_number_is_infinity */
|
|
|
|
/**
|
|
* Get fraction and exponent of the number
|
|
*
|
|
* @return shift of dot in the fraction
|
|
*/
|
|
static int32_t
|
|
ecma_number_get_fraction_and_exponent (ecma_number_t num, /**< ecma-number */
|
|
uint64_t *out_fraction_p, /**< [out] fraction of the number */
|
|
int32_t *out_exponent_p) /**< [out] exponent of the number */
|
|
{
|
|
JERRY_ASSERT (!ecma_number_is_nan (num));
|
|
|
|
uint32_t biased_exp = ecma_number_get_biased_exponent_field (num);
|
|
uint64_t fraction = ecma_number_get_fraction_field (num);
|
|
int32_t exponent;
|
|
|
|
if (JERRY_UNLIKELY (biased_exp == 0))
|
|
{
|
|
/* IEEE-754 2008, 3.4, d */
|
|
if (ecma_number_is_zero (num))
|
|
{
|
|
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
|
|
{
|
|
/* IEEE-754 2008, 3.4, c */
|
|
exponent = (int32_t) biased_exp - ecma_number_exponent_bias;
|
|
|
|
JERRY_ASSERT (biased_exp > 0 && biased_exp < (1u << ECMA_NUMBER_BIASED_EXP_WIDTH) - 1);
|
|
JERRY_ASSERT ((fraction & (1ull << ECMA_NUMBER_FRACTION_WIDTH)) == 0);
|
|
fraction |= 1ull << ECMA_NUMBER_FRACTION_WIDTH;
|
|
}
|
|
|
|
*out_fraction_p = fraction;
|
|
*out_exponent_p = exponent;
|
|
return ECMA_NUMBER_FRACTION_WIDTH;
|
|
} /* ecma_number_get_fraction_and_exponent */
|
|
|
|
/**
|
|
* Make normalised positive Number from given fraction and exponent
|
|
*
|
|
* @return ecma-number
|
|
*/
|
|
static ecma_number_t
|
|
ecma_number_make_normal_positive_from_fraction_and_exponent (uint64_t fraction, /**< fraction */
|
|
int32_t exponent) /**< exponent */
|
|
{
|
|
uint32_t biased_exp = (uint32_t) (exponent + ecma_number_exponent_bias);
|
|
JERRY_ASSERT (biased_exp > 0 && biased_exp < (1u << ECMA_NUMBER_BIASED_EXP_WIDTH) - 1);
|
|
JERRY_ASSERT ((fraction & ~((1ull << (ECMA_NUMBER_FRACTION_WIDTH + 1)) - 1)) == 0);
|
|
JERRY_ASSERT ((fraction & (1ull << ECMA_NUMBER_FRACTION_WIDTH)) != 0);
|
|
|
|
return ecma_number_pack (false,
|
|
biased_exp,
|
|
fraction & ~(1ull << ECMA_NUMBER_FRACTION_WIDTH));
|
|
} /* ecma_number_make_normal_positive_from_fraction_and_exponent */
|
|
|
|
/**
|
|
* Make Number of given sign from given mantissa value and binary exponent
|
|
*
|
|
* @return ecma-number (possibly Infinity of specified sign)
|
|
*/
|
|
ecma_number_t
|
|
ecma_number_make_from_sign_mantissa_and_exponent (bool sign, /**< true - for negative sign,
|
|
false - for positive sign */
|
|
uint64_t mantissa, /**< mantissa */
|
|
int32_t exponent) /**< binary exponent */
|
|
{
|
|
/* Rounding mantissa to fit into fraction field width */
|
|
if (mantissa & ~((1ull << (ECMA_NUMBER_FRACTION_WIDTH + 1)) - 1))
|
|
{
|
|
/* Rounded mantissa looks like the following: |00...0|1|fraction_width mantissa bits| */
|
|
while ((mantissa & ~((1ull << (ECMA_NUMBER_FRACTION_WIDTH + 1)) - 1)) != 0)
|
|
{
|
|
uint64_t rightmost_bit = (mantissa & 1);
|
|
|
|
exponent++;
|
|
mantissa >>= 1;
|
|
|
|
if ((mantissa & ~((1ull << (ECMA_NUMBER_FRACTION_WIDTH + 1)) - 1)) == 0)
|
|
{
|
|
/* Rounding to nearest value */
|
|
mantissa += rightmost_bit;
|
|
|
|
/* In the first case loop is finished,
|
|
and in the second - just one shift follows and then loop finishes */
|
|
JERRY_ASSERT (((mantissa & ~((1ull << (ECMA_NUMBER_FRACTION_WIDTH + 1)) - 1)) == 0)
|
|
|| (mantissa == (1ull << (ECMA_NUMBER_FRACTION_WIDTH + 1))));
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Normalizing mantissa */
|
|
while (mantissa != 0
|
|
&& ((mantissa & (1ull << ECMA_NUMBER_FRACTION_WIDTH)) == 0))
|
|
{
|
|
exponent--;
|
|
mantissa <<= 1;
|
|
}
|
|
|
|
/* Moving floating point */
|
|
exponent += ECMA_NUMBER_FRACTION_WIDTH - 1;
|
|
|
|
int32_t biased_exp_signed = exponent + ecma_number_exponent_bias;
|
|
|
|
if (biased_exp_signed < 1)
|
|
{
|
|
/* Denormalizing mantissa if biased_exponent is less than zero */
|
|
while (biased_exp_signed < 0)
|
|
{
|
|
biased_exp_signed++;
|
|
mantissa >>= 1;
|
|
}
|
|
|
|
/* Rounding to nearest value */
|
|
mantissa += 1;
|
|
mantissa >>= 1;
|
|
|
|
/* Encoding denormalized exponent */
|
|
biased_exp_signed = 0;
|
|
}
|
|
else
|
|
{
|
|
/* Clearing highest mantissa bit that should have been non-zero if mantissa is non-zero */
|
|
mantissa &= ~(1ull << ECMA_NUMBER_FRACTION_WIDTH);
|
|
}
|
|
|
|
uint32_t biased_exp = (uint32_t) biased_exp_signed;
|
|
|
|
if (biased_exp >= ((1u << ECMA_NUMBER_BIASED_EXP_WIDTH) - 1))
|
|
{
|
|
return ecma_number_make_infinity (sign);
|
|
}
|
|
|
|
JERRY_ASSERT (biased_exp < (1u << ECMA_NUMBER_BIASED_EXP_WIDTH) - 1);
|
|
JERRY_ASSERT ((mantissa & ~((1ull << ECMA_NUMBER_FRACTION_WIDTH) - 1)) == 0);
|
|
|
|
return ecma_number_pack (sign,
|
|
biased_exp,
|
|
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_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_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 */
|
|
|
|
/**
|
|
* Truncate fractional part of the number
|
|
*
|
|
* @return integer part of the number
|
|
*/
|
|
ecma_number_t
|
|
ecma_number_trunc (ecma_number_t num) /**< ecma-number */
|
|
{
|
|
JERRY_ASSERT (!ecma_number_is_nan (num));
|
|
|
|
uint64_t fraction;
|
|
int32_t exponent;
|
|
const int32_t dot_shift = ecma_number_get_fraction_and_exponent (num, &fraction, &exponent);
|
|
const bool sign = ecma_number_is_negative (num);
|
|
|
|
if (exponent < 0)
|
|
{
|
|
return ECMA_NUMBER_ZERO;
|
|
}
|
|
else if (exponent < dot_shift)
|
|
{
|
|
fraction &= ~((1ull << (dot_shift - exponent)) - 1);
|
|
|
|
ecma_number_t tmp = ecma_number_make_normal_positive_from_fraction_and_exponent (fraction,
|
|
exponent);
|
|
if (sign)
|
|
{
|
|
return -tmp;
|
|
}
|
|
else
|
|
{
|
|
return tmp;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return num;
|
|
}
|
|
} /* ecma_number_trunc */
|
|
|
|
/**
|
|
* Calculate remainder of division of two numbers,
|
|
* as specified in ECMA-262 v5, 11.5.3, item 6.
|
|
*
|
|
* Note:
|
|
* operands shouldn't contain NaN, Infinity, or zero.
|
|
*
|
|
* @return number - calculated remainder.
|
|
*/
|
|
ecma_number_t
|
|
ecma_number_calc_remainder (ecma_number_t left_num, /**< left operand */
|
|
ecma_number_t right_num) /**< right operand */
|
|
{
|
|
JERRY_ASSERT (!ecma_number_is_nan (left_num)
|
|
&& !ecma_number_is_zero (left_num)
|
|
&& !ecma_number_is_infinity (left_num));
|
|
JERRY_ASSERT (!ecma_number_is_nan (right_num)
|
|
&& !ecma_number_is_zero (right_num)
|
|
&& !ecma_number_is_infinity (right_num));
|
|
|
|
const ecma_number_t q = ecma_number_trunc (left_num / right_num);
|
|
ecma_number_t r = left_num - right_num * q;
|
|
|
|
if (ecma_number_is_zero (r)
|
|
&& ecma_number_is_negative (left_num))
|
|
{
|
|
r = -r;
|
|
}
|
|
|
|
return r;
|
|
} /* ecma_number_calc_remainder */
|
|
|
|
/**
|
|
* ECMA-integer number multiplication.
|
|
*
|
|
* @return number - result of multiplication.
|
|
*/
|
|
inline ecma_value_t JERRY_ATTR_ALWAYS_INLINE
|
|
ecma_integer_multiply (ecma_integer_value_t left_integer, /**< left operand */
|
|
ecma_integer_value_t right_integer) /**< right operand */
|
|
{
|
|
#if defined (__GNUC__) || defined (__clang__)
|
|
/* Check if left_integer is power of 2 */
|
|
if (JERRY_UNLIKELY ((left_integer & (left_integer - 1)) == 0))
|
|
{
|
|
/* Right shift right_integer with log2 (left_integer) */
|
|
return ecma_make_integer_value (right_integer << (__builtin_ctz ((unsigned int) left_integer)));
|
|
}
|
|
else if (JERRY_UNLIKELY ((right_integer & (right_integer - 1)) == 0))
|
|
{
|
|
/* Right shift left_integer with log2 (right_integer) */
|
|
return ecma_make_integer_value (left_integer << (__builtin_ctz ((unsigned int) right_integer)));
|
|
}
|
|
#endif /* defined (__GNUC__) || defined (__clang__) */
|
|
return ecma_make_integer_value (left_integer * right_integer);
|
|
} /* ecma_integer_multiply */
|
|
|
|
/**
|
|
* @}
|
|
* @}
|
|
*/
|