Skip to content

Commit ad2307c

Browse files
committed
py: Temporary fix for conversion of float to int when fits in small int.
Addresses issue adafruit#1044 (see also adafruit#1040). Could do with a better fix.
1 parent d8bfd77 commit ad2307c

4 files changed

Lines changed: 35 additions & 8 deletions

File tree

py/objint_mpz.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,9 @@ mp_obj_t mp_obj_new_int_from_float(mp_float_t val) {
303303
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OverflowError, "can't convert inf to int"));
304304
} else if (cl == FP_NAN) {
305305
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "can't convert NaN to int"));
306+
} else if (MICROPY_FLOAT_C_FUN(fabs)(val) < 10000) {
307+
// temporary(?) fix for optimising case where int will be small int
308+
return MP_OBJ_NEW_SMALL_INT(MICROPY_FLOAT_C_FUN(trunc)(val));
306309
} else {
307310
mp_obj_int_t *o = mp_obj_int_new_mpz();
308311
mpz_set_from_float(&o->mpz, val);

tests/float/float2int.py

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,21 @@
1-
# This case occurs with time.time() values
2-
print(int(1418774543.))
1+
# check cases converting float to int, relying only on single precision float
32

3+
print(int(14187745.))
44
print(int(2.**100))
5-
6-
print("%d" % 1418774543.)
7-
5+
print("%d" % 14187745.)
86
print("%d" % 2.**100)
97

108
testpass = True
11-
for i in range(0,1024):
9+
for i in range(0,128):
1210
bitcnt = len(bin(int(2.**i))) - 3;
1311
if i != bitcnt:
1412
print('fail: 2**%u was %u bits long' % (i, bitcnt));
1513
testpass = False
1614
print("power of 2 test: %s" % (testpass and 'passed' or 'failed'))
1715

16+
# TODO why does 10**12 fail this test for single precision float?
1817
testpass = True
19-
for i in range(0,23):
18+
for i in range(0,12):
2019
digcnt = len(str(int(10.**i))) - 1;
2120
if i != digcnt:
2221
print('fail: 10**%u was %u digits long' % (i, digcnt));
@@ -34,3 +33,7 @@
3433
int(float('nan'))
3534
except ValueError:
3635
print("ValueError")
36+
37+
# test numbers < 1 (this used to fail; see issue #1044)
38+
import struct
39+
struct.pack('I', int(1/2))
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# check cases converting float to int, requiring double precision float
2+
3+
# This case occurs with time.time() values
4+
print(int(1418774543.))
5+
print("%d" % 1418774543.)
6+
7+
testpass = True
8+
for i in range(0,1024):
9+
bitcnt = len(bin(int(2.**i))) - 3;
10+
if i != bitcnt:
11+
print('fail: 2**%u was %u bits long' % (i, bitcnt));
12+
testpass = False
13+
print("power of 2 test: %s" % (testpass and 'passed' or 'failed'))
14+
15+
testpass = True
16+
for i in range(0,23):
17+
digcnt = len(str(int(10.**i))) - 1;
18+
if i != digcnt:
19+
print('fail: 10**%u was %u digits long' % (i, digcnt));
20+
testpass = False
21+
print("power of 10 test: %s" % (testpass and 'passed' or 'failed'))

tests/run-tests

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ def run_tests(pyb, tests, args):
6565
# Some tests shouldn't be run on pyboard
6666
if pyb is not None:
6767
skip_tests.add('float/float_divmod.py') # tested by float/float_divmod_relaxed.py instead
68-
skip_tests.add('float/float2int.py') # requires double precision floating point to work
68+
skip_tests.add('float/float2int_doubleprec.py') # requires double precision floating point to work
6969

7070
# Some tests are known to fail on 64-bit machines
7171
if pyb is None and platform.architecture()[0] == '64bit':

0 commit comments

Comments
 (0)