407 lines
9.3 KiB
C
407 lines
9.3 KiB
C
/* Copyright 2014 Samsung Electronics Co., Ltd.
|
|
*
|
|
* 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.
|
|
*/
|
|
|
|
/** \addtogroup ecma ECMA
|
|
* @{
|
|
*
|
|
* \addtogroup ecmahelpers Helpers for operations with ECMA data types
|
|
* @{
|
|
*/
|
|
|
|
#include "ecma-globals.h"
|
|
#include "ecma-helpers.h"
|
|
|
|
#ifdef CONFIG_ECMA_NUMBER_FLOAT32
|
|
JERRY_STATIC_ASSERT (sizeof (ecma_number_t) == sizeof (uint32_t));
|
|
|
|
/**
|
|
* 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)
|
|
|
|
/**
|
|
* Field of ecma-number
|
|
*
|
|
* See also:
|
|
* IEEE-754 2008, 3.4
|
|
*/
|
|
typedef struct
|
|
{
|
|
/** fraction field */
|
|
unsigned int fraction : ECMA_NUMBER_FRACTION_WIDTH;
|
|
|
|
/** biased exponent field */
|
|
unsigned int biased_exp : ECMA_NUMBER_BIASED_EXP_WIDTH;
|
|
|
|
/** sign bit */
|
|
unsigned int sign : ECMA_NUMBER_SIGN_WIDTH;
|
|
} ecma_number_fields_t;
|
|
|
|
/**
|
|
* 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 defined (CONFIG_ECMA_NUMBER_FLOAT64)
|
|
JERRY_STATIC_ASSERT (sizeof (ecma_number_t) == sizeof (uint64_t));
|
|
|
|
/**
|
|
* 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)
|
|
|
|
/**
|
|
* Field of ecma-number
|
|
*
|
|
* See also:
|
|
* IEEE-754 2008, 3.4
|
|
*/
|
|
typedef struct
|
|
{
|
|
/** fraction field */
|
|
unsigned long int fraction : ECMA_NUMBER_FRACTION_WIDTH;
|
|
|
|
/** biased exponent field */
|
|
unsigned long int biased_exp : ECMA_NUMBER_BIASED_EXP_WIDTH;
|
|
|
|
/** sign bit */
|
|
unsigned long int sign : ECMA_NUMBER_SIGN_WIDTH;
|
|
} ecma_number_fields_t;
|
|
|
|
/**
|
|
* 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;
|
|
#else /* !CONFIG_ECMA_NUMBER_FLOAT32 && !CONFIG_ECMA_NUMBER_FLOAT64 */
|
|
# error "!CONFIG_ECMA_NUMBER_FLOAT32 && !CONFIG_ECMA_NUMBER_FLOAT64"
|
|
#endif /* !CONFIG_ECMA_NUMBER_FLOAT32 && !CONFIG_ECMA_NUMBER_FLOAT64 */
|
|
|
|
/**
|
|
* Get fraction of number
|
|
*
|
|
* @return normalized fraction field of number
|
|
*/
|
|
static uint64_t
|
|
ecma_number_get_fraction_field (ecma_number_t num) /**< ecma-number */
|
|
{
|
|
union
|
|
{
|
|
ecma_number_fields_t fields;
|
|
ecma_number_t value;
|
|
} u;
|
|
|
|
u.value = num;
|
|
|
|
return u.fields.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 */
|
|
{
|
|
union
|
|
{
|
|
ecma_number_fields_t fields;
|
|
ecma_number_t value;
|
|
} u;
|
|
|
|
u.value = num;
|
|
|
|
return u.fields.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 */
|
|
{
|
|
union
|
|
{
|
|
ecma_number_fields_t fields;
|
|
ecma_number_t value;
|
|
} u;
|
|
|
|
u.value = num;
|
|
|
|
return u.fields.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
|
|
*/
|
|
bool
|
|
ecma_number_is_nan (ecma_number_t num) /**< ecma-number */
|
|
{
|
|
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 */
|
|
|
|
return ((biased_exp == (1u << ECMA_NUMBER_BIASED_EXP_WIDTH) - 1)
|
|
&& (fraction != 0));
|
|
} /* ecma_number_is_nan */
|
|
|
|
/**
|
|
* Make a NaN.
|
|
*
|
|
* @return NaN value
|
|
*/
|
|
ecma_number_t
|
|
ecma_number_make_nan (void)
|
|
{
|
|
union
|
|
{
|
|
ecma_number_fields_t fields;
|
|
ecma_number_t value;
|
|
} u;
|
|
|
|
u.fields.biased_exp = (1u << ECMA_NUMBER_BIASED_EXP_WIDTH) - 1;
|
|
u.fields.fraction = 1;
|
|
u.fields.sign = 0;
|
|
|
|
return u.value;
|
|
} /* 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 */
|
|
{
|
|
union
|
|
{
|
|
ecma_number_fields_t fields;
|
|
ecma_number_t value;
|
|
} u;
|
|
|
|
u.fields.biased_exp = (1u << ECMA_NUMBER_BIASED_EXP_WIDTH) - 1;
|
|
u.fields.fraction = 0;
|
|
u.fields.sign = sign;
|
|
|
|
return u.value;
|
|
} /* ecma_number_make_infinity */
|
|
|
|
/**
|
|
* Check if ecma-number is negative
|
|
*
|
|
* @return true - if sign bit of ecma-number is set
|
|
* false - otherwise
|
|
*/
|
|
bool
|
|
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));
|
|
|
|
/* IEEE-754 2008, 3.4, e */
|
|
|
|
return (ecma_number_get_fraction_field (num) == 0
|
|
&& ecma_number_get_biased_exponent_field (num) == 0);
|
|
} /* 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
|
|
*/
|
|
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));
|
|
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);
|
|
int32_t exponent;
|
|
|
|
if (unlikely (biased_exp == 0))
|
|
{
|
|
/* IEEE-754 2008, 3.4, d */
|
|
exponent = 1 - ecma_number_exponent_bias;
|
|
|
|
while (!(fraction & (1ul << ECMA_NUMBER_FRACTION_WIDTH)))
|
|
{
|
|
JERRY_ASSERT (fraction != 0);
|
|
|
|
fraction <<= 1;
|
|
exponent--;
|
|
}
|
|
}
|
|
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 & (1ul << ECMA_NUMBER_FRACTION_WIDTH)) == 0);
|
|
fraction |= 1ul << 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
|
|
*/
|
|
ecma_number_t
|
|
ecma_number_make_normal_positive_from_fraction_and_exponent (uint64_t fraction, /**< fraction */
|
|
int32_t exponent) /**< exponent */
|
|
{
|
|
union
|
|
{
|
|
ecma_number_fields_t fields;
|
|
ecma_number_t value;
|
|
} u;
|
|
|
|
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);
|
|
|
|
u.fields.biased_exp = biased_exp & ((1u << ECMA_NUMBER_BIASED_EXP_WIDTH) - 1);
|
|
u.fields.fraction = fraction & ((1u << ECMA_NUMBER_FRACTION_WIDTH) - 1);
|
|
u.fields.sign = 0;
|
|
|
|
return u.value;
|
|
} /* ecma_number_make_normal_positive_from_fraction_and_exponent */
|
|
|
|
/**
|
|
* Negate ecma-number
|
|
*
|
|
* @return negated number
|
|
*/
|
|
ecma_number_t
|
|
ecma_number_negate (ecma_number_t num) /**< ecma-number */
|
|
{
|
|
JERRY_ASSERT (!ecma_number_is_nan (num));
|
|
|
|
union
|
|
{
|
|
ecma_number_fields_t fields;
|
|
ecma_number_t value;
|
|
} u;
|
|
|
|
u.value = num;
|
|
|
|
u.fields.sign = !u.fields.sign;
|
|
|
|
return u.value;
|
|
} /* ecma_number_negate */
|
|
|
|
|
|
/**
|
|
* @}
|
|
* @}
|
|
*/
|