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 @@ 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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy