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.
This commit is contained in:
parent
4d1fb6107f
commit
04552ff71b
4
py/mpz.c
4
py/mpz.c
|
@ -946,10 +946,6 @@ bool mpz_is_pos(const mpz_t *z) {
|
||||||
return z->len > 0 && z->neg == 0;
|
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) {
|
bool mpz_is_odd(const mpz_t *z) {
|
||||||
return z->len > 0 && (z->dig[0] & 1) != 0;
|
return z->len > 0 && (z->dig[0] & 1) != 0;
|
||||||
}
|
}
|
||||||
|
|
1
py/mpz.h
1
py/mpz.h
|
@ -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);
|
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_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);
|
int mpz_cmp(const mpz_t *lhs, const mpz_t *rhs);
|
||||||
|
|
||||||
void mpz_abs_inpl(mpz_t *dest, const mpz_t *z);
|
void mpz_abs_inpl(mpz_t *dest, const mpz_t *z);
|
||||||
|
|
|
@ -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_POWER:
|
||||||
case MP_BINARY_OP_INPLACE_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;
|
long long ans = 1;
|
||||||
while (rhs_val > 0) {
|
while (rhs_val > 0) {
|
||||||
if (rhs_val & 1) {
|
if (rhs_val & 1) {
|
||||||
|
|
|
@ -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_POWER:
|
||||||
case MP_BINARY_OP_INPLACE_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);
|
mpz_pow_inpl(&res->mpz, zlhs, zrhs);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,10 @@ print("%.5g" % (i / 1.2))
|
||||||
# this should delegate to complex
|
# this should delegate to complex
|
||||||
print("%.5g" % (i * 1.2j).imag)
|
print("%.5g" % (i * 1.2j).imag)
|
||||||
|
|
||||||
|
# negative power should produce float
|
||||||
|
print("%.5g" % (i ** -1))
|
||||||
|
print("%.5g" % ((2 + i - i) ** -3))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
i / 0
|
i / 0
|
||||||
except ZeroDivisionError:
|
except ZeroDivisionError:
|
||||||
|
|
Loading…
Reference in New Issue