summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--py/modbuiltins.c13
-rw-r--r--py/objint.c10
-rw-r--r--py/objint.h1
-rw-r--r--py/objint_longlong.c24
-rw-r--r--py/objint_mpz.c21
-rw-r--r--tests/basics/builtin_abs.py14
6 files changed, 75 insertions, 8 deletions
diff --git a/py/modbuiltins.c b/py/modbuiltins.c
index 31ed8a7159..78fa4afc33 100644
--- a/py/modbuiltins.c
+++ b/py/modbuiltins.c
@@ -29,6 +29,7 @@
#include "py/nlr.h"
#include "py/smallint.h"
+#include "py/objint.h"
#include "py/objstr.h"
#include "py/runtime0.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
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) {
- if (MP_OBJ_IS_SMALL_INT(o_in)) {
- mp_int_t val = MP_OBJ_SMALL_INT_VALUE(o_in);
- if (val < 0) {
- val = -val;
- }
- return MP_OBJ_NEW_SMALL_INT(val);
+ if (0) {
+ // dummy
#if MICROPY_PY_BUILTINS_FLOAT
} else if (MP_OBJ_IS_TYPE(o_in, &mp_type_float)) {
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) {
#endif
#endif
} else {
- assert(0);
- return mp_const_none;
+ // this will raise a TypeError if the argument is not integral
+ return mp_obj_int_abs(o_in);
}
}
MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_abs_obj, mp_builtin_abs);
diff --git a/py/objint.c b/py/objint.c
index 0fb2a38262..26e1cc048f 100644
--- a/py/objint.c
+++ b/py/objint.c
@@ -266,6 +266,16 @@ bool mp_obj_int_is_positive(mp_obj_t self_in) {
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
mp_obj_t mp_obj_int_unary_op(mp_uint_t op, mp_obj_t o_in) {
return MP_OBJ_NULL; // op not supported
diff --git a/py/objint.h b/py/objint.h
index c995f2632a..63cd91a698 100644
--- a/py/objint.h
+++ b/py/objint.h
@@ -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);
mp_int_t mp_obj_int_hash(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_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);
diff --git a/py/objint_longlong.c b/py/objint_longlong.c
index 83e1c67d6d..837889704a 100644
--- a/py/objint_longlong.c
+++ b/py/objint_longlong.c
@@ -71,6 +71,30 @@ bool mp_obj_int_is_positive(mp_obj_t self_in) {
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_int_t *o = o_in;
switch (op) {
diff --git a/py/objint_mpz.c b/py/objint_mpz.c
index c46692ec76..be917f4a74 100644
--- a/py/objint_mpz.c
+++ b/py/objint_mpz.c
@@ -112,6 +112,27 @@ bool mp_obj_int_is_positive(mp_obj_t self_in) {
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_int_t *o = o_in;
switch (op) {
diff --git a/tests/basics/builtin_abs.py b/tests/basics/builtin_abs.py
new file mode 100644
index 0000000000..788bc450f8
--- /dev/null
+++ b/tests/basics/builtin_abs.py
@@ -0,0 +1,14 @@
+# 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))