33
33
#include <stddef.h>
34
34
#include <assert.h>
35
35
#include <stdbool.h>
36
- #include "private.h" /* For _bc_rm_leading_zeros() */
36
+ #include "private.h"
37
37
#include "zend_alloc.h"
38
38
39
39
40
40
#if SIZEOF_SIZE_T >= 8
41
- # define BC_MUL_UINT_DIGITS 8
42
- # define BC_MUL_UINT_OVERFLOW (BC_UINT_T) 100000000
41
+ # define BC_VECTOR_SIZE 8
42
+ /* The boundary number is computed from BASE ** BC_VECTOR_SIZE */
43
+ # define BC_VECTOR_BOUNDARY_NUM (BC_VECTOR) 100000000
43
44
#else
44
- # define BC_MUL_UINT_DIGITS 4
45
- # define BC_MUL_UINT_OVERFLOW (BC_UINT_T) 10000
45
+ # define BC_VECTOR_SIZE 4
46
+ /* The boundary number is computed from BASE ** BC_VECTOR_SIZE */
47
+ # define BC_VECTOR_BOUNDARY_NUM (BC_VECTOR) 10000
46
48
#endif
47
49
48
- #define BC_MUL_MAX_ADD_COUNT (~((BC_UINT_T) 0) / (BC_MUL_UINT_OVERFLOW * BC_MUL_UINT_OVERFLOW))
50
+ /*
51
+ * Adding more than this many times may cause uint32_t/uint64_t to overflow.
52
+ * Typically this is 1844 for 64bit and 42 for 32bit.
53
+ */
54
+ #define BC_VECTOR_NO_OVERFLOW_ADD_COUNT (~((BC_VECTOR) 0) / (BC_VECTOR_BOUNDARY_NUM * BC_VECTOR_BOUNDARY_NUM))
49
55
50
56
51
57
/* Multiply utility routines */
52
58
53
- static inline void bc_digits_adjustment (BC_UINT_T * prod_uint , size_t prod_arr_size )
59
+ static inline void bc_digits_adjustment (BC_VECTOR * prod_vector , size_t prod_arr_size )
54
60
{
55
61
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 ;
62
+ prod_vector [i + 1 ] += prod_vector [i ] / BC_VECTOR_BOUNDARY_NUM ;
63
+ prod_vector [i ] %= BC_VECTOR_BOUNDARY_NUM ;
58
64
}
59
65
}
60
66
@@ -66,16 +72,16 @@ static inline void bc_digits_adjustment(BC_UINT_T *prod_uint, size_t prod_arr_si
66
72
* due to its divide-and-conquer nature.
67
73
*/
68
74
#if SIZEOF_SIZE_T == 4
69
- static uint32_t bc_parse_chunk_chars (const char * str )
75
+ static BC_VECTOR bc_parse_chunk_chars (const char * str )
70
76
{
71
- uint32_t tmp ;
77
+ BC_VECTOR tmp ;
72
78
memcpy (& tmp , str , sizeof (tmp ));
73
79
#if !BC_LITTLE_ENDIAN
74
80
tmp = BC_BSWAP (tmp );
75
81
#endif
76
82
77
- uint32_t lower_digits = (tmp & 0x0f000f00 ) >> 8 ;
78
- uint32_t upper_digits = (tmp & 0x000f000f ) * 10 ;
83
+ BC_VECTOR lower_digits = (tmp & 0x0f000f00 ) >> 8 ;
84
+ BC_VECTOR upper_digits = (tmp & 0x000f000f ) * 10 ;
79
85
80
86
tmp = lower_digits + upper_digits ;
81
87
@@ -85,16 +91,16 @@ static uint32_t bc_parse_chunk_chars(const char *str)
85
91
return lower_digits + upper_digits ;
86
92
}
87
93
#elif SIZEOF_SIZE_T == 8
88
- static uint64_t bc_parse_chunk_chars (const char * str )
94
+ static BC_VECTOR bc_parse_chunk_chars (const char * str )
89
95
{
90
- uint64_t tmp ;
96
+ BC_VECTOR tmp ;
91
97
memcpy (& tmp , str , sizeof (tmp ));
92
98
#if !BC_LITTLE_ENDIAN
93
99
tmp = BC_BSWAP (tmp );
94
100
#endif
95
101
96
- uint64_t lower_digits = (tmp & 0x0f000f000f000f00 ) >> 8 ;
97
- uint64_t upper_digits = (tmp & 0x000f000f000f000f ) * 10 ;
102
+ BC_VECTOR lower_digits = (tmp & 0x0f000f000f000f00 ) >> 8 ;
103
+ BC_VECTOR upper_digits = (tmp & 0x000f000f000f000f ) * 10 ;
98
104
99
105
tmp = lower_digits + upper_digits ;
100
106
@@ -111,17 +117,17 @@ static uint64_t bc_parse_chunk_chars(const char *str)
111
117
#endif
112
118
113
119
/*
114
- * Converts BCD to uint , going backwards from pointer n by the number of
120
+ * Converts bc_num to BC_VECTOR , going backwards from pointer n by the number of
115
121
* characters specified by len.
116
122
*/
117
- static inline BC_UINT_T bc_partial_convert_to_uint (const char * n , size_t len )
123
+ static inline BC_VECTOR bc_partial_convert_to_vector (const char * n , size_t len )
118
124
{
119
- if (len == BC_MUL_UINT_DIGITS ) {
120
- return bc_parse_chunk_chars (n - BC_MUL_UINT_DIGITS + 1 );
125
+ if (len == BC_VECTOR_SIZE ) {
126
+ return bc_parse_chunk_chars (n - BC_VECTOR_SIZE + 1 );
121
127
}
122
128
123
- BC_UINT_T num = 0 ;
124
- BC_UINT_T base = 1 ;
129
+ BC_VECTOR num = 0 ;
130
+ BC_VECTOR base = 1 ;
125
131
126
132
for (size_t i = 0 ; i < len ; i ++ ) {
127
133
num += * n * base ;
@@ -132,12 +138,12 @@ static inline BC_UINT_T bc_partial_convert_to_uint(const char *n, size_t len)
132
138
return num ;
133
139
}
134
140
135
- static inline void bc_convert_to_uint ( BC_UINT_T * n_uint , const char * nend , size_t nlen )
141
+ static inline void bc_convert_to_vector ( BC_VECTOR * n_vector , const char * nend , size_t nlen )
136
142
{
137
143
size_t i = 0 ;
138
144
while (nlen > 0 ) {
139
- size_t len = MIN (BC_MUL_UINT_DIGITS , nlen );
140
- n_uint [i ] = bc_partial_convert_to_uint (nend , len );
145
+ size_t len = MIN (BC_VECTOR_SIZE , nlen );
146
+ n_vector [i ] = bc_partial_convert_to_vector (nend , len );
141
147
nend -= len ;
142
148
nlen -= len ;
143
149
i ++ ;
@@ -153,18 +159,18 @@ static inline void bc_fast_mul(bc_num n1, size_t n1len, bc_num n2, size_t n2len,
153
159
const char * n1end = n1 -> n_value + n1len - 1 ;
154
160
const char * n2end = n2 -> n_value + n2len - 1 ;
155
161
156
- BC_UINT_T n1_uint = bc_partial_convert_to_uint (n1end , n1len );
157
- BC_UINT_T n2_uint = bc_partial_convert_to_uint (n2end , n2len );
158
- BC_UINT_T prod_uint = n1_uint * n2_uint ;
162
+ BC_VECTOR n1_vector = bc_partial_convert_to_vector (n1end , n1len );
163
+ BC_VECTOR n2_vector = bc_partial_convert_to_vector (n2end , n2len );
164
+ BC_VECTOR prod_vector = n1_vector * n2_vector ;
159
165
160
166
size_t prodlen = n1len + n2len ;
161
167
* prod = bc_new_num_nonzeroed (prodlen , 0 );
162
168
char * pptr = (* prod )-> n_value ;
163
169
char * pend = pptr + prodlen - 1 ;
164
170
165
171
while (pend >= pptr ) {
166
- * pend -- = prod_uint % BASE ;
167
- prod_uint /= BASE ;
172
+ * pend -- = prod_vector % BASE ;
173
+ prod_vector /= BASE ;
168
174
}
169
175
}
170
176
@@ -215,7 +221,7 @@ static void bc_write_bcd_representation(uint32_t value, char *str)
215
221
}
216
222
217
223
/*
218
- * Converts the BCD of bc_num by 4 (32 bits) or 8 (64 bits) digits to an array of BC_UINT_Ts .
224
+ * Converts the BCD of bc_num by 4 (32 bits) or 8 (64 bits) digits to an array of BC_VECTOR .
219
225
* The array is generated starting with the smaller digits.
220
226
* e.g. 12345678901234567890 => {34567890, 56789012, 1234}
221
227
*
@@ -229,28 +235,28 @@ static void bc_standard_mul(bc_num n1, size_t n1len, bc_num n2, size_t n2len, bc
229
235
const char * n2end = n2 -> n_value + n2len - 1 ;
230
236
size_t prodlen = n1len + n2len ;
231
237
232
- size_t n1_arr_size = (n1len + BC_MUL_UINT_DIGITS - 1 ) / BC_MUL_UINT_DIGITS ;
233
- size_t n2_arr_size = (n2len + BC_MUL_UINT_DIGITS - 1 ) / BC_MUL_UINT_DIGITS ;
238
+ size_t n1_arr_size = (n1len + BC_VECTOR_SIZE - 1 ) / BC_VECTOR_SIZE ;
239
+ size_t n2_arr_size = (n2len + BC_VECTOR_SIZE - 1 ) / BC_VECTOR_SIZE ;
234
240
size_t prod_arr_size = n1_arr_size + n2_arr_size - 1 ;
235
241
236
242
/*
237
- * let's say that N is the max of n1len and n2len (and a multiple of BC_MUL_UINT_DIGITS for simplicity),
238
- * then this sum is <= N/BC_MUL_UINT_DIGITS + N/BC_MUL_UINT_DIGITS + N/BC_MUL_UINT_DIGITS + N/BC_MUL_UINT_DIGITS - 1
239
- * which is equal to N - 1 if BC_MUL_UINT_DIGITS is 4, and N/2 - 1 if BC_MUL_UINT_DIGITS is 8.
243
+ * let's say that N is the max of n1len and n2len (and a multiple of BC_VECTOR_SIZE for simplicity),
244
+ * then this sum is <= N/BC_VECTOR_SIZE + N/BC_VECTOR_SIZE + N/BC_VECTOR_SIZE + N/BC_VECTOR_SIZE - 1
245
+ * which is equal to N - 1 if BC_VECTOR_SIZE is 4, and N/2 - 1 if BC_VECTOR_SIZE is 8.
240
246
*/
241
- BC_UINT_T * buf = safe_emalloc (n1_arr_size + n2_arr_size + prod_arr_size , sizeof (BC_UINT_T ), 0 );
247
+ BC_VECTOR * buf = safe_emalloc (n1_arr_size + n2_arr_size + prod_arr_size , sizeof (BC_VECTOR ), 0 );
242
248
243
- BC_UINT_T * n1_uint = buf ;
244
- BC_UINT_T * n2_uint = buf + n1_arr_size ;
245
- BC_UINT_T * prod_uint = n2_uint + n2_arr_size ;
249
+ BC_VECTOR * n1_vector = buf ;
250
+ BC_VECTOR * n2_vector = buf + n1_arr_size ;
251
+ BC_VECTOR * prod_vector = n2_vector + n2_arr_size ;
246
252
247
253
for (i = 0 ; i < prod_arr_size ; i ++ ) {
248
- prod_uint [i ] = 0 ;
254
+ prod_vector [i ] = 0 ;
249
255
}
250
256
251
257
/* Convert to uint[] */
252
- bc_convert_to_uint ( n1_uint , n1end , n1len );
253
- bc_convert_to_uint ( n2_uint , n2end , n2len );
258
+ bc_convert_to_vector ( n1_vector , n1end , n1len );
259
+ bc_convert_to_vector ( n2_vector , n2end , n2len );
254
260
255
261
/* Multiplication and addition */
256
262
size_t count = 0 ;
@@ -260,34 +266,34 @@ static void bc_standard_mul(bc_num n1, size_t n1len, bc_num n2, size_t n2len, bc
260
266
* When multiplying large numbers of digits, there is a possibility of
261
267
* overflow, so digit adjustment is performed beforehand.
262
268
*/
263
- if (UNEXPECTED (count >= BC_MUL_MAX_ADD_COUNT )) {
264
- bc_digits_adjustment (prod_uint , prod_arr_size );
269
+ if (UNEXPECTED (count >= BC_VECTOR_NO_OVERFLOW_ADD_COUNT )) {
270
+ bc_digits_adjustment (prod_vector , prod_arr_size );
265
271
count = 0 ;
266
272
}
267
273
count ++ ;
268
274
for (size_t j = 0 ; j < n2_arr_size ; j ++ ) {
269
- prod_uint [i + j ] += n1_uint [i ] * n2_uint [j ];
275
+ prod_vector [i + j ] += n1_vector [i ] * n2_vector [j ];
270
276
}
271
277
}
272
278
273
279
/*
274
280
* Move a value exceeding 4/8 digits by carrying to the next digit.
275
281
* However, the last digit does nothing.
276
282
*/
277
- bc_digits_adjustment (prod_uint , prod_arr_size );
283
+ bc_digits_adjustment (prod_vector , prod_arr_size );
278
284
279
285
/* Convert to bc_num */
280
286
* prod = bc_new_num_nonzeroed (prodlen , 0 );
281
287
char * pptr = (* prod )-> n_value ;
282
288
char * pend = pptr + prodlen - 1 ;
283
289
i = 0 ;
284
290
while (i < prod_arr_size - 1 ) {
285
- #if BC_MUL_UINT_DIGITS == 4
286
- bc_write_bcd_representation (prod_uint [i ], pend - 3 );
291
+ #if BC_VECTOR_SIZE == 4
292
+ bc_write_bcd_representation (prod_vector [i ], pend - 3 );
287
293
pend -= 4 ;
288
294
#else
289
- bc_write_bcd_representation (prod_uint [i ] / 10000 , pend - 7 );
290
- bc_write_bcd_representation (prod_uint [i ] % 10000 , pend - 3 );
295
+ bc_write_bcd_representation (prod_vector [i ] / 10000 , pend - 7 );
296
+ bc_write_bcd_representation (prod_vector [i ] % 10000 , pend - 3 );
291
297
pend -= 8 ;
292
298
#endif
293
299
i ++ ;
@@ -298,8 +304,8 @@ static void bc_standard_mul(bc_num n1, size_t n1len, bc_num n2, size_t n2len, bc
298
304
* Also need to fill it to the end with zeros, so loop until the end of the string.
299
305
*/
300
306
while (pend >= pptr ) {
301
- * pend -- = prod_uint [i ] % BASE ;
302
- prod_uint [i ] /= BASE ;
307
+ * pend -- = prod_vector [i ] % BASE ;
308
+ prod_vector [i ] /= BASE ;
303
309
}
304
310
305
311
efree (buf );
@@ -320,7 +326,7 @@ bc_num bc_multiply(bc_num n1, bc_num n2, size_t scale)
320
326
size_t prod_scale = MIN (full_scale , MAX (scale , MAX (n1 -> n_scale , n2 -> n_scale )));
321
327
322
328
/* Do the multiply */
323
- if (len1 <= BC_MUL_UINT_DIGITS && len2 <= BC_MUL_UINT_DIGITS ) {
329
+ if (len1 <= BC_VECTOR_SIZE && len2 <= BC_VECTOR_SIZE ) {
324
330
bc_fast_mul (n1 , len1 , n2 , len2 , & prod );
325
331
} else {
326
332
bc_standard_mul (n1 , len1 , n2 , len2 , & prod );
0 commit comments