Commit 6837d46c authored by Damien George's avatar Damien George
Browse files

py: Fix builtin abs so it works for bools and bignum.

parent 26a9975f
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
#include "py/nlr.h" #include "py/nlr.h"
#include "py/smallint.h" #include "py/smallint.h"
#include "py/objint.h"
#include "py/objstr.h" #include "py/objstr.h"
#include "py/runtime0.h" #include "py/runtime0.h"
#include "py/runtime.h" #include "py/runtime.h"
...@@ -86,12 +87,8 @@ STATIC mp_obj_t mp_builtin___build_class__(mp_uint_t n_args, const mp_obj_t *arg ...@@ -86,12 +87,8 @@ STATIC mp_obj_t mp_builtin___build_class__(mp_uint_t n_args, const mp_obj_t *arg
MP_DEFINE_CONST_FUN_OBJ_VAR(mp_builtin___build_class___obj, 2, mp_builtin___build_class__); MP_DEFINE_CONST_FUN_OBJ_VAR(mp_builtin___build_class___obj, 2, mp_builtin___build_class__);
STATIC mp_obj_t mp_builtin_abs(mp_obj_t o_in) { STATIC mp_obj_t mp_builtin_abs(mp_obj_t o_in) {
if (MP_OBJ_IS_SMALL_INT(o_in)) { if (0) {
mp_int_t val = MP_OBJ_SMALL_INT_VALUE(o_in); // dummy
if (val < 0) {
val = -val;
}
return MP_OBJ_NEW_SMALL_INT(val);
#if MICROPY_PY_BUILTINS_FLOAT #if MICROPY_PY_BUILTINS_FLOAT
} else if (MP_OBJ_IS_TYPE(o_in, &mp_type_float)) { } else if (MP_OBJ_IS_TYPE(o_in, &mp_type_float)) {
mp_float_t value = mp_obj_float_get(o_in); mp_float_t value = mp_obj_float_get(o_in);
...@@ -109,8 +106,8 @@ STATIC mp_obj_t mp_builtin_abs(mp_obj_t o_in) { ...@@ -109,8 +106,8 @@ STATIC mp_obj_t mp_builtin_abs(mp_obj_t o_in) {
#endif #endif
#endif #endif
} else { } else {
assert(0); // this will raise a TypeError if the argument is not integral
return mp_const_none; return mp_obj_int_abs(o_in);
} }
} }
MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_abs_obj, mp_builtin_abs); MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_abs_obj, mp_builtin_abs);
......
...@@ -266,6 +266,16 @@ bool mp_obj_int_is_positive(mp_obj_t self_in) { ...@@ -266,6 +266,16 @@ bool mp_obj_int_is_positive(mp_obj_t self_in) {
return mp_obj_get_int(self_in) >= 0; return mp_obj_get_int(self_in) >= 0;
} }
// This must handle int and bool types, and must raise a
// TypeError if the argument is not integral
mp_obj_t mp_obj_int_abs(mp_obj_t self_in) {
mp_int_t val = mp_obj_get_int(self_in);
if (val < 0) {
val = -val;
}
return MP_OBJ_NEW_SMALL_INT(val);
}
// This is called for operations on SMALL_INT that are not handled by mp_unary_op // This is called for operations on SMALL_INT that are not handled by mp_unary_op
mp_obj_t mp_obj_int_unary_op(mp_uint_t op, mp_obj_t o_in) { mp_obj_t mp_obj_int_unary_op(mp_uint_t op, mp_obj_t o_in) {
return MP_OBJ_NULL; // op not supported return MP_OBJ_NULL; // op not supported
......
...@@ -57,6 +57,7 @@ char *mp_obj_int_formatted_impl(char **buf, mp_uint_t *buf_size, mp_uint_t *fmt_ ...@@ -57,6 +57,7 @@ char *mp_obj_int_formatted_impl(char **buf, mp_uint_t *buf_size, mp_uint_t *fmt_
int base, const char *prefix, char base_char, char comma); int base, const char *prefix, char base_char, char comma);
mp_int_t mp_obj_int_hash(mp_obj_t self_in); mp_int_t mp_obj_int_hash(mp_obj_t self_in);
bool mp_obj_int_is_positive(mp_obj_t self_in); bool mp_obj_int_is_positive(mp_obj_t self_in);
mp_obj_t mp_obj_int_abs(mp_obj_t self_in);
mp_obj_t mp_obj_int_unary_op(mp_uint_t op, mp_obj_t o_in); mp_obj_t mp_obj_int_unary_op(mp_uint_t op, mp_obj_t o_in);
mp_obj_t mp_obj_int_binary_op(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_in); mp_obj_t mp_obj_int_binary_op(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_in);
mp_obj_t mp_obj_int_binary_op_extra_cases(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_in); mp_obj_t mp_obj_int_binary_op_extra_cases(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_in);
......
...@@ -71,6 +71,30 @@ bool mp_obj_int_is_positive(mp_obj_t self_in) { ...@@ -71,6 +71,30 @@ bool mp_obj_int_is_positive(mp_obj_t self_in) {
return self->val >= 0; return self->val >= 0;
} }
// This must handle int and bool types, and must raise a
// TypeError if the argument is not integral
mp_obj_t mp_obj_int_abs(mp_obj_t self_in) {
if (MP_OBJ_IS_TYPE(self_in, &mp_type_int)) {
mp_obj_int_t *self = self_in;
self = mp_obj_new_int_from_ll(self->val);
if (self->val < 0) {
// TODO could overflow long long
self->val = -self->val;
}
return self;
} else {
mp_int_t val = mp_obj_get_int(self_in);
if (val == MP_SMALL_INT_MIN) {
return mp_obj_new_int_from_ll(-val);
} else {
if (val < 0) {
val = -val;
}
return MP_OBJ_NEW_SMALL_INT(val);
}
}
}
mp_obj_t mp_obj_int_unary_op(mp_uint_t op, mp_obj_t o_in) { mp_obj_t mp_obj_int_unary_op(mp_uint_t op, mp_obj_t o_in) {
mp_obj_int_t *o = o_in; mp_obj_int_t *o = o_in;
switch (op) { switch (op) {
......
...@@ -112,6 +112,27 @@ bool mp_obj_int_is_positive(mp_obj_t self_in) { ...@@ -112,6 +112,27 @@ bool mp_obj_int_is_positive(mp_obj_t self_in) {
return !self->mpz.neg; return !self->mpz.neg;
} }
// This must handle int and bool types, and must raise a
// TypeError if the argument is not integral
mp_obj_t mp_obj_int_abs(mp_obj_t self_in) {
if (MP_OBJ_IS_TYPE(self_in, &mp_type_int)) {
mp_obj_int_t *self = self_in;
mp_obj_int_t *self2 = mp_obj_int_new_mpz();
mpz_abs_inpl(&self2->mpz, &self->mpz);
return self2;
} else {
mp_int_t val = mp_obj_get_int(self_in);
if (val == MP_SMALL_INT_MIN) {
return mp_obj_new_int_from_ll(-val);
} else {
if (val < 0) {
val = -val;
}
return MP_OBJ_NEW_SMALL_INT(val);
}
}
}
mp_obj_t mp_obj_int_unary_op(mp_uint_t op, mp_obj_t o_in) { mp_obj_t mp_obj_int_unary_op(mp_uint_t op, mp_obj_t o_in) {
mp_obj_int_t *o = o_in; mp_obj_int_t *o = o_in;
switch (op) { switch (op) {
......
# test builtin abs
print(abs(False))
print(abs(True))
print(abs(1))
print(abs(-1))
# bignum
print(abs(123456789012345678901234567890))
print(abs(-123456789012345678901234567890))
# edge cases for 32 and 64 bit archs (small int overflow when negating)
print(abs(-0x3fffffff - 1))
print(abs(-0x3fffffffffffffff - 1))
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment