From aa86a3643b0950399157ca5a3dfb55251212c300 Mon Sep 17 00:00:00 2001 From: Ruben Ayrapetyan Date: Tue, 2 Sep 2014 15:09:36 +0400 Subject: [PATCH] Implementing remainder operation according to ECMA. Checking that implementations of other arithmetic operations already conform to ECMA and removing corresponding TODOs from them. --- src/libecmaobjects/ecma-helpers-number.c | 25 +++++++++ src/libecmaobjects/ecma-helpers.h | 2 + .../ecma-number-arithmetic.c | 56 +++++++++++++++---- tests/jerry/arithmetics.js | 3 + 4 files changed, 76 insertions(+), 10 deletions(-) diff --git a/src/libecmaobjects/ecma-helpers-number.c b/src/libecmaobjects/ecma-helpers-number.c index 2bcf3608e..651d83fc9 100644 --- a/src/libecmaobjects/ecma-helpers-number.c +++ b/src/libecmaobjects/ecma-helpers-number.c @@ -350,6 +350,31 @@ ecma_number_get_fraction_and_exponent (ecma_number_t num, /**< ecma-number */ 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 * diff --git a/src/libecmaobjects/ecma-helpers.h b/src/libecmaobjects/ecma-helpers.h index b7296476d..9c19a8ac3 100644 --- a/src/libecmaobjects/ecma-helpers.h +++ b/src/libecmaobjects/ecma-helpers.h @@ -124,6 +124,8 @@ extern bool ecma_number_is_infinity (ecma_number_t num); extern int32_t ecma_number_get_fraction_and_exponent (ecma_number_t num, uint64_t *out_fraction_p, int32_t *out_exponent_p); +extern ecma_number_t ecma_number_make_normal_positive_from_fraction_and_exponent (uint64_t fraction, + int32_t exponent); extern ecma_number_t ecma_number_negate (ecma_number_t num); /* ecma-helpers-values-collection.c */ diff --git a/src/libecmaoperations/ecma-number-arithmetic.c b/src/libecmaoperations/ecma-number-arithmetic.c index f2983b5bf..b66bb118d 100644 --- a/src/libecmaoperations/ecma-number-arithmetic.c +++ b/src/libecmaoperations/ecma-number-arithmetic.c @@ -14,6 +14,7 @@ */ #include "ecma-globals.h" +#include "ecma-helpers.h" #include "ecma-number-arithmetic.h" /** \addtogroup ecma ECMA @@ -37,8 +38,6 @@ ecma_number_t ecma_op_number_add (ecma_number_t left_num, /**< left operand */ ecma_number_t right_num) /**< right operand */ { - TODO(Implement according to ECMA); - return left_num + right_num; } /* ecma_op_number_add */ @@ -69,8 +68,6 @@ ecma_number_t ecma_op_number_multiply (ecma_number_t left_num, /**< left operand */ ecma_number_t right_num) /**< right operand */ { - TODO(Implement according to ECMA); - return left_num * right_num; } /* ecma_op_number_multiply */ @@ -86,8 +83,6 @@ ecma_number_t ecma_op_number_divide (ecma_number_t left_num, /**< left operand */ ecma_number_t right_num) /**< right operand */ { - TODO(Implement according to ECMA); - return left_num / right_num; } /* ecma_op_number_divide */ @@ -103,11 +98,54 @@ ecma_number_t ecma_op_number_remainder (ecma_number_t left_num, /**< left operand */ ecma_number_t right_num) /**< right operand */ { - TODO(Implement according to ECMA); + TODO (Check precision); ecma_number_t n = left_num, d = right_num; - return (n - d * (ecma_number_t) ((int32_t) (n / d))); + if (ecma_number_is_nan (n) + || ecma_number_is_nan (d) + || ecma_number_is_infinity (n) + || ecma_number_is_zero (d)) + { + return ecma_number_make_nan (); + } + else if (ecma_number_is_infinity (d) + || (ecma_number_is_zero (n) + && !ecma_number_is_zero (d))) + { + return n; + } + + JERRY_ASSERT (!ecma_number_is_nan (n) + && !ecma_number_is_zero (n) + && !ecma_number_is_infinity (n)); + JERRY_ASSERT (!ecma_number_is_nan (d) + && !ecma_number_is_zero (d) + && !ecma_number_is_infinity (d)); + + ecma_number_t q = n / d; + + uint64_t fraction; + int32_t exponent; + int32_t dot_shift = ecma_number_get_fraction_and_exponent (q, &fraction, &exponent); + + if (exponent < 0) + { + return n; + } + else if (exponent >= dot_shift) + { + return n - d * q; + } + else + { + fraction &= ~((1ull << (dot_shift - exponent)) - 1); + + q = ecma_number_make_normal_positive_from_fraction_and_exponent (fraction, + exponent); + + return n - d * q; + } } /* ecma_op_number_remainder */ /** @@ -121,8 +159,6 @@ ecma_op_number_remainder (ecma_number_t left_num, /**< left operand */ ecma_number_t ecma_op_number_negate (ecma_number_t num) /**< operand */ { - TODO(Implement according to ECMA); - return -num; } /* ecma_op_number_negate */ diff --git a/tests/jerry/arithmetics.js b/tests/jerry/arithmetics.js index beb3bfeed..0c871ba87 100644 --- a/tests/jerry/arithmetics.js +++ b/tests/jerry/arithmetics.js @@ -29,3 +29,6 @@ assert((number - 9) == 72); assert((number * 10) == 810); assert((number / 9) == 9); assert((number % 79) == 2); + +var num1 = 1234567, num2 = 1234000; +assert((num1 % num2) == 567);