Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
TASTE
uPython-mirror
Commits
c5029bcb
Commit
c5029bcb
authored
Jun 13, 2015
by
Damien George
Browse files
py: Add MP_BINARY_OP_DIVMOD to simplify and consolidate divmod builtin.
parent
6f495200
Changes
10
Hide whitespace changes
Inline
Side-by-side
py/bc0.h
View file @
c5029bcb
...
...
@@ -117,6 +117,6 @@
#define MP_BC_LOAD_FAST_MULTI (0xb0) // + N(16)
#define MP_BC_STORE_FAST_MULTI (0xc0) // + N(16)
#define MP_BC_UNARY_OP_MULTI (0xd0) // + op(6)
#define MP_BC_BINARY_OP_MULTI (0xd6) // + op(3
5
)
#define MP_BC_BINARY_OP_MULTI (0xd6) // + op(3
6
)
#endif // __MICROPY_INCLUDED_PY_BC0_H__
py/modbuiltins.c
View file @
c5029bcb
...
...
@@ -230,44 +230,7 @@ STATIC mp_obj_t mp_builtin_dir(mp_uint_t n_args, const mp_obj_t *args) {
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN
(
mp_builtin_dir_obj
,
0
,
1
,
mp_builtin_dir
);
STATIC
mp_obj_t
mp_builtin_divmod
(
mp_obj_t
o1_in
,
mp_obj_t
o2_in
)
{
// TODO handle big int
if
(
MP_OBJ_IS_SMALL_INT
(
o1_in
)
&&
MP_OBJ_IS_SMALL_INT
(
o2_in
))
{
mp_int_t
i1
=
MP_OBJ_SMALL_INT_VALUE
(
o1_in
);
mp_int_t
i2
=
MP_OBJ_SMALL_INT_VALUE
(
o2_in
);
if
(
i2
==
0
)
{
#if MICROPY_PY_BUILTINS_FLOAT
zero_division_error:
#endif
nlr_raise
(
mp_obj_new_exception_msg
(
&
mp_type_ZeroDivisionError
,
"division by zero"
));
}
mp_obj_t
args
[
2
];
args
[
0
]
=
MP_OBJ_NEW_SMALL_INT
(
mp_small_int_floor_divide
(
i1
,
i2
));
args
[
1
]
=
MP_OBJ_NEW_SMALL_INT
(
mp_small_int_modulo
(
i1
,
i2
));
return
mp_obj_new_tuple
(
2
,
args
);
#if MICROPY_PY_BUILTINS_FLOAT
}
else
if
(
MP_OBJ_IS_TYPE
(
o1_in
,
&
mp_type_float
)
||
MP_OBJ_IS_TYPE
(
o2_in
,
&
mp_type_float
))
{
mp_float_t
f1
=
mp_obj_get_float
(
o1_in
);
mp_float_t
f2
=
mp_obj_get_float
(
o2_in
);
if
(
f2
==
0
.
0
)
{
goto
zero_division_error
;
}
mp_obj_float_divmod
(
&
f1
,
&
f2
);
mp_obj_t
tuple
[
2
]
=
{
mp_obj_new_float
(
f1
),
mp_obj_new_float
(
f2
),
};
return
mp_obj_new_tuple
(
2
,
tuple
);
#endif
}
else
{
if
(
MICROPY_ERROR_REPORTING
==
MICROPY_ERROR_REPORTING_TERSE
)
{
nlr_raise
(
mp_obj_new_exception_msg
(
&
mp_type_TypeError
,
"unsupported operand type(s) for divmod()"
));
}
else
{
nlr_raise
(
mp_obj_new_exception_msg_varg
(
&
mp_type_TypeError
,
"unsupported operand type(s) for divmod(): '%s' and '%s'"
,
mp_obj_get_type_str
(
o1_in
),
mp_obj_get_type_str
(
o2_in
)));
}
}
return
mp_binary_op
(
MP_BINARY_OP_DIVMOD
,
o1_in
,
o2_in
);
}
MP_DEFINE_CONST_FUN_OBJ_2
(
mp_builtin_divmod_obj
,
mp_builtin_divmod
);
...
...
py/obj.h
View file @
c5029bcb
...
...
@@ -575,7 +575,6 @@ typedef struct _mp_obj_float_t {
}
mp_obj_float_t
;
mp_float_t
mp_obj_float_get
(
mp_obj_t
self_in
);
mp_obj_t
mp_obj_float_binary_op
(
mp_uint_t
op
,
mp_float_t
lhs_val
,
mp_obj_t
rhs
);
// can return MP_OBJ_NULL if op not supported
void
mp_obj_float_divmod
(
mp_float_t
*
x
,
mp_float_t
*
y
);
// complex
void
mp_obj_complex_get
(
mp_obj_t
self_in
,
mp_float_t
*
real
,
mp_float_t
*
imag
);
...
...
py/objfloat.c
View file @
c5029bcb
...
...
@@ -126,6 +126,41 @@ mp_float_t mp_obj_float_get(mp_obj_t self_in) {
return
self
->
value
;
}
STATIC
void
mp_obj_float_divmod
(
mp_float_t
*
x
,
mp_float_t
*
y
)
{
// logic here follows that of CPython
// https://docs.python.org/3/reference/expressions.html#binary-arithmetic-operations
// x == (x//y)*y + (x%y)
// divmod(x, y) == (x//y, x%y)
mp_float_t
mod
=
MICROPY_FLOAT_C_FUN
(
fmod
)(
*
x
,
*
y
);
mp_float_t
div
=
(
*
x
-
mod
)
/
*
y
;
// Python specs require that mod has same sign as second operand
if
(
mod
==
0
.
0
)
{
mod
=
MICROPY_FLOAT_C_FUN
(
copysign
)(
0
.
0
,
*
y
);
}
else
{
if
((
mod
<
0
.
0
)
!=
(
*
y
<
0
.
0
))
{
mod
+=
*
y
;
div
-=
1
.
0
;
}
}
mp_float_t
floordiv
;
if
(
div
==
0
.
0
)
{
// if division is zero, take the correct sign of zero
floordiv
=
MICROPY_FLOAT_C_FUN
(
copysign
)(
0
.
0
,
*
x
/
*
y
);
}
else
{
// Python specs require that x == (x//y)*y + (x%y)
floordiv
=
MICROPY_FLOAT_C_FUN
(
floor
)(
div
);
if
(
div
-
floordiv
>
0
.
5
)
{
floordiv
+=
1
.
0
;
}
}
// return results
*
x
=
floordiv
;
*
y
=
mod
;
}
mp_obj_t
mp_obj_float_binary_op
(
mp_uint_t
op
,
mp_float_t
lhs_val
,
mp_obj_t
rhs_in
)
{
mp_float_t
rhs_val
=
mp_obj_get_float
(
rhs_in
);
// can be any type, this function will convert to float (if possible)
switch
(
op
)
{
...
...
@@ -170,6 +205,17 @@ mp_obj_t mp_obj_float_binary_op(mp_uint_t op, mp_float_t lhs_val, mp_obj_t rhs_i
break
;
case
MP_BINARY_OP_POWER
:
case
MP_BINARY_OP_INPLACE_POWER
:
lhs_val
=
MICROPY_FLOAT_C_FUN
(
pow
)(
lhs_val
,
rhs_val
);
break
;
case
MP_BINARY_OP_DIVMOD
:
{
if
(
rhs_val
==
0
)
{
goto
zero_division_error
;
}
mp_obj_float_divmod
(
&
lhs_val
,
&
rhs_val
);
mp_obj_t
tuple
[
2
]
=
{
mp_obj_new_float
(
lhs_val
),
mp_obj_new_float
(
rhs_val
),
};
return
mp_obj_new_tuple
(
2
,
tuple
);
}
case
MP_BINARY_OP_LESS
:
return
MP_BOOL
(
lhs_val
<
rhs_val
);
case
MP_BINARY_OP_MORE
:
return
MP_BOOL
(
lhs_val
>
rhs_val
);
case
MP_BINARY_OP_EQUAL
:
return
MP_BOOL
(
lhs_val
==
rhs_val
);
...
...
@@ -182,39 +228,4 @@ mp_obj_t mp_obj_float_binary_op(mp_uint_t op, mp_float_t lhs_val, mp_obj_t rhs_i
return
mp_obj_new_float
(
lhs_val
);
}
void
mp_obj_float_divmod
(
mp_float_t
*
x
,
mp_float_t
*
y
)
{
// logic here follows that of CPython
// https://docs.python.org/3/reference/expressions.html#binary-arithmetic-operations
// x == (x//y)*y + (x%y)
// divmod(x, y) == (x//y, x%y)
mp_float_t
mod
=
MICROPY_FLOAT_C_FUN
(
fmod
)(
*
x
,
*
y
);
mp_float_t
div
=
(
*
x
-
mod
)
/
*
y
;
// Python specs require that mod has same sign as second operand
if
(
mod
==
0
.
0
)
{
mod
=
MICROPY_FLOAT_C_FUN
(
copysign
)(
0
.
0
,
*
y
);
}
else
{
if
((
mod
<
0
.
0
)
!=
(
*
y
<
0
.
0
))
{
mod
+=
*
y
;
div
-=
1
.
0
;
}
}
mp_float_t
floordiv
;
if
(
div
==
0
.
0
)
{
// if division is zero, take the correct sign of zero
floordiv
=
MICROPY_FLOAT_C_FUN
(
copysign
)(
0
.
0
,
*
x
/
*
y
);
}
else
{
// Python specs require that x == (x//y)*y + (x%y)
floordiv
=
MICROPY_FLOAT_C_FUN
(
floor
)(
div
);
if
(
div
-
floordiv
>
0
.
5
)
{
floordiv
+=
1
.
0
;
}
}
// return results
*
x
=
floordiv
;
*
y
=
mod
;
}
#endif // MICROPY_PY_BUILTINS_FLOAT
py/objtype.c
View file @
c5029bcb
...
...
@@ -400,6 +400,7 @@ const qstr mp_binary_op_method_name[] = {
/*
MP_BINARY_OP_MODULO,
MP_BINARY_OP_POWER,
MP_BINARY_OP_DIVMOD,
MP_BINARY_OP_INPLACE_OR,
MP_BINARY_OP_INPLACE_XOR,
MP_BINARY_OP_INPLACE_AND,
...
...
py/runtime.c
View file @
c5029bcb
...
...
@@ -441,6 +441,17 @@ mp_obj_t mp_binary_op(mp_uint_t op, mp_obj_t lhs, mp_obj_t rhs) {
lhs
=
mp_obj_new_int_from_ll
(
MP_OBJ_SMALL_INT_VALUE
(
lhs
));
goto
generic_binary_op
;
case
MP_BINARY_OP_DIVMOD
:
{
if
(
rhs_val
==
0
)
{
goto
zero_division
;
}
// to reduce stack usage we don't pass a temp array of the 2 items
mp_obj_tuple_t
*
tuple
=
mp_obj_new_tuple
(
2
,
NULL
);
tuple
->
items
[
0
]
=
MP_OBJ_NEW_SMALL_INT
(
mp_small_int_floor_divide
(
lhs_val
,
rhs_val
));
tuple
->
items
[
1
]
=
MP_OBJ_NEW_SMALL_INT
(
mp_small_int_modulo
(
lhs_val
,
rhs_val
));
return
tuple
;
}
case
MP_BINARY_OP_LESS
:
return
MP_BOOL
(
lhs_val
<
rhs_val
);
break
;
case
MP_BINARY_OP_MORE
:
return
MP_BOOL
(
lhs_val
>
rhs_val
);
break
;
case
MP_BINARY_OP_LESS_EQUAL
:
return
MP_BOOL
(
lhs_val
<=
rhs_val
);
break
;
...
...
py/runtime0.h
View file @
c5029bcb
...
...
@@ -74,29 +74,30 @@ typedef enum {
MP_BINARY_OP_MODULO
,
MP_BINARY_OP_POWER
,
MP_BINARY_OP_DIVMOD
,
// not emitted by the compiler but supported by the runtime
MP_BINARY_OP_INPLACE_OR
,
MP_BINARY_OP_INPLACE_XOR
,
MP_BINARY_OP_INPLACE_AND
,
MP_BINARY_OP_INPLACE_AND
,
MP_BINARY_OP_INPLACE_LSHIFT
,
MP_BINARY_OP_INPLACE_RSHIFT
,
MP_BINARY_OP_INPLACE_ADD
,
MP_BINARY_OP_INPLACE_SUBTRACT
,
MP_BINARY_OP_INPLACE_MULTIPLY
,
MP_BINARY_OP_INPLACE_MULTIPLY
,
MP_BINARY_OP_INPLACE_FLOOR_DIVIDE
,
MP_BINARY_OP_INPLACE_TRUE_DIVIDE
,
MP_BINARY_OP_INPLACE_MODULO
,
MP_BINARY_OP_INPLACE_POWER
,
// these should return a bool
MP_BINARY_OP_LESS
,
MP_BINARY_OP_MORE
,
MP_BINARY_OP_EQUAL
,
MP_BINARY_OP_LESS_EQUAL
,
MP_BINARY_OP_MORE_EQUAL
,
MP_BINARY_OP_NOT_EQUAL
,
MP_BINARY_OP_NOT_EQUAL
,
MP_BINARY_OP_IN
,
MP_BINARY_OP_IS
,
MP_BINARY_OP_EXCEPTION_MATCH
,
...
...
py/vm.c
View file @
c5029bcb
...
...
@@ -1199,7 +1199,7 @@ yield:
}
else
if
(
ip
[
-
1
]
<
MP_BC_UNARY_OP_MULTI
+
6
)
{
SET_TOP
(
mp_unary_op
(
ip
[
-
1
]
-
MP_BC_UNARY_OP_MULTI
,
TOP
()));
DISPATCH
();
}
else
if
(
ip
[
-
1
]
<
MP_BC_BINARY_OP_MULTI
+
3
5
)
{
}
else
if
(
ip
[
-
1
]
<
MP_BC_BINARY_OP_MULTI
+
3
6
)
{
mp_obj_t
rhs
=
POP
();
mp_obj_t
lhs
=
TOP
();
SET_TOP
(
mp_binary_op
(
ip
[
-
1
]
-
MP_BC_BINARY_OP_MULTI
,
lhs
,
rhs
));
...
...
py/vmentrytable.h
View file @
c5029bcb
...
...
@@ -112,7 +112,7 @@ static void* entry_table[256] = {
[
MP_BC_LOAD_FAST_MULTI
...
MP_BC_LOAD_FAST_MULTI
+
15
]
=
&&
entry_MP_BC_LOAD_FAST_MULTI
,
[
MP_BC_STORE_FAST_MULTI
...
MP_BC_STORE_FAST_MULTI
+
15
]
=
&&
entry_MP_BC_STORE_FAST_MULTI
,
[
MP_BC_UNARY_OP_MULTI
...
MP_BC_UNARY_OP_MULTI
+
5
]
=
&&
entry_MP_BC_UNARY_OP_MULTI
,
[
MP_BC_BINARY_OP_MULTI
...
MP_BC_BINARY_OP_MULTI
+
3
4
]
=
&&
entry_MP_BC_BINARY_OP_MULTI
,
[
MP_BC_BINARY_OP_MULTI
...
MP_BC_BINARY_OP_MULTI
+
3
5
]
=
&&
entry_MP_BC_BINARY_OP_MULTI
,
};
#if __clang__
...
...
tests/cmdline/cmd_showbc.py.exp
View file @
c5029bcb
...
...
@@ -93,21 +93,21 @@ arg names:
69 LOAD_DEREF 14
71 DUP_TOP
72 ROT_THREE
73 BINARY_OP 2
6
__eq__
73 BINARY_OP 2
7
__eq__
74 JUMP_IF_FALSE_OR_POP 82
77 LOAD_FAST 1
78 BINARY_OP 2
6
__eq__
78 BINARY_OP 2
7
__eq__
79 JUMP 84
82 ROT_TWO
83 POP_TOP
84 STORE_FAST 10
85 LOAD_FAST 0
86 LOAD_DEREF 14
88 BINARY_OP 2
6
__eq__
88 BINARY_OP 2
7
__eq__
89 JUMP_IF_FALSE_OR_POP 96
92 LOAD_DEREF 14
94 LOAD_FAST 1
95 BINARY_OP 2
6
__eq__
95 BINARY_OP 2
7
__eq__
96 UNARY_OP 0
97 NOT
98 STORE_FAST 10
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment