Implement missing Math functions from ES6 standard (#3593)
First step to fix issue #3568. Changes: - Implemented Math.clz32(), Math.fround(), Math.imul(), Math.hypot(). - Implemented all remaining Math functions with calling the standard libm functions, but they throw UNIMPLEMENTED exception with jerry-libm, because the necessary fdlibm functions are missing and should be ported. All Math related test262 tests pass (except function name and length tests) JerryScript-DCO-1.0-Signed-off-by: Csaba Osztrogonác oszi@inf.u-szeged.hu
This commit is contained in:
committed by
GitHub
parent
6c3a42ec48
commit
72f8ef344c
@@ -29,6 +29,10 @@
|
||||
#include "jrt.h"
|
||||
#include "jrt-libc-includes.h"
|
||||
|
||||
#if defined (WIN32)
|
||||
#include <intrin.h>
|
||||
#endif
|
||||
|
||||
#if ENABLED (JERRY_BUILTIN_MATH)
|
||||
|
||||
#define ECMA_BUILTINS_INTERNAL
|
||||
@@ -55,21 +59,37 @@ enum
|
||||
ECMA_MATH_OBJECT_EXP, /* ECMA-262 v5, 15.8.2.8 */
|
||||
ECMA_MATH_OBJECT_FLOOR, /* ECMA-262 v5, 15.8.2.9 */
|
||||
ECMA_MATH_OBJECT_LOG, /* ECMA-262 v5, 15.8.2.10 */
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
ECMA_MATH_OBJECT_TRUNC, /* ECMA-262 v6, 20.2.2.35 */
|
||||
ECMA_MATH_OBJECT_SIGN, /* ECMA-262 v6, 20.2.2.29 */
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
ECMA_MATH_OBJECT_ROUND, /* ECMA-262 v5, 15.8.2.15 */
|
||||
ECMA_MATH_OBJECT_SIN, /* ECMA-262 v5, 15.8.2.16 */
|
||||
ECMA_MATH_OBJECT_SQRT, /* ECMA-262 v5, 15.8.2.17 */
|
||||
ECMA_MATH_OBJECT_TAN, /* ECMA-262 v5, 15.8.2.18 */
|
||||
|
||||
ECMA_MATH_OBJECT_ATAN2, /* ECMA-262 v5, 15.8.2.5 */
|
||||
ECMA_MATH_OBJECT_POW, /* ECMA-262 v5, 15.8.2.13 */
|
||||
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
ECMA_MATH_OBJECT_ACOSH, /* ECMA-262 v6, 20.2.2.3 */
|
||||
ECMA_MATH_OBJECT_ASINH, /* ECMA-262 v6, 20.2.2.5 */
|
||||
ECMA_MATH_OBJECT_ATANH, /* ECMA-262 v6, 20.2.2.7 */
|
||||
ECMA_MATH_OBJECT_CBRT, /* ECMA-262 v6, 20.2.2.9 */
|
||||
ECMA_MATH_OBJECT_CLZ32, /* ECMA-262 v6, 20.2.2.11 */
|
||||
ECMA_MATH_OBJECT_COSH, /* ECMA-262 v6, 20.2.2.13 */
|
||||
ECMA_MATH_OBJECT_EXPM1, /* ECMA-262 v6, 20.2.2.15 */
|
||||
ECMA_MATH_OBJECT_FROUND, /* ECMA-262 v6, 20.2.2.17 */
|
||||
ECMA_MATH_OBJECT_LOG1P, /* ECMA-262 v6, 20.2.2.21 */
|
||||
ECMA_MATH_OBJECT_LOG10, /* ECMA-262 v6, 20.2.2.22 */
|
||||
ECMA_MATH_OBJECT_LOG2, /* ECMA-262 v6, 20.2.2.23 */
|
||||
ECMA_MATH_OBJECT_SIGN, /* ECMA-262 v6, 20.2.2.29 */
|
||||
ECMA_MATH_OBJECT_SINH, /* ECMA-262 v6, 20.2.2.31 */
|
||||
ECMA_MATH_OBJECT_TANH, /* ECMA-262 v6, 20.2.2.34 */
|
||||
ECMA_MATH_OBJECT_TRUNC, /* ECMA-262 v6, 20.2.2.35 */
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
ECMA_MATH_OBJECT_ATAN2, /* ECMA-262 v5, 15.8.2.5 */ /* first routine with 2 arguments */
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
ECMA_MATH_OBJECT_IMUL, /* ECMA-262 v6, 20.2.2.19 */
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
ECMA_MATH_OBJECT_POW, /* ECMA-262 v5, 15.8.2.13 */ /* last routine with 1 or 2 arguments*/
|
||||
ECMA_MATH_OBJECT_MAX, /* ECMA-262 v5, 15.8.2.11 */
|
||||
ECMA_MATH_OBJECT_MIN, /* ECMA-262 v5, 15.8.2.12 */
|
||||
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
ECMA_MATH_OBJECT_HYPOT, /* ECMA-262 v6, 20.2.2.18 */
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
ECMA_MATH_OBJECT_RANDOM, /* ECMA-262 v5, 15.8.2.14 */
|
||||
};
|
||||
|
||||
@@ -164,6 +184,76 @@ ecma_builtin_math_object_max_min (bool is_max, /**< 'max' or 'min' operation */
|
||||
} /* ecma_builtin_math_object_max_min */
|
||||
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
/**
|
||||
* The Math object's 'hypot' routine
|
||||
*
|
||||
* See also:
|
||||
* ECMA-262 v6, 20.2.2.18
|
||||
*
|
||||
* @return ecma value
|
||||
* Returned value must be freed with ecma_free_value.
|
||||
*/
|
||||
static ecma_value_t
|
||||
ecma_builtin_math_object_hypot (const ecma_value_t *arg, /**< arguments list */
|
||||
ecma_length_t args_number) /**< number of arguments */
|
||||
{
|
||||
if (args_number == 0)
|
||||
{
|
||||
return ecma_make_number_value (0.0);
|
||||
}
|
||||
|
||||
bool nan_found = false;
|
||||
bool inf_found = false;
|
||||
ecma_number_t result_num = 0;
|
||||
|
||||
while (args_number > 0)
|
||||
{
|
||||
ecma_number_t arg_num;
|
||||
if (ecma_is_value_number (*arg))
|
||||
{
|
||||
arg_num = ecma_get_number_from_value (*arg);
|
||||
}
|
||||
else
|
||||
{
|
||||
ecma_value_t value = ecma_op_to_number (*arg);
|
||||
if (ECMA_IS_VALUE_ERROR (value))
|
||||
{
|
||||
return value;
|
||||
}
|
||||
arg_num = ecma_get_number_from_value (value);
|
||||
ecma_fast_free_value (value);
|
||||
}
|
||||
|
||||
arg++;
|
||||
args_number--;
|
||||
|
||||
if (JERRY_UNLIKELY (inf_found || ecma_number_is_infinity (arg_num)))
|
||||
{
|
||||
inf_found = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (JERRY_UNLIKELY (nan_found || ecma_number_is_nan (arg_num)))
|
||||
{
|
||||
nan_found = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
result_num += arg_num * arg_num;
|
||||
}
|
||||
|
||||
if (JERRY_UNLIKELY (inf_found))
|
||||
{
|
||||
return ecma_make_number_value (ecma_number_make_infinity (false));
|
||||
}
|
||||
|
||||
if (JERRY_UNLIKELY (nan_found))
|
||||
{
|
||||
return ecma_make_nan_value ();
|
||||
}
|
||||
|
||||
return ecma_make_number_value (sqrt (result_num));
|
||||
} /* ecma_builtin_math_object_hypot */
|
||||
|
||||
/**
|
||||
* The Math object's 'trunc' routine
|
||||
@@ -432,10 +522,141 @@ ecma_builtin_math_dispatch_routine (uint16_t builtin_routine_id, /**< built-in w
|
||||
}
|
||||
break;
|
||||
}
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
case ECMA_MATH_OBJECT_ACOSH:
|
||||
{
|
||||
#ifdef JERRY_LIBM_MATH_H
|
||||
return ecma_raise_type_error (ECMA_ERR_MSG ("UNIMPLEMENTED: Math.acosh"));
|
||||
#else /* !JERRY_LIBM_MATH_H */
|
||||
x = DOUBLE_TO_ECMA_NUMBER_T (acosh (x));
|
||||
#endif /* JERRY_LIBM_MATH_H */
|
||||
break;
|
||||
}
|
||||
case ECMA_MATH_OBJECT_ASINH:
|
||||
{
|
||||
#ifdef JERRY_LIBM_MATH_H
|
||||
return ecma_raise_type_error (ECMA_ERR_MSG ("UNIMPLEMENTED: Math.asinh"));
|
||||
#else /* !JERRY_LIBM_MATH_H */
|
||||
x = DOUBLE_TO_ECMA_NUMBER_T (asinh (x));
|
||||
#endif /* JERRY_LIBM_MATH_H */
|
||||
break;
|
||||
}
|
||||
case ECMA_MATH_OBJECT_ATANH:
|
||||
{
|
||||
#ifdef JERRY_LIBM_MATH_H
|
||||
return ecma_raise_type_error (ECMA_ERR_MSG ("UNIMPLEMENTED: Math.atanh"));
|
||||
#else /* !JERRY_LIBM_MATH_H */
|
||||
x = DOUBLE_TO_ECMA_NUMBER_T (atanh (x));
|
||||
#endif /* JERRY_LIBM_MATH_H */
|
||||
break;
|
||||
}
|
||||
case ECMA_MATH_OBJECT_CBRT:
|
||||
{
|
||||
#ifdef JERRY_LIBM_MATH_H
|
||||
return ecma_raise_type_error (ECMA_ERR_MSG ("UNIMPLEMENTED: Math.cbrt"));
|
||||
#else /* !JERRY_LIBM_MATH_H */
|
||||
x = DOUBLE_TO_ECMA_NUMBER_T (cbrt (x));
|
||||
#endif /* JERRY_LIBM_MATH_H */
|
||||
break;
|
||||
}
|
||||
case ECMA_MATH_OBJECT_COSH:
|
||||
{
|
||||
#ifdef JERRY_LIBM_MATH_H
|
||||
return ecma_raise_type_error (ECMA_ERR_MSG ("UNIMPLEMENTED: Math.cosh"));
|
||||
#else /* !JERRY_LIBM_MATH_H */
|
||||
x = DOUBLE_TO_ECMA_NUMBER_T (cosh (x));
|
||||
#endif /* JERRY_LIBM_MATH_H */
|
||||
break;
|
||||
}
|
||||
case ECMA_MATH_OBJECT_EXPM1:
|
||||
{
|
||||
#ifdef JERRY_LIBM_MATH_H
|
||||
return ecma_raise_type_error (ECMA_ERR_MSG ("UNIMPLEMENTED: Math.expm1"));
|
||||
#else /* !JERRY_LIBM_MATH_H */
|
||||
x = DOUBLE_TO_ECMA_NUMBER_T (expm1 (x));
|
||||
#endif /* JERRY_LIBM_MATH_H */
|
||||
break;
|
||||
}
|
||||
case ECMA_MATH_OBJECT_LOG1P:
|
||||
{
|
||||
#ifdef JERRY_LIBM_MATH_H
|
||||
return ecma_raise_type_error (ECMA_ERR_MSG ("UNIMPLEMENTED: Math.log1p"));
|
||||
#else /* !JERRY_LIBM_MATH_H */
|
||||
x = DOUBLE_TO_ECMA_NUMBER_T (log1p (x));
|
||||
#endif /* JERRY_LIBM_MATH_H */
|
||||
break;
|
||||
}
|
||||
case ECMA_MATH_OBJECT_LOG10:
|
||||
{
|
||||
#ifdef JERRY_LIBM_MATH_H
|
||||
return ecma_raise_type_error (ECMA_ERR_MSG ("UNIMPLEMENTED: Math.log10"));
|
||||
#else /* !JERRY_LIBM_MATH_H */
|
||||
x = DOUBLE_TO_ECMA_NUMBER_T (log10 (x));
|
||||
#endif /* JERRY_LIBM_MATH_H */
|
||||
break;
|
||||
}
|
||||
case ECMA_MATH_OBJECT_LOG2:
|
||||
{
|
||||
#ifdef JERRY_LIBM_MATH_H
|
||||
return ecma_raise_type_error (ECMA_ERR_MSG ("UNIMPLEMENTED: Math.log2"));
|
||||
#else /* !JERRY_LIBM_MATH_H */
|
||||
x = DOUBLE_TO_ECMA_NUMBER_T (log2 (x));
|
||||
#endif /* JERRY_LIBM_MATH_H */
|
||||
break;
|
||||
}
|
||||
case ECMA_MATH_OBJECT_SINH:
|
||||
{
|
||||
#ifdef JERRY_LIBM_MATH_H
|
||||
return ecma_raise_type_error (ECMA_ERR_MSG ("UNIMPLEMENTED: Math.sinh"));
|
||||
#else /* !JERRY_LIBM_MATH_H */
|
||||
x = DOUBLE_TO_ECMA_NUMBER_T (sinh (x));
|
||||
#endif /* JERRY_LIBM_MATH_H */
|
||||
break;
|
||||
}
|
||||
case ECMA_MATH_OBJECT_TANH:
|
||||
{
|
||||
#ifdef JERRY_LIBM_MATH_H
|
||||
return ecma_raise_type_error (ECMA_ERR_MSG ("UNIMPLEMENTED: Math.tanh"));
|
||||
#else /* !JERRY_LIBM_MATH_H */
|
||||
x = DOUBLE_TO_ECMA_NUMBER_T (tanh (x));
|
||||
#endif /* JERRY_LIBM_MATH_H */
|
||||
break;
|
||||
}
|
||||
case ECMA_MATH_OBJECT_CLZ32:
|
||||
{
|
||||
uint32_t n = ecma_number_to_uint32 (x);
|
||||
#if defined (__GNUC__) || defined (__clang__)
|
||||
x = n ? __builtin_clz (n) : 32;
|
||||
#elif defined (WIN32)
|
||||
unsigned long ret;
|
||||
x = _BitScanReverse (&ret, n) ? 31 - ret : 32;
|
||||
#else
|
||||
x = 32;
|
||||
for (int i = 31; i >= 0; i--)
|
||||
{
|
||||
if (n >> i)
|
||||
{
|
||||
x = 31 - i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
case ECMA_MATH_OBJECT_FROUND:
|
||||
{
|
||||
x = (float) x;
|
||||
break;
|
||||
}
|
||||
case ECMA_MATH_OBJECT_IMUL:
|
||||
{
|
||||
x = (int32_t) (ecma_number_to_uint32 (x) * ecma_number_to_uint32 (y));
|
||||
break;
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
}
|
||||
|
||||
return ecma_make_number_value (x);
|
||||
}
|
||||
} /* if (builtin_routine_id <= ECMA_MATH_OBJECT_POW) */
|
||||
|
||||
if (builtin_routine_id <= ECMA_MATH_OBJECT_MIN)
|
||||
{
|
||||
@@ -444,6 +665,13 @@ ecma_builtin_math_dispatch_routine (uint16_t builtin_routine_id, /**< built-in w
|
||||
arguments_number);
|
||||
}
|
||||
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
if (builtin_routine_id == ECMA_MATH_OBJECT_HYPOT)
|
||||
{
|
||||
return ecma_builtin_math_object_hypot (arguments_list, arguments_number);
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
|
||||
JERRY_ASSERT (builtin_routine_id == ECMA_MATH_OBJECT_RANDOM);
|
||||
|
||||
return ecma_builtin_math_object_random ();
|
||||
|
||||
@@ -92,7 +92,22 @@ ROUTINE (LIT_MAGIC_STRING_SIN, ECMA_MATH_OBJECT_SIN, 1, 1)
|
||||
ROUTINE (LIT_MAGIC_STRING_SQRT, ECMA_MATH_OBJECT_SQRT, 1, 1)
|
||||
ROUTINE (LIT_MAGIC_STRING_TAN, ECMA_MATH_OBJECT_TAN, 1, 1)
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
ROUTINE (LIT_MAGIC_STRING_ACOSH, ECMA_MATH_OBJECT_ACOSH, 1, 1)
|
||||
ROUTINE (LIT_MAGIC_STRING_ASINH, ECMA_MATH_OBJECT_ASINH, 1, 1)
|
||||
ROUTINE (LIT_MAGIC_STRING_ATANH, ECMA_MATH_OBJECT_ATANH, 1, 1)
|
||||
ROUTINE (LIT_MAGIC_STRING_CBRT, ECMA_MATH_OBJECT_CBRT, 1, 1)
|
||||
ROUTINE (LIT_MAGIC_STRING_CLZ32, ECMA_MATH_OBJECT_CLZ32, 1, 1)
|
||||
ROUTINE (LIT_MAGIC_STRING_COSH, ECMA_MATH_OBJECT_COSH, 1, 1)
|
||||
ROUTINE (LIT_MAGIC_STRING_EXPM1, ECMA_MATH_OBJECT_EXPM1, 1, 1)
|
||||
ROUTINE (LIT_MAGIC_STRING_FROUND, ECMA_MATH_OBJECT_FROUND, 1, 1)
|
||||
ROUTINE (LIT_MAGIC_STRING_HYPOT, ECMA_MATH_OBJECT_HYPOT, NON_FIXED, 2)
|
||||
ROUTINE (LIT_MAGIC_STRING_IMUL, ECMA_MATH_OBJECT_IMUL, 2, 2)
|
||||
ROUTINE (LIT_MAGIC_STRING_LOG1P, ECMA_MATH_OBJECT_LOG1P, 1, 1)
|
||||
ROUTINE (LIT_MAGIC_STRING_LOG10, ECMA_MATH_OBJECT_LOG10, 1, 1)
|
||||
ROUTINE (LIT_MAGIC_STRING_LOG2, ECMA_MATH_OBJECT_LOG2, 1, 1)
|
||||
ROUTINE (LIT_MAGIC_STRING_SIGN, ECMA_MATH_OBJECT_SIGN, 1, 1)
|
||||
ROUTINE (LIT_MAGIC_STRING_SINH, ECMA_MATH_OBJECT_SINH, 1, 1)
|
||||
ROUTINE (LIT_MAGIC_STRING_TANH, ECMA_MATH_OBJECT_TANH, 1, 1)
|
||||
ROUTINE (LIT_MAGIC_STRING_TRUNC, ECMA_MATH_OBJECT_TRUNC, 1, 1)
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
|
||||
|
||||
Reference in New Issue
Block a user