Skip to content

Commit

Permalink
py: Implement raising a big-int to a negative power.
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
dpgeorge committed Jul 25, 2017
1 parent 4d1fb61 commit 04552ff
Show file tree
Hide file tree
Showing 5 changed files with 19 additions and 4 deletions.
4 changes: 0 additions & 4 deletions py/mpz.c
Original file line number Diff line number Diff line change
Expand Up @@ -946,10 +946,6 @@ bool mpz_is_pos(const mpz_t *z) {
return z->len > 0 && z->neg == 0;
}

bool mpz_is_neg(const mpz_t *z) {
return z->len > 0 && z->neg != 0;
}

bool mpz_is_odd(const mpz_t *z) {
return z->len > 0 && (z->dig[0] & 1) != 0;
}
Expand Down
1 change: 1 addition & 0 deletions py/mpz.h
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ size_t mpz_set_from_str(mpz_t *z, const char *str, size_t len, bool neg, unsigne
void mpz_set_from_bytes(mpz_t *z, bool big_endian, size_t len, const byte *buf);

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

void mpz_abs_inpl(mpz_t *dest, const mpz_t *z);
Expand Down
7 changes: 7 additions & 0 deletions py/objint_longlong.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {

case MP_BINARY_OP_POWER:
case MP_BINARY_OP_INPLACE_POWER: {
if (rhs_val < 0) {
#if MICROPY_PY_BUILTINS_FLOAT
return mp_obj_float_binary_op(op, lhs_val, rhs_in);
#else
mp_raise_ValueError("negative power with no float support");
#endif
}
long long ans = 1;
while (rhs_val > 0) {
if (rhs_val & 1) {
Expand Down
7 changes: 7 additions & 0 deletions py/objint_mpz.c
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,13 @@ mp_obj_t mp_obj_int_binary_op(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) {

case MP_BINARY_OP_POWER:
case MP_BINARY_OP_INPLACE_POWER:
if (mpz_is_neg(zrhs)) {
#if MICROPY_PY_BUILTINS_FLOAT
return mp_obj_float_binary_op(op, mpz_as_float(zlhs), rhs_in);
#else
mp_raise_ValueError("negative power with no float support");
#endif
}
mpz_pow_inpl(&res->mpz, zlhs, zrhs);
break;

Expand Down
4 changes: 4 additions & 0 deletions tests/float/int_big_float.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@
# this should delegate to complex
print("%.5g" % (i * 1.2j).imag)

# negative power should produce float
print("%.5g" % (i ** -1))
print("%.5g" % ((2 + i - i) ** -3))

try:
i / 0
except ZeroDivisionError:
Expand Down

0 comments on commit 04552ff

Please sign in to comment.