From 6c422fec2e0c159347314103712a6b37e91e2043 Mon Sep 17 00:00:00 2001 From: Ruben Ayrapetyan Date: Tue, 23 Sep 2014 18:44:27 +0400 Subject: [PATCH] Implementing Math.min and Math.max built-ins. --- .../ecma-builtin-math-object.c | 152 +++++++++++++++++- tests/jerry/math_max.js | 31 ++++ tests/jerry/math_min.js | 31 ++++ 3 files changed, 212 insertions(+), 2 deletions(-) create mode 100644 tests/jerry/math_max.js create mode 100644 tests/jerry/math_min.js diff --git a/src/libecmabuiltins/ecma-builtin-math-object.c b/src/libecmabuiltins/ecma-builtin-math-object.c index c38e58f45..2ed146b3b 100644 --- a/src/libecmabuiltins/ecma-builtin-math-object.c +++ b/src/libecmabuiltins/ecma-builtin-math-object.c @@ -338,7 +338,81 @@ static ecma_completion_value_t ecma_builtin_math_object_max (ecma_value_t args[], /**< arguments list */ ecma_length_t args_number) /**< number of arguments */ { - JERRY_UNIMPLEMENTED_REF_UNUSED_VARS (args, args_number); + ecma_completion_value_t ret_value = ecma_make_empty_completion_value (); + + ecma_number_t ret_num = ecma_number_make_infinity (true); + + bool is_just_convert = false; + + for (ecma_length_t arg_index = 0; + arg_index < args_number; + arg_index++) + { + ECMA_TRY_CATCH (arg_num_value, + ecma_op_to_number (args[arg_index]), + ret_value); + + if (!is_just_convert) + { + ecma_number_t arg_num = *(ecma_number_t*) ECMA_GET_POINTER (arg_num_value.u.value.value); + + if (unlikely (ecma_number_is_nan (arg_num))) + { + ret_num = arg_num; + is_just_convert = true; + } + else if (ecma_number_is_zero (arg_num) /* both numbers are zeroes */ + && ecma_number_is_zero (ret_num)) + { + if (!ecma_number_is_negative (arg_num)) + { + ret_num = arg_num; + } + } + else if (ecma_number_is_infinity (arg_num)) + { + if (!ecma_number_is_negative (arg_num)) + { + ret_num = arg_num; + is_just_convert = true; + } + } + else if (ecma_number_is_infinity (ret_num)) /* ret_num is negative infinity */ + { + JERRY_ASSERT (ecma_number_is_negative (ret_num)); + + ret_num = arg_num; + } + else + { + JERRY_ASSERT (!ecma_number_is_nan (arg_num) + && !ecma_number_is_infinity (arg_num)); + JERRY_ASSERT (!ecma_number_is_nan (ret_num) + && !ecma_number_is_infinity (ret_num)); + + if (arg_num > ret_num) + { + ret_num = arg_num; + } + } + } + + ECMA_FINALIZE (arg_num_value); + + if (ecma_is_completion_value_throw (ret_value)) + { + return ret_value; + } + + JERRY_ASSERT (ecma_is_completion_value_empty (ret_value)); + } + + JERRY_ASSERT (ecma_is_completion_value_empty (ret_value)); + + ecma_number_t *num_p = ecma_alloc_number (); + *num_p = ret_num; + + return ecma_make_return_completion_value (ecma_make_number_value (num_p)); } /* ecma_builtin_math_object_max */ /** @@ -354,7 +428,81 @@ static ecma_completion_value_t ecma_builtin_math_object_min (ecma_value_t args[], /**< arguments list */ ecma_length_t args_number) /**< number of arguments */ { - JERRY_UNIMPLEMENTED_REF_UNUSED_VARS (args, args_number); + ecma_completion_value_t ret_value = ecma_make_empty_completion_value (); + + ecma_number_t ret_num = ecma_number_make_infinity (false); + + bool is_just_convert = false; + + for (ecma_length_t arg_index = 0; + arg_index < args_number; + arg_index++) + { + ECMA_TRY_CATCH (arg_num_value, + ecma_op_to_number (args[arg_index]), + ret_value); + + if (!is_just_convert) + { + ecma_number_t arg_num = *(ecma_number_t*) ECMA_GET_POINTER (arg_num_value.u.value.value); + + if (unlikely (ecma_number_is_nan (arg_num))) + { + ret_num = arg_num; + is_just_convert = true; + } + else if (ecma_number_is_zero (arg_num) /* both numbers are zeroes */ + && ecma_number_is_zero (ret_num)) + { + if (ecma_number_is_negative (arg_num)) + { + ret_num = arg_num; + } + } + else if (ecma_number_is_infinity (arg_num)) + { + if (ecma_number_is_negative (arg_num)) + { + ret_num = arg_num; + is_just_convert = true; + } + } + else if (ecma_number_is_infinity (ret_num)) /* ret_num is positive infinity */ + { + JERRY_ASSERT (!ecma_number_is_negative (ret_num)); + + ret_num = arg_num; + } + else + { + JERRY_ASSERT (!ecma_number_is_nan (arg_num) + && !ecma_number_is_infinity (arg_num)); + JERRY_ASSERT (!ecma_number_is_nan (ret_num) + && !ecma_number_is_infinity (ret_num)); + + if (arg_num < ret_num) + { + ret_num = arg_num; + } + } + } + + ECMA_FINALIZE (arg_num_value); + + if (ecma_is_completion_value_throw (ret_value)) + { + return ret_value; + } + + JERRY_ASSERT (ecma_is_completion_value_empty (ret_value)); + } + + JERRY_ASSERT (ecma_is_completion_value_empty (ret_value)); + + ecma_number_t *num_p = ecma_alloc_number (); + *num_p = ret_num; + + return ecma_make_return_completion_value (ecma_make_number_value (num_p)); } /* ecma_builtin_math_object_min */ /** diff --git a/tests/jerry/math_max.js b/tests/jerry/math_max.js new file mode 100644 index 000000000..243f60cf7 --- /dev/null +++ b/tests/jerry/math_max.js @@ -0,0 +1,31 @@ +// 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. + +assert(isNaN (Math['max'] (1.0, NaN))); +assert(isNaN (Math['max'] (NaN, 1.0))); +assert(Math['max'] (1.0, 3.0, 0.0) === 3.0); +assert(Math['max'] (1.0, 3.0, Infinity) === Infinity); +assert(Math['max'] (1.0, 3.0, -Infinity) === 3.0); +assert(Math['max'] (-Infinity, Infinity) === Infinity); +assert(Math['max'] (Infinity, -Infinity) === Infinity); +assert(Math['max'] (Infinity, Infinity) === Infinity); +assert(Math['max'] (-Infinity, -Infinity) === -Infinity); +assert(Math['max'] () === -Infinity); + +/* + FIXME: Uncomment when unary minus support appears. + +assert(Math['max'] (0.0, -0.0) === 0.0); +assert(Math['max'] (-0.0, 0.0) === 0.0); +*/ diff --git a/tests/jerry/math_min.js b/tests/jerry/math_min.js new file mode 100644 index 000000000..f81d98f46 --- /dev/null +++ b/tests/jerry/math_min.js @@ -0,0 +1,31 @@ +// 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. + +assert(isNaN (Math['min'] (1.0, NaN))); +assert(isNaN (Math['min'] (NaN, 1.0))); +assert(Math['min'] (1.0, 3.0, 0.0) === 0.0); +assert(Math['min'] (1.0, 3.0, Infinity) === 1.0); +assert(Math['min'] (1.0, 3.0, -Infinity) === -Infinity); +assert(Math['min'] (-Infinity, Infinity) === -Infinity); +assert(Math['min'] (Infinity, -Infinity) === -Infinity); +assert(Math['min'] (Infinity, Infinity) === Infinity); +assert(Math['min'] (-Infinity, -Infinity) === -Infinity); +assert(Math['min'] () === Infinity); + +/* + FIXME: Uncomment when unary minus support appears. + +assert(Math['min'] (0.0, -0.0) === -0.0); +assert(Math['min'] (-0.0, 0.0) === -0.0); +*/