Skip to content

Commit 48d7d04

Browse files
Fix of ToUInt32 (ecma_number_to_uint32) and ToInt32 (ecma_number_to_int32) conversion routines.
Related issue: #160 JerryScript-DCO-1.0-Signed-off-by: Ruben Ayrapetyan [email protected]
1 parent 1a3940c commit 48d7d04

File tree

2 files changed

+176
-14
lines changed

2 files changed

+176
-14
lines changed

jerry-core/ecma/base/ecma-helpers-conversion.cpp

Lines changed: 77 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -823,24 +823,70 @@ ecma_int32_to_number (int32_t value) /**< signed 32-bit integer value */
823823
} /* ecma_int32_to_number */
824824

825825
/**
826-
* ECMA-defined conversion of Number value to Uint32 value
826+
* ECMA-defined conversion of Number value to UInt32 value
827827
*
828828
* See also:
829829
* ECMA-262 v5, 9.6
830830
*
831-
* @return number - result of conversion.
831+
* @return 32-bit unsigned integer - result of conversion.
832832
*/
833833
uint32_t
834-
ecma_number_to_uint32 (ecma_number_t value) /**< unsigned 32-bit integer value */
834+
ecma_number_to_uint32 (ecma_number_t num) /**< ecma-number */
835835
{
836-
if (ecma_number_is_nan (value)
837-
|| ecma_number_is_zero (value)
838-
|| ecma_number_is_infinity (value))
836+
if (ecma_number_is_nan (num)
837+
|| ecma_number_is_zero (num)
838+
|| ecma_number_is_infinity (num))
839839
{
840840
return 0;
841841
}
842842

843-
return (uint32_t) value;
843+
bool sign = ecma_number_is_negative (num);
844+
ecma_number_t abs_num;
845+
846+
if (sign)
847+
{
848+
abs_num = ecma_number_negate (num);
849+
}
850+
else
851+
{
852+
abs_num = num;
853+
}
854+
855+
// 2 ^ 32
856+
const uint64_t uint64_2_pow_32 = (1ull << 32);
857+
858+
const ecma_number_t num_2_pow_32 = (float) uint64_2_pow_32;
859+
860+
ecma_number_t num_in_uint32_range;
861+
862+
if (abs_num >= num_2_pow_32)
863+
{
864+
num_in_uint32_range = ecma_number_calc_remainder (abs_num,
865+
num_2_pow_32);
866+
}
867+
else
868+
{
869+
num_in_uint32_range = abs_num;
870+
}
871+
872+
uint64_t uint64_num = (uint64_t) num_in_uint32_range;
873+
874+
uint64_t ret;
875+
876+
if (sign
877+
&& uint64_num != 0)
878+
{
879+
ret = uint64_2_pow_32 - uint64_num;
880+
}
881+
else
882+
{
883+
ret = uint64_num;
884+
}
885+
886+
// Check that the value can be represented with uint32_t
887+
JERRY_ASSERT (ret < (1ull << 32));
888+
889+
return (uint32_t) ret;
844890
} /* ecma_number_to_uint32 */
845891

846892
/**
@@ -849,19 +895,36 @@ ecma_number_to_uint32 (ecma_number_t value) /**< unsigned 32-bit integer value *
849895
* See also:
850896
* ECMA-262 v5, 9.5
851897
*
852-
* @return number - result of conversion.
898+
* @return 32-bit signed integer - result of conversion.
853899
*/
854900
int32_t
855-
ecma_number_to_int32 (ecma_number_t value) /**< unsigned 32-bit integer value */
901+
ecma_number_to_int32 (ecma_number_t num) /**< ecma-number */
856902
{
857-
if (ecma_number_is_nan (value)
858-
|| ecma_number_is_zero (value)
859-
|| ecma_number_is_infinity (value))
903+
int64_t int64_num = ecma_number_to_uint32 (num);
904+
905+
// 2 ^ 32
906+
const int64_t int64_2_pow_32 = (1ll << 32);
907+
908+
// 2 ^ 31
909+
const int64_t int64_2_pow_31 = (1ll << 31);
910+
911+
JERRY_ASSERT (int64_num >= 0);
912+
913+
int64_t ret;
914+
915+
if (int64_num >= int64_2_pow_31)
860916
{
861-
return 0;
917+
ret = (int64_num - int64_2_pow_32);
862918
}
919+
else
920+
{
921+
ret = int64_num;
922+
}
923+
924+
// Check that the value can be represented with int32_t
925+
JERRY_ASSERT (ret >= -int64_2_pow_31 && ret < int64_2_pow_31);
863926

864-
return (int32_t) (uint32_t) value;
927+
return (int32_t) ret;
865928
} /* ecma_number_to_int32 */
866929

