From: Valentin Bartenev Date: Sat, 19 Nov 2016 19:20:06 +0000 (+0300) Subject: Math.imul() method. X-Git-Tag: 0.1.6~18 X-Git-Url: http://git.kaiwu.me/postgresql/log/contrib/postgres_fdw/static/gitweb.js?a=commitdiff_plain;h=06591a3a7f05526db3e14e6698c2fd4611176179;p=njs.git Math.imul() method. --- diff --git a/njs/njs_math.c b/njs/njs_math.c index f20f5fee..0a7d7d24 100644 --- a/njs/njs_math.c +++ b/njs/njs_math.c @@ -377,6 +377,29 @@ njs_object_math_hypot(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs, } +static njs_ret_t +njs_object_math_imul(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs, + njs_index_t unused) +{ + double num; + uint32_t a, b; + + if (nargs > 2) { + a = njs_number_to_integer(args[1].data.u.number); + b = njs_number_to_integer(args[2].data.u.number); + + num = (int32_t) (a * b); + + } else { + num = 0; + } + + njs_number_set(&vm->retval, num); + + return NXT_OK; +} + + static njs_ret_t njs_object_math_log(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs, njs_index_t unused) @@ -898,6 +921,14 @@ static const njs_object_prop_t njs_math_object_properties[] = .value = njs_native_function(njs_object_math_hypot, 0, 0), }, + /* ES6. */ + { + .type = NJS_METHOD, + .name = njs_string("imul"), + .value = njs_native_function(njs_object_math_imul, 0, + NJS_SKIP_ARG, NJS_NUMBER_ARG, NJS_NUMBER_ARG), + }, + { .type = NJS_METHOD, .name = njs_string("log"), diff --git a/njs/njs_number.c b/njs/njs_number.c index 2b9e1501..1e01a845 100644 --- a/njs/njs_number.c +++ b/njs/njs_number.c @@ -741,3 +741,28 @@ njs_number_parse_float(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs, return NXT_OK; } + + +nxt_noinline uint32_t +njs_number_to_integer(double num) +{ + int64_t i64; + + /* + * ECMAScript 5.1: integer must be modulo 2^32. + * 2^53 is the largest integer number which can be stored in the IEEE-754 + * format and numbers less than 2^53 can be just converted to int64_t + * eliding more expensive fmod() operation. Then the int64 integer is + * truncated to uint32_t. The NaN can be converted to 0x8000000000000000 + * and becomes 0 after truncation. fmod() of the infinity returns NaN. + */ + + if (num < 0 || num > 9007199254740992.0) { + i64 = fmod(num, 4294967296.0); + + } else { + i64 = num; + } + + return (uint32_t) i64; +} diff --git a/njs/njs_number.h b/njs/njs_number.h index 724dfbbe..4365065d 100644 --- a/njs/njs_number.h +++ b/njs/njs_number.h @@ -27,6 +27,7 @@ njs_ret_t njs_number_parse_int(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs, njs_index_t unused); njs_ret_t njs_number_parse_float(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs, njs_index_t unused); +nxt_noinline uint32_t njs_number_to_integer(double num); extern const njs_object_init_t njs_number_constructor_init; diff --git a/njs/njs_vm.c b/njs/njs_vm.c index ee86bf4d..e1a0557d 100644 --- a/njs/njs_vm.c +++ b/njs/njs_vm.c @@ -78,7 +78,6 @@ static njs_ret_t njs_object_property_query(njs_vm_t *vm, njs_property_query_t *pq, njs_value_t *value, njs_object_t *object); static njs_ret_t njs_method_private_copy(njs_vm_t *vm, njs_property_query_t *pq); -static nxt_noinline uint32_t njs_integer_value(double num); static nxt_noinline njs_ret_t njs_values_equal(const njs_value_t *val1, const njs_value_t *val2); static nxt_noinline njs_ret_t njs_values_compare(const njs_value_t *val1, @@ -1639,8 +1638,8 @@ njs_vmcode_left_shift(njs_vm_t *vm, njs_value_t *val1, njs_value_t *val2) if (nxt_fast_path(njs_is_numeric(val1) && njs_is_numeric(val2))) { - num1 = njs_integer_value(val1->data.u.number); - num2 = njs_integer_value(val2->data.u.number); + num1 = njs_number_to_integer(val1->data.u.number); + num2 = njs_number_to_integer(val2->data.u.number); njs_number_set(&vm->retval, num1 << (num2 & 0x1f)); return sizeof(njs_vmcode_3addr_t); @@ -1658,8 +1657,8 @@ njs_vmcode_right_shift(njs_vm_t *vm, njs_value_t *val1, njs_value_t *val2) if (nxt_fast_path(njs_is_numeric(val1) && njs_is_numeric(val2))) { - num1 = njs_integer_value(val1->data.u.number); - num2 = njs_integer_value(val2->data.u.number); + num1 = njs_number_to_integer(val1->data.u.number); + num2 = njs_number_to_integer(val2->data.u.number); njs_number_set(&vm->retval, num1 >> (num2 & 0x1f)); return sizeof(njs_vmcode_3addr_t); @@ -1678,8 +1677,8 @@ njs_vmcode_unsigned_right_shift(njs_vm_t *vm, njs_value_t *val1, if (nxt_fast_path(njs_is_numeric(val1) && njs_is_numeric(val2))) { - num1 = njs_integer_value(val1->data.u.number); - num2 = njs_integer_value(val2->data.u.number); + num1 = njs_number_to_integer(val1->data.u.number); + num2 = njs_number_to_integer(val2->data.u.number); njs_number_set(&vm->retval, num1 >> (num2 & 0x1f)); return sizeof(njs_vmcode_3addr_t); @@ -1745,7 +1744,7 @@ njs_vmcode_bitwise_not(njs_vm_t *vm, njs_value_t *value, njs_value_t *invld) int32_t num; if (nxt_fast_path(njs_is_numeric(value))) { - num = njs_integer_value(value->data.u.number); + num = njs_number_to_integer(value->data.u.number); njs_number_set(&vm->retval, ~num); return sizeof(njs_vmcode_2addr_t); @@ -1762,8 +1761,8 @@ njs_vmcode_bitwise_and(njs_vm_t *vm, njs_value_t *val1, njs_value_t *val2) if (nxt_fast_path(njs_is_numeric(val1) && njs_is_numeric(val2))) { - num1 = njs_integer_value(val1->data.u.number); - num2 = njs_integer_value(val2->data.u.number); + num1 = njs_number_to_integer(val1->data.u.number); + num2 = njs_number_to_integer(val2->data.u.number); njs_number_set(&vm->retval, num1 & num2); return sizeof(njs_vmcode_3addr_t); @@ -1780,8 +1779,8 @@ njs_vmcode_bitwise_xor(njs_vm_t *vm, njs_value_t *val1, njs_value_t *val2) if (nxt_fast_path(njs_is_numeric(val1) && njs_is_numeric(val2))) { - num1 = njs_integer_value(val1->data.u.number); - num2 = njs_integer_value(val2->data.u.number); + num1 = njs_number_to_integer(val1->data.u.number); + num2 = njs_number_to_integer(val2->data.u.number); njs_number_set(&vm->retval, num1 ^ num2); return sizeof(njs_vmcode_3addr_t); @@ -1798,8 +1797,8 @@ njs_vmcode_bitwise_or(njs_vm_t *vm, njs_value_t *val1, njs_value_t *val2) if (nxt_fast_path(njs_is_numeric(val1) && njs_is_numeric(val2))) { - num1 = njs_integer_value(val1->data.u.number); - num2 = njs_integer_value(val2->data.u.number); + num1 = njs_number_to_integer(val1->data.u.number); + num2 = njs_number_to_integer(val2->data.u.number); njs_number_set(&vm->retval, num1 | num2); return sizeof(njs_vmcode_3addr_t); @@ -1809,31 +1808,6 @@ njs_vmcode_bitwise_or(njs_vm_t *vm, njs_value_t *val1, njs_value_t *val2) } -static nxt_noinline uint32_t -njs_integer_value(double num) -{ - int64_t i64; - - /* - * ECMAScript 5.1: integer must be modulo 2^32. - * 2^53 is the largest integer number which can be stored in the IEEE-754 - * format and numbers less than 2^53 can be just converted to int64_t - * eliding more expensive fmod() operation. Then the int64 integer is - * truncated to uint32_t. The NaN can be converted to 0x8000000000000000 - * and becomes 0 after truncation. fmod() of the infinity returns NaN. - */ - - if (num < 0 || num > 9007199254740992.0) { - i64 = fmod(num, 4294967296.0); - - } else { - i64 = num; - } - - return (uint32_t) i64; -} - - njs_ret_t njs_vmcode_equal(njs_vm_t *vm, njs_value_t *val1, njs_value_t *val2) { diff --git a/njs/test/njs_unit_test.c b/njs/test/njs_unit_test.c index d8c14013..2a5866e2 100644 --- a/njs/test/njs_unit_test.c +++ b/njs/test/njs_unit_test.c @@ -5968,6 +5968,63 @@ static njs_unit_test_t njs_test[] = { nxt_string("Math.hypot(3, -4, 12.0, '84', 132)"), nxt_string("157") }, + { nxt_string("Math.imul()"), + nxt_string("0") }, + + { nxt_string("Math.imul(1)"), + nxt_string("0") }, + + { nxt_string("Math.imul('a', 1)"), + nxt_string("0") }, + + { nxt_string("Math.imul(1, NaN)"), + nxt_string("0") }, + + { nxt_string("Math.imul(2, '3')"), + nxt_string("6") }, + + { nxt_string("Math.imul('3.9', -2.1)"), + nxt_string("-6") }, + + { nxt_string("Math.imul(2, 2147483647)"), + nxt_string("-2") }, + + { nxt_string("Math.imul(Number.MAX_SAFE_INTEGER, 2)"), + nxt_string("-2") }, + + { nxt_string("Math.imul(1, Number.MAX_SAFE_INTEGER + 1)"), + nxt_string("0") }, + + { nxt_string("Math.imul(2, Number.MIN_SAFE_INTEGER)"), + nxt_string("2") }, + + { nxt_string("Math.imul(Number.MIN_SAFE_INTEGER - 1, 1)"), + nxt_string("0") }, + + { nxt_string("Math.imul(2, 4294967297)"), + nxt_string("2") }, + + { nxt_string("Math.imul(-4294967297, 4294967297)"), + nxt_string("-1") }, + + { nxt_string("Math.imul(4294967297, -4294967298)"), + nxt_string("-2") }, + + { nxt_string("Math.imul(-4294967290, 4294967290)"), + nxt_string("-36") }, + + { nxt_string("Math.imul(-Infinity, 1)"), + nxt_string("0") }, + + { nxt_string("Math.imul(1, Infinity)"), + nxt_string("0") }, + + { nxt_string("Math.imul(Number.MAX_VALUE, 1)"), + nxt_string("0") }, + + { nxt_string("Math.imul(1, -Number.MAX_VALUE)"), + nxt_string("0") }, + { nxt_string("Math.log()"), nxt_string("NaN") },