8000 py: Implement raising a big-int to a negative power. · lable/micropython@04552ff · GitHub
[go: up one dir, main page]

Skip to content

Commit 04552ff

Browse files
committed
py: Implement raising a big-int to a negative power.
Before this patch raising a big-int to a negative power would just return 0. Now it returns a floating-point number with the correct value.
1 parent 4d1fb61 commit 04552ff

File tree

5 files changed

+19
-4
lines changed

5 files changed

+19
-4
lines changed

py/mpz.c

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -946,10 +946,6 @@ bool mpz_is_pos(const mpz_t *z) {
946946
return z->len > 0 && z->neg == 0;
947947
}
948948

949-
bool mpz_is_neg(const mpz_t *z) {
950-
return z->len > 0 && z->neg != 0;
951-
}
952-
953949
bool mpz_is_odd(const mpz_t *z) {
954950
return z->len > 0 && (z->dig[0] & 1) != 0;
955951
}

py/mpz.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ size_t mpz_set_from_str(mpz_t *z, const char *str, size_t len, bool neg, unsigne
112112
void mpz_set_from_bytes(mpz_t *z, bool big_endian, size_t len, const byte *buf);
113113

114114
static inline bool mpz_is_zero(const mpz_t *z) { return z->len == 0; }
115+
static inline bool mpz_is_neg(const mpz_t *z) { return z->len != 0 && z->neg != 0; }
115116
int mpz_cmp(const mpz_t *lhs, const mpz_t *rhs);
116117

117118
void mpz_abs_inpl(mpz_t *dest, const mpz_t *z);

py/objint_longlong.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,13 @@ mp_obj_t mp_obj_int_binary_op(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
191191

192192
case MP_BINARY_OP_POWER:
193193
case MP_BINARY_OP_INPLACE_POWER: {
194+
if (rhs_val < 0) {
195+
#if MICROPY_PY_BUILTINS_FLOAT
196+
return mp_obj_float_binary_op(op, lhs_val, rhs_in);
197+
#else
198+
mp_raise_ValueError("negative power with no float support");
199+
#endif
200+
}
194201
long long ans = 1;
195202
while (rhs_val > 0) {
196203
if (rhs_val & 1) {

py/objint_mpz.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,13 @@ D76A mp_obj_t mp_obj_int_binary_op(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
290290

291291
case MP_BINARY_OP_POWER:
292292
case MP_BINARY_OP_INPLACE_POWER:
293+
if (mpz_is_neg(zrhs)) {
294+
#if MICROPY_PY_BUILTINS_FLOAT
295+
return mp_obj_float_binary_op(op, mpz_as_float(zlhs), rhs_in);
296+
#else
297+
mp_raise_ValueError("negative power with no float support");
298+
#endif
299+
}
293300
mpz_pow_inpl(&res->mpz, zlhs, zrhs);
294301
break;
295302

tests/float/int_big_float.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@
1818
# this should delegate to complex
1919
print("%.5g" % (i * 1.2j).imag)
2020

21+
# negative power should produce float
22+
print("%.5g" % (i ** -1))
23+
print("%.5g" % ((2 + i - i) ** -3))
24+
2125
try:
2226
i / 0
2327
except ZeroDivisionError:

0 commit comments

Comments
 (0)
0