[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