kopia lustrzana https://github.com/micropython/micropython
py/obj: Make mp_obj_get_complex_maybe call mp_obj_get_float_maybe first.
This commit simplifies mp_obj_get_complex_maybe() by first calling mp_obj_get_float_maybe() to handle the cases corresponding to floats. Only if that fails does it attempt to extra a full complex number. This reduces code size and also means that mp_obj_get_complex_maybe() now supports user-defined classes defining __float__; in particular this allows user-defined classes to be used as arguments to cmath-module function. Furthermore, complex_make_new() can now be simplified to directly call mp_obj_get_complex(), instead of mp_obj_get_complex_maybe() followed by mp_obj_get_float(). This also improves error messages from complex with an invalid argument, it now raises "can't convert <type> to complex" rather than "can't convert <type> to float". Signed-off-by: Damien George <damien@micropython.org>pull/8905/head
rodzic
1e87b56219
commit
4fe3e493b1
17
py/obj.c
17
py/obj.c
|
@ -383,22 +383,7 @@ mp_float_t mp_obj_get_float(mp_obj_t arg) {
|
||||||
|
|
||||||
#if MICROPY_PY_BUILTINS_COMPLEX
|
#if MICROPY_PY_BUILTINS_COMPLEX
|
||||||
bool mp_obj_get_complex_maybe(mp_obj_t arg, mp_float_t *real, mp_float_t *imag) {
|
bool mp_obj_get_complex_maybe(mp_obj_t arg, mp_float_t *real, mp_float_t *imag) {
|
||||||
if (arg == mp_const_false) {
|
if (mp_obj_get_float_maybe(arg, real)) {
|
||||||
*real = 0;
|
|
||||||
*imag = 0;
|
|
||||||
} else if (arg == mp_const_true) {
|
|
||||||
*real = 1;
|
|
||||||
*imag = 0;
|
|
||||||
} else if (mp_obj_is_small_int(arg)) {
|
|
||||||
*real = (mp_float_t)MP_OBJ_SMALL_INT_VALUE(arg);
|
|
||||||
*imag = 0;
|
|
||||||
#if MICROPY_LONGINT_IMPL != MICROPY_LONGINT_IMPL_NONE
|
|
||||||
} else if (mp_obj_is_exact_type(arg, &mp_type_int)) {
|
|
||||||
*real = mp_obj_int_as_float_impl(arg);
|
|
||||||
*imag = 0;
|
|
||||||
#endif
|
|
||||||
} else if (mp_obj_is_float(arg)) {
|
|
||||||
*real = mp_obj_float_get(arg);
|
|
||||||
*imag = 0;
|
*imag = 0;
|
||||||
} else if (mp_obj_is_type(arg, &mp_type_complex)) {
|
} else if (mp_obj_is_type(arg, &mp_type_complex)) {
|
||||||
mp_obj_complex_get(arg, real, imag);
|
mp_obj_complex_get(arg, real, imag);
|
||||||
|
|
|
@ -89,11 +89,8 @@ STATIC mp_obj_t complex_make_new(const mp_obj_type_t *type_in, size_t n_args, si
|
||||||
return args[0];
|
return args[0];
|
||||||
} else {
|
} else {
|
||||||
mp_float_t real, imag;
|
mp_float_t real, imag;
|
||||||
if (mp_obj_get_complex_maybe(args[0], &real, &imag)) {
|
mp_obj_get_complex(args[0], &real, &imag);
|
||||||
return mp_obj_new_complex(real, imag);
|
return mp_obj_new_complex(real, imag);
|
||||||
}
|
|
||||||
// something else, try to cast it to a complex
|
|
||||||
return mp_obj_new_complex(mp_obj_get_float(args[0]), 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
# test that cmath functions support user classes with __float__ and __complex__
|
||||||
|
|
||||||
|
try:
|
||||||
|
import cmath
|
||||||
|
except ImportError:
|
||||||
|
print("SKIP")
|
||||||
|
raise SystemExit
|
||||||
|
|
||||||
|
|
||||||
|
class TestFloat:
|
||||||
|
def __float__(self):
|
||||||
|
return 1.0
|
||||||
|
|
||||||
|
|
||||||
|
class TestComplex:
|
||||||
|
def __complex__(self):
|
||||||
|
return 1j + 10
|
||||||
|
|
||||||
|
|
||||||
|
for clas in TestFloat, TestComplex:
|
||||||
|
print("%.5g" % cmath.phase(clas()))
|
|
@ -1,6 +1,11 @@
|
||||||
# test __complex__ function support
|
# test __complex__ function support
|
||||||
|
|
||||||
|
|
||||||
|
class TestFloat:
|
||||||
|
def __float__(self):
|
||||||
|
return 1.0
|
||||||
|
|
||||||
|
|
||||||
class TestComplex:
|
class TestComplex:
|
||||||
def __complex__(self):
|
def __complex__(self):
|
||||||
return 1j + 10
|
return 1j + 10
|
||||||
|
@ -20,6 +25,7 @@ class Test:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
print(complex(TestFloat()))
|
||||||
print(complex(TestComplex()))
|
print(complex(TestComplex()))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
# test that math functions support user classes with __float__
|
||||||
|
|
||||||
|
try:
|
||||||
|
import math
|
||||||
|
except ImportError:
|
||||||
|
print("SKIP")
|
||||||
|
raise SystemExit
|
||||||
|
|
||||||
|
|
||||||
|
class TestFloat:
|
||||||
|
def __float__(self):
|
||||||
|
return 1.0
|
||||||
|
|
||||||
|
|
||||||
|
print("%.5g" % math.exp(TestFloat()))
|
Ładowanie…
Reference in New Issue