From: Dmitry Volyntsev Date: Mon, 24 May 2021 14:18:15 +0000 (+0000) Subject: Fixed ToInt32() with values >= 2**(53+30). X-Git-Tag: 0.6.0~18 X-Git-Url: http://www.kaiwu.me/postgresql/commit/static/gitweb.js?a=commitdiff_plain;h=72ff5c29a86cdb6ba73f1bd66e450a81ffe59198;p=njs.git Fixed ToInt32() with values >= 2**(53+30). --- diff --git a/src/njs_number.h b/src/njs_number.h index 53800cda..9d97c8db 100644 --- a/src/njs_number.h +++ b/src/njs_number.h @@ -85,12 +85,12 @@ njs_number_to_int32(double num) exp = (conv.u64 & NJS_DBL_EXPONENT_MASK) >> NJS_DBL_SIGNIFICAND_SIZE; - if (njs_fast_path(exp < (NJS_DBL_EXPONENT_OFFSET + 30))) { + if (njs_fast_path(exp < (NJS_DBL_EXPONENT_OFFSET + 31))) { /* |num| < 2**31. */ return num; } - if (exp < (NJS_DBL_EXPONENT_OFFSET + 30 + 53)) { + if (exp < (NJS_DBL_EXPONENT_OFFSET + 31 + 53)) { v = (conv.u64 & NJS_DBL_SIGNIFICAND_MASK) | NJS_DBL_HIDDEN_BIT; v <<= (exp - NJS_DBL_EXPONENT_BIAS + 32); r = v >> 32; @@ -105,7 +105,7 @@ njs_number_to_int32(double num) /* * 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. + * (exp >= NJS_DBL_EXPONENT_OFFSET + 31 + 53) is a multiple of 2**32 => 0. * This also handles NaN and Inf. */ diff --git a/src/test/njs_unit_test.c b/src/test/njs_unit_test.c index 08612dad..e610d7e7 100644 --- a/src/test/njs_unit_test.c +++ b/src/test/njs_unit_test.c @@ -22303,6 +22303,69 @@ njs_string_to_index_test(njs_vm_t *vm, njs_opts_t *opts, njs_stat_t *stat) } +static njs_int_t +njs_to_int32_test(njs_vm_t *vm, njs_opts_t *opts, njs_stat_t *stat) +{ + int32_t i32, second; + njs_uint_t i; + + static const struct { + double value; + int32_t expected; + } tests[] = { + { -1.0, -1 }, + { 0.0, 0 }, + { 0.001, 0 }, + { 1.0, 1 }, + { 2147483647.0, 2147483647 }, + { 2147483648.0, -2147483648 }, + { 2147483649.0, -2147483647 }, + { -1844674406941458432.0, -2147483648 }, + { 4.835703278458518e+24 /* 2**(53+29) + 2**30 */, 1073741824 }, + { 9.671406556917036e+24 /* 2**(53+30) + 2**31 */, -2147483648 }, + }; + + for (i = 0; i < njs_nitems(tests); i++) { + i32 = njs_number_to_int32(tests[i].value); + + if (i32 != tests[i].expected) { + njs_printf("njs_to_int32_test(%f):\n" + "expected: %D\n got: %D\n", + tests[i].value, tests[i].expected, i32); + + stat->failed++; + continue; + } + + second = njs_number_to_int32(i32); + + if (i32 != second) { + njs_printf("njs_to_int32_test(%f): not idempodent\n" + "expected: %D\n got: %D\n", + tests[i].value, i32, second); + + stat->failed++; + continue; + } + + second = njs_number_to_int32(njs_number_to_uint32(tests[i].value)); + + if (i32 != second) { + njs_printf("ToInt32(%f) != ToInt32(ToUint32(%f))\n" + "left: %D\n right: %D\n", + tests[i].value, tests[i].value, i32, second); + + stat->failed++; + continue; + } + + stat->passed++; + } + + return NJS_OK; +} + + static njs_int_t njs_vm_internal_api_test(njs_unit_test_t unused[], size_t num, njs_str_t *name, njs_opts_t *opts, njs_stat_t *stat) @@ -22329,6 +22392,8 @@ njs_vm_internal_api_test(njs_unit_test_t unused[], size_t num, njs_str_t *name, njs_str("njs_sort_test") }, { njs_string_to_index_test, njs_str("njs_string_to_index_test") }, + { njs_to_int32_test, + njs_str("njs_to_int32_test") }, }; vm = NULL;