Skip to content

Commit ae49105

Browse files
committed
py: Fix float/complex binop returning NULL; implement complex power.
1 parent f31b6ff commit ae49105

File tree

4 files changed

+45
-5
lines changed

4 files changed

+45
-5
lines changed

py/obj.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -429,11 +429,11 @@ typedef struct _mp_obj_float_t {
429429
mp_float_t value;
430430
} mp_obj_float_t;
431431
mp_float_t mp_obj_float_get(mp_obj_t self_in);
432-
mp_obj_t mp_obj_float_binary_op(int op, mp_float_t lhs_val, mp_obj_t rhs);
432+
mp_obj_t mp_obj_float_binary_op(int op, mp_float_t lhs_val, mp_obj_t rhs); // can return MP_OBJ_NULL
433433

434434
// complex
435435
void mp_obj_complex_get(mp_obj_t self_in, mp_float_t *real, mp_float_t *imag);
436-
mp_obj_t mp_obj_complex_binary_op(int op, mp_float_t lhs_real, mp_float_t lhs_imag, mp_obj_t rhs_in);
436+
mp_obj_t mp_obj_complex_binary_op(int op, mp_float_t lhs_real, mp_float_t lhs_imag, mp_obj_t rhs_in); // can return MP_OBJ_NULL
437437
#endif
438438

439439
// tuple

py/objcomplex.c

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111

1212
#if MICROPY_ENABLE_FLOAT
1313

14+
#include <math.h>
15+
1416
#if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT
1517
#include "formatfloat.h"
1618
#endif
@@ -176,6 +178,33 @@ mp_obj_t mp_obj_complex_binary_op(int op, mp_float_t lhs_real, mp_float_t lhs_im
176178
}
177179
break;
178180

181+
case MP_BINARY_OP_POWER:
182+
case MP_BINARY_OP_INPLACE_POWER: {
183+
// z1**z2 = exp(z2*ln(z1))
184+
// = exp(z2*(ln(|z1|)+i*arg(z1)))
185+
// = exp( (x2*ln1 - y2*arg1) + i*(y2*ln1 + x2*arg1) )
186+
// = exp(x3 + i*y3)
187+
// = exp(x3)*(cos(y3) + i*sin(y3))
188+
mp_float_t abs1 = MICROPY_FLOAT_C_FUN(sqrt)(lhs_real*lhs_real + lhs_imag*lhs_imag);
189+
if (abs1 == 0) {
190+
if (rhs_imag == 0) {
191+
lhs_real = 1;
192+
rhs_real = 0;
193+
} else {
194+
nlr_raise(mp_obj_new_exception_msg(&mp_type_ZeroDivisionError, "0.0 to a complex power"));
195+
}
196+
} else {
197+
mp_float_t ln1 = MICROPY_FLOAT_C_FUN(log)(abs1);
198+
mp_float_t arg1 = MICROPY_FLOAT_C_FUN(atan2)(lhs_imag, lhs_real);
199+
mp_float_t x3 = rhs_real * ln1 - rhs_imag * arg1;
200+
mp_float_t y3 = rhs_imag * ln1 + rhs_real * arg1;
201+
mp_float_t exp_x3 = MICROPY_FLOAT_C_FUN(exp)(x3);
202+
lhs_real = exp_x3 * MICROPY_FLOAT_C_FUN(cos)(y3);
203+
lhs_imag = exp_x3 * MICROPY_FLOAT_C_FUN(sin)(y3);
204+
}
205+
break;
206+
}
207+
179208
default:
180209
return MP_OBJ_NULL; // op not supported
181210
}

py/objfloat.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ mp_obj_t mp_obj_float_binary_op(int op, mp_float_t lhs_val, mp_obj_t rhs_in) {
136136
case MP_BINARY_OP_MORE_EQUAL: return MP_BOOL(lhs_val >= rhs_val);
137137

138138
default:
139-
return NULL; // op not supported
139+
return MP_OBJ_NULL; // op not supported
140140
}
141141
return mp_obj_new_float(lhs_val);
142142
}

py/runtime.c

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -386,9 +386,19 @@ mp_obj_t mp_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) {
386386
}
387387
#if MICROPY_ENABLE_FLOAT
388388
} else if (MP_OBJ_IS_TYPE(rhs, &mp_type_float)) {
389-
return mp_obj_float_binary_op(op, lhs_val, rhs);
389+
mp_obj_t res = mp_obj_float_binary_op(op, lhs_val, rhs);
390+
if (res == MP_OBJ_NULL) {
391+
goto unsupported_op;
392+
} else {
393+
return res;
394+
}
390395
} else if (MP_OBJ_IS_TYPE(rhs, &mp_type_complex)) {
391-
return mp_obj_complex_binary_op(op, lhs_val, 0, rhs);
396+
mp_obj_t res = mp_obj_complex_binary_op(op, lhs_val, 0, rhs);
397+
if (res == MP_OBJ_NULL) {
398+
goto unsupported_op;
399+
} else {
400+
return res;
401+
}
392402
#endif
393403
}
394404
}
@@ -438,6 +448,7 @@ mp_obj_t mp_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) {
438448
// TODO implement dispatch for reverse binary ops
439449

440450
// TODO specify in error message what the operator is
451+
unsupported_op:
441452
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
442453
"unsupported operand types for binary operator: '%s', '%s'",
443454
mp_obj_get_type_str(lhs), mp_obj_get_type_str(rhs)));

0 commit comments

Comments
 (0)