[njs] Fixed njs_number_to_int32() for big-endian platforms.

Dmitry Volyntsev xeioex at nginx.com
Tue Jul 14 13:16:52 UTC 2020


details:   https://hg.nginx.org/njs/rev/c1f74ea54f89
branches:  
changeset: 1465:c1f74ea54f89
user:      Dmitry Volyntsev <xeioex at nginx.com>
date:      Tue Jul 14 13:16:05 2020 +0000
description:
Fixed njs_number_to_int32() for big-endian platforms.

This is related to #326 issue in Github.

diffstat:

 auto/clang       |  17 -------------
 src/njs_number.h |  73 ++++++++++++++++++++++++++++---------------------------
 2 files changed, 37 insertions(+), 53 deletions(-)

diffs (135 lines):

diff -r 022995046310 -r c1f74ea54f89 auto/clang
--- a/auto/clang	Tue Jul 14 14:49:46 2020 +0300
+++ b/auto/clang	Tue Jul 14 13:16:05 2020 +0000
@@ -162,23 +162,6 @@ njs_feature_test="#include <sanitizer/ms
 . auto/feature
 
 
-njs_feature="NAN to uint conversion"
-njs_feature_name=NJS_NAN_TO_UINT_CONVERSION
-njs_feature_run=value
-njs_feature_incs=
-njs_feature_libs=-lm
-njs_feature_test="#include <math.h>
-                  #include <stdio.h>
-                  #include <stdint.h>
-
-                  int main(void) {
-                      int64_t  i64 = acosh(0);
-                      printf(\"%x\", (uint32_t) i64);
-                      return 0;
-                  }"
-. auto/feature
-
-
 njs_feature="_mm_setcsr()"
 njs_feature_name=NJS_HAVE_DENORMALS_CONTROL
 njs_feature_run=no
diff -r 022995046310 -r c1f74ea54f89 src/njs_number.h
--- a/src/njs_number.h	Tue Jul 14 14:49:46 2020 +0300
+++ b/src/njs_number.h	Tue Jul 14 13:16:05 2020 +0000
@@ -52,38 +52,6 @@ njs_key_is_integer_index(double num, con
 
 
 njs_inline int64_t
-njs_number_to_int64(double num)
-{
-#if (NJS_NAN_TO_UINT_CONVERSION != 0)
-    /*
-     * PPC32: NaN and Inf are converted to 0x8000000080000000
-     * and become non-zero after truncation.
-     */
-
-    if (isnan(num) || isinf(num)) {
-        return 0;
-    }
-#endif
-
-    /*
-     * ES5.1: integer must be modulo 2^32.
-     * 2^53 is the largest integer number which can be stored safely
-     * 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 is
-     * converted to 0x8000000000000000 and becomes 0 after truncation.
-     * fmod() of the Infinity returns NaN.
-     */
-
-    if (fabs(num) > 9007199254740992.0) {
-        return (int64_t) fmod(num, 4294967296.0);
-    }
-
-    return (int64_t) num;
-}
-
-
-njs_inline int64_t
 njs_number_to_integer(double num)
 {
     if (njs_slow_path(isinf(num))) {
@@ -97,28 +65,61 @@ njs_number_to_integer(double num)
         return 0;
     }
 
-    return njs_number_to_int64(num);
+    return trunc(num) + 0.0;
 }
 
 
 njs_inline int32_t
 njs_number_to_int32(double num)
 {
-    return (int32_t) njs_number_to_int64(num);
+    int32_t           r;
+    uint64_t          v;
+    njs_int_t         exp;
+    njs_diyfp_conv_t  conv;
+
+    conv.d = num;
+
+    exp = (conv.u64 & NJS_DBL_EXPONENT_MASK) >> NJS_DBL_SIGNIFICAND_SIZE;
+
+    if (njs_fast_path(exp < (NJS_DBL_EXPONENT_OFFSET + 30))) {
+        /* |num| < 2**31. */
+        return num;
+    }
+
+    if (exp < (NJS_DBL_EXPONENT_OFFSET + 30 + 53)) {
+        v = (conv.u64 & NJS_DBL_SIGNIFICAND_MASK) | NJS_DBL_HIDDEN_BIT;
+        v <<= (exp - NJS_DBL_EXPONENT_BIAS + 32);
+        r = v >> 32;
+
+        if (conv.u64 & NJS_DBL_SIGN_MASK) {
+            r = -r;
+        }
+
+        return r;
+    }
+
+    /*
+     * ES5.1: integer must be modulo 2^32.
+     * The distance between larger doubles
+     * (exp >= NJS_DBL_EXPONENT_OFFSET + 30 + 53) is a multiple of 2**32 => 0.
+     * This also handles NaN and Inf.
+     */
+
+    return 0;
 }
 
 
 njs_inline uint32_t
 njs_number_to_uint32(double num)
 {
-    return (uint32_t) njs_number_to_int64(num);
+    return (uint32_t) njs_number_to_int32(num);
 }
 
 
 njs_inline uint16_t
 njs_number_to_uint16(double num)
 {
-    return (uint16_t) njs_number_to_int64(num);
+    return (uint16_t) njs_number_to_int32(num);
 }
 
 


More information about the nginx-devel mailing list