Skip to content

Commit 5b58624

Browse files
committed
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>
1 parent 782f394 commit 5b58624

File tree

4 files changed

+17
-10
lines changed

4 files changed

+17
-10
lines changed

py/parsenum.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,10 +99,10 @@ mp_obj_t mp_parse_num_integer(const char *restrict str_, size_t len, int base, m
9999
}
100100

101101
// add next digi and check for overflow
102-
if (mp_small_int_mul_overflow(int_val, base)) {
102+
if (mp_small_int_mul_overflow(int_val, base, &int_val)) {
103103
goto overflow;
104104
}
105-
int_val = int_val * base + dig;
105+
int_val += dig;
106106
if (!MP_SMALL_INT_FITS(int_val)) {
107107
goto overflow;
108108
}

py/runtime.c

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -505,13 +505,14 @@ mp_obj_t MICROPY_WRAP_MP_BINARY_OP(mp_binary_op)(mp_binary_op_t op, mp_obj_t lhs
505505
}
506506
#endif
507507

508-
if (mp_small_int_mul_overflow(lhs_val, rhs_val)) {
508+
mp_int_t int_res;
509+
if (mp_small_int_mul_overflow(lhs_val, rhs_val, &int_res)) {
509510
// use higher precision
510511
lhs = mp_obj_new_int_from_ll(lhs_val);
511512
goto generic_binary_op;
512513
} else {
513514
// use standard precision
514-
return MP_OBJ_NEW_SMALL_INT(lhs_val * rhs_val);
515+
return MP_OBJ_NEW_SMALL_INT(int_res);
515516
}
516517
}
517518
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
552553
mp_int_t ans = 1;
553554
while (rhs_val > 0) {
554555
if (rhs_val & 1) {
555-
if (mp_small_int_mul_overflow(ans, lhs_val)) {
556+
if (mp_small_int_mul_overflow(ans, lhs_val, &ans)) {
556557
goto power_overflow;
557558
}
558-
ans *= lhs_val;
559559
}
560560
if (rhs_val == 1) {
561561
break;
562562
}
563563
rhs_val /= 2;
564-
if (mp_small_int_mul_overflow(lhs_val, lhs_val)) {
564+
mp_int_t int_res;
565+
if (mp_small_int_mul_overflow(lhs_val, lhs_val, &int_res)) {
565566
goto power_overflow;
566567
}
567-
lhs_val *= lhs_val;
568+
lhs_val = int_res;
568569
}
569570
lhs_val = ans;
570571
}

py/smallint.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626

2727
#include "py/smallint.h"
2828

29-
bool mp_small_int_mul_overflow(mp_int_t x, mp_int_t y) {
29+
bool mp_small_int_mul_overflow(mp_int_t x, mp_int_t y, mp_int_t *res) {
3030
// Check for multiply overflow; see CERT INT32-C
3131
if (x > 0) { // x is positive
3232
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) {
4949
}
5050
} // End if x and y are nonpositive
5151
} // End if x is nonpositive
52+
53+
// Result doesn't overflow
54+
*res = x * y;
5255
return false;
5356
}
5457

py/smallint.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,10 @@
6868
// The number of bits in a MP_SMALL_INT including the sign bit.
6969
#define MP_SMALL_INT_BITS (MP_IMAX_BITS(MP_SMALL_INT_MAX) + 1)
7070

71-
bool mp_small_int_mul_overflow(mp_int_t x, mp_int_t y);
71+
// Multiply two small ints.
72+
// If returns false, the correct result is stored in 'res'
73+
// If returns true, the multiplication would have overflowed. 'res' is unchanged.
74+
bool mp_small_int_mul_overflow(mp_int_t x, mp_int_t y, mp_int_t *res);
7275
mp_int_t mp_small_int_modulo(mp_int_t dividend, mp_int_t divisor);
7376
mp_int_t mp_small_int_floor_divide(mp_int_t num, mp_int_t denom);
7477

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