867930
#if CONFIG_ECMA_NUMBER_TYPE == CONFIG_ECMA_NUMBER_FLOAT64

tests/unit/test-number-to-integer.cpp

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
/* Copyright 2015 Samsung Electronics Co., Ltd.
2+
*
3+
* Licensed under the Apache License, Version 2.0 (the "License");
4+
* you may not use this file except in compliance with the License.
5+
* You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software
10+
* distributed under the License is distributed on an "AS IS" BASIS
11+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
* See the License for the specific language governing permissions and
13+
* limitations under the License.
14+
*/
15+
16+
#include "ecma-globals.h"
17+
#include "ecma-helpers.h"
18+
19+
#include "test-common.h"
20+
21+
/**
22+
* Unit test's main function.
23+
*/
24+
int
25+
main (int __attr_unused___ argc,
26+
char __attr_unused___ **argv)
27+
{
28+
TEST_INIT ();
29+
30+
const struct
31+
{
32+
ecma_number_t num;
33+
uint32_t uint32_num;
34+
} test_cases_uint32 [] = {
35+
{ 1.0, 1 },
36+
{ 0.0, 0 },
37+
{ ecma_number_negate (0.0), 0 },
38+
{ NAN, 0 },
39+
{ -NAN, 0 },
40+
{ INFINITY, 0 },
41+
{ -INFINITY, 0 },
42+
{ 0.1, 0 },
43+
{ -0.1, 0 },
44+
{ 1.1, 1 },
45+
{ -1.1, 4294967295 },
46+
{ 4294967295, 4294967295 },
47+
{ -4294967295, 1 },
48+
{ 4294967296, 0 },
49+
{ -4294967296, 0 },
50+
{ 4294967297, 1 },
51+
{ -4294967297, 4294967295 }
52+
};
53+
54+
for (uint32_t i = 0;
55+
i < sizeof (test_cases_uint32) / sizeof (test_cases_uint32[0]);
56+
i++)
57+
{
58+
JERRY_ASSERT (ecma_number_to_uint32 (test_cases_uint32[i].num) == test_cases_uint32[i].uint32_num);
59+
}
60+
61+
const struct
62+
{
63+
ecma_number_t num;
64+
int32_t int32_num;
65+
} test_cases_int32 [] = {
66+
{ 1.0, 1 },
67+
{ 0.0, 0 },
68+
{ ecma_number_negate (0.0), 0 },
69+
{ NAN, 0 },
70+
{ -NAN, 0 },
71+
{ INFINITY, 0 },
72+
{ -INFINITY, 0 },
73+
{ 0.1, 0 },
74+
{ -0.1, 0 },
75+
{ 1.1, 1 },
76+
{ -1.1, -1 },
77+
{ 4294967295, -1 },
78+
{ -4294967295, 1 },
79+
{ 4294967296, 0 },
80+
{ -4294967296, 0 },
81+
{ 4294967297, 1 },
82+
{ -4294967297, -1 },
83+
{ 2147483648, -2147483648 },
84+
{ -2147483648, -2147483648 },
85+
{ 2147483647, 2147483647 },
86+
{ -2147483647, -2147483647 },
87+
{ -2147483649, 2147483647 },
88+
{ 2147483649, -2147483647 }
89+
};
90+
91+
for (uint32_t i = 0;
92+
i < sizeof (test_cases_int32) / sizeof (test_cases_int32[0]);
93+
i++)
94+
{
95+
JERRY_ASSERT (ecma_number_to_int32 (test_cases_int32[i].num) == test_cases_int32[i].int32_num);
96+
}
97+
98+
return 0;
99+
} /* main */

0 commit comments

Comments
 (0)