[njs] Math.imul() method.
Valentin Bartenev
vbart at nginx.com
Sat Nov 19 19:18:03 UTC 2016
details: http://hg.nginx.org/njs/rev/91dc07616b19
branches:
changeset: 264:91dc07616b19
user: Valentin Bartenev <vbart at nginx.com>
date: Sat Nov 19 22:20:06 2016 +0300
description:
Math.imul() method.
diffstat:
njs/njs_math.c | 31 ++++++++++++++++++++++++++
njs/njs_number.c | 25 +++++++++++++++++++++
njs/njs_number.h | 1 +
njs/njs_vm.c | 52 ++++++++++--------------------------------
njs/test/njs_unit_test.c | 57 ++++++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 127 insertions(+), 39 deletions(-)
diffs (276 lines):
diff -r f06c2b48ff78 -r 91dc07616b19 njs/njs_math.c
--- a/njs/njs_math.c Fri Nov 18 17:25:45 2016 +0300
+++ b/njs/njs_math.c Sat Nov 19 22:20:06 2016 +0300
@@ -378,6 +378,29 @@ njs_object_math_hypot(njs_vm_t *vm, njs_
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
.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 -r f06c2b48ff78 -r 91dc07616b19 njs/njs_number.c
--- a/njs/njs_number.c Fri Nov 18 17:25:45 2016 +0300
+++ b/njs/njs_number.c Sat Nov 19 22:20:06 2016 +0300
@@ -741,3 +741,28 @@ njs_number_parse_float(njs_vm_t *vm, njs
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 -r f06c2b48ff78 -r 91dc07616b19 njs/njs_number.h
--- a/njs/njs_number.h Fri Nov 18 17:25:45 2016 +0300
+++ b/njs/njs_number.h Sat Nov 19 22:20:06 2016 +0300
@@ -27,6 +27,7 @@ njs_ret_t njs_number_parse_int(njs_vm_t
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 -r f06c2b48ff78 -r 91dc07616b19 njs/njs_vm.c
--- a/njs/njs_vm.c Fri Nov 18 17:25:45 2016 +0300
+++ b/njs/njs_vm.c Sat Nov 19 22:20:06 2016 +0300
@@ -78,7 +78,6 @@ static njs_ret_t njs_object_property_que
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_
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
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
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
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
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
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_
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_
}
-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 -r f06c2b48ff78 -r 91dc07616b19 njs/test/njs_unit_test.c
--- a/njs/test/njs_unit_test.c Fri Nov 18 17:25:45 2016 +0300
+++ b/njs/test/njs_unit_test.c Sat Nov 19 22:20:06 2016 +0300
@@ -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") },
More information about the nginx-devel
mailing list