py/smallint: Update mp_small_int_mul_overflow() to perform the multiply.
Makes it compatible with the __builtin_mul_overflow() syntax, used in follow-up commit. Includes optimisation in runtime.c to minimise the code size impact from additional param. Signed-off-by: Damien George <damien@micropython.org> Signed-off-by: Angus Gratton <angus@redyak.com.au>
This commit is contained in:
committed by
Damien George
parent
516aa02104
commit
e9845ab20e
@@ -99,10 +99,10 @@ mp_obj_t mp_parse_num_integer(const char *restrict str_, size_t len, int base, m
|
|||||||
}
|
}
|
||||||
|
|
||||||
// add next digi and check for overflow
|
// add next digi and check for overflow
|
||||||
if (mp_small_int_mul_overflow(int_val, base)) {
|
if (mp_small_int_mul_overflow(int_val, base, &int_val)) {
|
||||||
goto overflow;
|
goto overflow;
|
||||||
}
|
}
|
||||||
int_val = int_val * base + dig;
|
int_val += dig;
|
||||||
if (!MP_SMALL_INT_FITS(int_val)) {
|
if (!MP_SMALL_INT_FITS(int_val)) {
|
||||||
goto overflow;
|
goto overflow;
|
||||||
}
|
}
|
||||||
|
|||||||
13
py/runtime.c
13
py/runtime.c
@@ -505,13 +505,14 @@ mp_obj_t MICROPY_WRAP_MP_BINARY_OP(mp_binary_op)(mp_binary_op_t op, mp_obj_t lhs
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (mp_small_int_mul_overflow(lhs_val, rhs_val)) {
|
mp_int_t int_res;
|
||||||
|
if (mp_small_int_mul_overflow(lhs_val, rhs_val, &int_res)) {
|
||||||
// use higher precision
|
// use higher precision
|
||||||
lhs = mp_obj_new_int_from_ll(lhs_val);
|
lhs = mp_obj_new_int_from_ll(lhs_val);
|
||||||
goto generic_binary_op;
|
goto generic_binary_op;
|
||||||
} else {
|
} else {
|
||||||
// use standard precision
|
// use standard precision
|
||||||
return MP_OBJ_NEW_SMALL_INT(lhs_val * rhs_val);
|
return MP_OBJ_NEW_SMALL_INT(int_res);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case MP_BINARY_OP_FLOOR_DIVIDE:
|
case MP_BINARY_OP_FLOOR_DIVIDE:
|
||||||
@@ -552,19 +553,19 @@ mp_obj_t MICROPY_WRAP_MP_BINARY_OP(mp_binary_op)(mp_binary_op_t op, mp_obj_t lhs
|
|||||||
mp_int_t ans = 1;
|
mp_int_t ans = 1;
|
||||||
while (rhs_val > 0) {
|
while (rhs_val > 0) {
|
||||||
if (rhs_val & 1) {
|
if (rhs_val & 1) {
|
||||||
if (mp_small_int_mul_overflow(ans, lhs_val)) {
|
if (mp_small_int_mul_overflow(ans, lhs_val, &ans)) {
|
||||||
goto power_overflow;
|
goto power_overflow;
|
||||||
}
|
}
|
||||||
ans *= lhs_val;
|
|
||||||
}
|
}
|
||||||
if (rhs_val == 1) {
|
if (rhs_val == 1) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
rhs_val /= 2;
|
rhs_val /= 2;
|
||||||
if (mp_small_int_mul_overflow(lhs_val, lhs_val)) {
|
mp_int_t int_res;
|
||||||
|
if (mp_small_int_mul_overflow(lhs_val, lhs_val, &int_res)) {
|
||||||
goto power_overflow;
|
goto power_overflow;
|
||||||
}
|
}
|
||||||
lhs_val *= lhs_val;
|
lhs_val = int_res;
|
||||||
}
|
}
|
||||||
lhs_val = ans;
|
lhs_val = ans;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,7 +26,7 @@
|
|||||||
|
|
||||||
#include "py/smallint.h"
|
#include "py/smallint.h"
|
||||||
|
|
||||||
bool mp_small_int_mul_overflow(mp_int_t x, mp_int_t y) {
|
bool mp_small_int_mul_overflow(mp_int_t x, mp_int_t y, mp_int_t *res) {
|
||||||
// Check for multiply overflow; see CERT INT32-C
|
// Check for multiply overflow; see CERT INT32-C
|
||||||
if (x > 0) { // x is positive
|
if (x > 0) { // x is positive
|
||||||
if (y > 0) { // x and y are positive
|
if (y > 0) { // x and y are positive
|
||||||
@@ -49,6 +49,9 @@ bool mp_small_int_mul_overflow(mp_int_t x, mp_int_t y) {
|
|||||||
}
|
}
|
||||||
} // End if x and y are nonpositive
|
} // End if x and y are nonpositive
|
||||||
} // End if x is nonpositive
|
} // End if x is nonpositive
|
||||||
|
|
||||||
|
// Result doesn't overflow
|
||||||
|
*res = x * y;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -68,7 +68,10 @@
|
|||||||
// The number of bits in a MP_SMALL_INT including the sign bit.
|
// The number of bits in a MP_SMALL_INT including the sign bit.
|
||||||
#define MP_SMALL_INT_BITS (MP_IMAX_BITS(MP_SMALL_INT_MAX) + 1)
|
#define MP_SMALL_INT_BITS (MP_IMAX_BITS(MP_SMALL_INT_MAX) + 1)
|
||||||
|
|
||||||
bool mp_small_int_mul_overflow(mp_int_t x, mp_int_t y);
|
// Multiply two small ints.
|
||||||
|
// If returns false, the correct result is stored in 'res'
|
||||||
|
// If returns true, the multiplication would have overflowed. 'res' is unchanged.
|
||||||
|
bool mp_small_int_mul_overflow(mp_int_t x, mp_int_t y, mp_int_t *res);
|
||||||
mp_int_t mp_small_int_modulo(mp_int_t dividend, mp_int_t divisor);
|
mp_int_t mp_small_int_modulo(mp_int_t dividend, mp_int_t divisor);
|
||||||
mp_int_t mp_small_int_floor_divide(mp_int_t num, mp_int_t denom);
|
mp_int_t mp_small_int_floor_divide(mp_int_t num, mp_int_t denom);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user