39
39
40
40
#if SIZEOF_SIZE_T >= 8
41
41
# define BC_MUL_UINT_DIGITS 8
42
- # define BC_MUL_UINT_OVERFLOW 100000000
42
+ # define BC_MUL_UINT_OVERFLOW (BC_UINT_T) 100000000
43
43
#else
44
44
# define BC_MUL_UINT_DIGITS 4
45
- # define BC_MUL_UINT_OVERFLOW 10000
45
+ # define BC_MUL_UINT_OVERFLOW (BC_UINT_T) 10000
46
46
#endif
47
47
48
+ #define BC_MUL_MAX_ADD_COUNT (~((BC_UINT_T) 0) / (BC_MUL_UINT_OVERFLOW * BC_MUL_UINT_OVERFLOW))
49
+
48
50
49
51
/* Multiply utility routines */
50
52
53
+ static inline void bc_digits_adjustment (BC_UINT_T * prod_uint , size_t prod_arr_size )
54
+ {
55
+ for (size_t i = 0 ; i < prod_arr_size - 1 ; i ++ ) {
56
+ prod_uint [i + 1 ] += prod_uint [i ] / BC_MUL_UINT_OVERFLOW ;
57
+ prod_uint [i ] %= BC_MUL_UINT_OVERFLOW ;
58
+ }
59
+ }
60
+
51
61
/*
52
62
* Converts BCD to uint, going backwards from pointer n by the number of
53
63
* characters specified by len.
@@ -141,7 +151,18 @@ static void bc_standard_mul(bc_num n1, size_t n1len, bc_num n2, size_t n2len, bc
141
151
bc_convert_to_uint (n2_uint , n2end , n2len );
142
152
143
153
/* Multiplication and addition */
154
+ size_t count = 0 ;
144
155
for (i = 0 ; i < n1_arr_size ; i ++ ) {
156
+ /*
157
+ * This calculation adds the result multiple times to the array entries.
158
+ * When multiplying large numbers of digits, there is a possibility of
159
+ * overflow, so digit adjustment is performed beforehand.
160
+ */
161
+ if (UNEXPECTED (count >= BC_MUL_MAX_ADD_COUNT )) {
162
+ bc_digits_adjustment (prod_uint , prod_arr_size );
163
+ count = 0 ;
164
+ }
165
+ count ++ ;
145
166
for (size_t j = 0 ; j < n2_arr_size ; j ++ ) {
146
167
prod_uint [i + j ] += n1_uint [i ] * n2_uint [j ];
147
168
}
@@ -151,10 +172,7 @@ static void bc_standard_mul(bc_num n1, size_t n1len, bc_num n2, size_t n2len, bc
151
172
* Move a value exceeding 4/8 digits by carrying to the next digit.
152
173
* However, the last digit does nothing.
153
174
*/
154
- for (i = 0 ; i < prod_arr_size - 1 ; i ++ ) {
155
- prod_uint [i + 1 ] += prod_uint [i ] / BC_MUL_UINT_OVERFLOW ;
156
- prod_uint [i ] %= BC_MUL_UINT_OVERFLOW ;
157
- }
175
+ bc_digits_adjustment (prod_uint , prod_arr_size );
158
176
159
177
/* Convert to bc_num */
160
178
* prod = bc_new_num_nonzeroed (prodlen , 0 );
0 commit comments