Skip to content

Commit 5640279

Browse files
committed
Fixed floor division on mp ints and small ints. Added a floordivide test case.
1 parent cde8631 commit 5640279

5 files changed

Lines changed: 65 additions & 9 deletions

File tree

py/compile.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include <stdio.h>
44
#include <string.h>
55
#include <assert.h>
6+
#include <math.h>
67

78
#include "misc.h"
89
#include "mpconfig.h"
@@ -141,12 +142,13 @@ mp_parse_node_t fold_constants(mp_parse_node_t pn) {
141142
} else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_SLASH)) {
142143
; // pass
143144
} else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_PERCENT)) {
144-
// XXX implement this properly as Python's % operator acts differently to C's
145-
//pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, arg0 % arg1);
146145
pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, python_modulo(arg0, arg1));
147146
} else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_DBL_SLASH)) {
148-
// XXX implement this properly as Python's // operator acts differently to C's
149-
pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, arg0 / arg1);
147+
//pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT,
148+
// floor((mp_float_t)arg0 / arg1));
149+
pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT,
150+
python_floor_divide(arg0, arg1));
151+
150152
} else {
151153
// shouldn't happen
152154
assert(0);

py/objint_mpz.c

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#include <stdint.h>
22
#include <string.h>
3+
#include <stdio.h>
34

45
#include "nlr.h"
56
#include "misc.h"
@@ -97,6 +98,12 @@ mp_obj_t int_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
9798
case RT_BINARY_OP_INPLACE_FLOOR_DIVIDE: {
9899
mpz_t rem; mpz_init_zero(&rem);
99100
mpz_divmod_inpl(&res->mpz, &rem, zlhs, zrhs);
101+
if (zlhs->neg != zrhs->neg) {
102+
if (!mpz_is_zero(&rem)) {
103+
mpz_t mpzone; mpz_init_from_int(&mpzone, -1);
104+
mpz_add_inpl(&res->mpz, &res->mpz, &mpzone);
105+
}
106+
}
100107
mpz_deinit(&rem);
101108
break;
102109
}
@@ -105,8 +112,8 @@ mp_obj_t int_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
105112
mpz_t quo; mpz_init_zero(&quo);
106113
mpz_divmod_inpl(&quo, &res->mpz, zlhs, zrhs);
107114
mpz_deinit(&quo);
108-
// Check signs and do Python style modulo
109-
if (zlhs->neg != zrhs->neg) {
115+
// Check signs and do Python style modulo
116+
if (zlhs->neg != zrhs->neg) {
110117
mpz_add_inpl(&res->mpz, &res->mpz, zrhs);
111118
}
112119
break;

py/runtime.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include <stdio.h>
66
#include <string.h>
77
#include <assert.h>
8+
#include <math.h>
89

910
#include "nlr.h"
1011
#include "misc.h"
@@ -661,7 +662,11 @@ mp_obj_t rt_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) {
661662
break;
662663
}
663664
case RT_BINARY_OP_FLOOR_DIVIDE:
664-
case RT_BINARY_OP_INPLACE_FLOOR_DIVIDE: lhs_val /= rhs_val; break;
665+
case RT_BINARY_OP_INPLACE_FLOOR_DIVIDE:
666+
{
667+
lhs_val = python_floor_divide(lhs_val, rhs_val);
668+
break;
669+
}
665670
#if MICROPY_ENABLE_FLOAT
666671
case RT_BINARY_OP_TRUE_DIVIDE:
667672
case RT_BINARY_OP_INPLACE_TRUE_DIVIDE: return mp_obj_new_float((mp_float_t)lhs_val / (mp_float_t)rhs_val);

tests/basics/floordivide.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# check modulo matches python definition
2+
3+
# This tests compiler version
4+
print(123 // 7)
5+
print(-123 // 7)
6+
print(123 // -7)
7+
print(-123 // -7)
8+
9+
a = 10000001
10+
b = 10000000
11+
print(a // b)
12+
print(a // -b)
13+
print(-a // b)
14+
print(-a // -b)
15+
16+
if True:
17+
a = 987654321987987987987987987987
18+
b = 19
19+
20+
print(a // b)
21+
print(a // -b)
22+
print(-a // b)
23+
print(-a // -b)
24+
a = 10000000000000000000000000000000000000000000
25+
b = 100
26+
print(a // b)
27+
print(a // -b)
28+
print(-a // b)
29+
print(-a // -b)

tests/basics/modulo.py

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
11
# check modulo matches python definition
2-
2+
# This test compiler version
33
print(123 % 7)
44
print(-123 % 7)
55
print(123 % -7)
66
print(-123 % -7)
77

88
a = 321
99
b = 19
10-
1110
print(a % b)
1211
print(a % -b)
1312
print(-a % b)
@@ -21,3 +20,17 @@
2120
print(a % -b)
2221
print(-a % b)
2322
print(-a % -b)
23+
24+
if False:
25+
print(1.23456 % 0.7)
26+
print(-1.23456 % 0.7)
27+
print(1.23456 % -0.7)
28+
print(-1.23456 % -0.7)
29+
30+
a = 1.23456
31+
b = 0.7
32+
print(a % b)
33+
print(a % -b)
34+
print(-a % b)
35+
print(-a % -b)
36+

0 commit comments

Comments
 (0)