diff --git a/ext/bcmath/libbcmath/src/convert.h b/ext/bcmath/libbcmath/src/convert.h index e278ae5fef1aa..73c38cd130107 100644 --- a/ext/bcmath/libbcmath/src/convert.h +++ b/ext/bcmath/libbcmath/src/convert.h @@ -85,4 +85,30 @@ static inline void bc_convert_to_vector_with_zero_pad(BC_VECTOR *n_vector, const bc_convert_to_vector(n_vector, nend, nlen); } +static inline void bc_convert_vector_to_char(const BC_VECTOR *vector, char *nptr, char *nend, size_t arr_size) +{ + size_t i = 0; + while (i < arr_size - 1) { +#if BC_VECTOR_SIZE == 4 + bc_write_bcd_representation(vector[i], nend - 3); + nend -= 4; +#else + bc_write_bcd_representation(vector[i] / 10000, nend - 7); + bc_write_bcd_representation(vector[i] % 10000, nend - 3); + nend -= 8; +#endif + i++; + } + + /* + * The last digit may carry over. + * Also need to fill it to the end with zeros, so loop until the end of the string. + */ + BC_VECTOR last = vector[i]; + while (nend >= nptr) { + *nend-- = last % BASE; + last /= BASE; + } +} + #endif diff --git a/ext/bcmath/libbcmath/src/div.c b/ext/bcmath/libbcmath/src/div.c index 7da023df9a7e4..1cf8a434c8608 100644 --- a/ext/bcmath/libbcmath/src/div.c +++ b/ext/bcmath/libbcmath/src/div.c @@ -255,10 +255,10 @@ static void bc_do_div( const char *divisor, size_t divisor_size, bc_num *quot, size_t quot_size ) { - size_t numerator_arr_size = (numerator_size + BC_VECTOR_SIZE - 1) / BC_VECTOR_SIZE; - size_t divisor_arr_size = (divisor_size + BC_VECTOR_SIZE - 1) / BC_VECTOR_SIZE; + size_t numerator_arr_size = BC_ARR_SIZE_FROM_LEN(numerator_size); + size_t divisor_arr_size = BC_ARR_SIZE_FROM_LEN(divisor_size); size_t quot_arr_size = numerator_arr_size - divisor_arr_size + 1; - size_t quot_real_arr_size = MIN(quot_arr_size, (quot_size + BC_VECTOR_SIZE - 1) / BC_VECTOR_SIZE); + size_t quot_real_arr_size = MIN(quot_arr_size, BC_ARR_SIZE_FROM_LEN(quot_size)); BC_VECTOR stack_vectors[BC_STACK_VECTOR_SIZE]; size_t allocation_arr_size = numerator_arr_size + divisor_arr_size + quot_arr_size; @@ -293,22 +293,7 @@ static void bc_do_div( char *qptr = (*quot)->n_value; char *qend = qptr + (*quot)->n_len + (*quot)->n_scale - 1; - size_t i; - for (i = 0; i < quot_real_arr_size - 1; i++) { -#if BC_VECTOR_SIZE == 4 - bc_write_bcd_representation(quot_vectors[i], qend - 3); - qend -= 4; -#else - bc_write_bcd_representation(quot_vectors[i] / 10000, qend - 7); - bc_write_bcd_representation(quot_vectors[i] % 10000, qend - 3); - qend -= 8; -#endif - } - - while (qend >= qptr) { - *qend-- = quot_vectors[i] % BASE; - quot_vectors[i] /= BASE; - } + bc_convert_vector_to_char(quot_vectors, qptr, qend, quot_real_arr_size); if (allocation_arr_size > BC_STACK_VECTOR_SIZE) { efree(numerator_vectors); diff --git a/ext/bcmath/libbcmath/src/private.h b/ext/bcmath/libbcmath/src/private.h index 7e972952c75e3..91facfb2f8b40 100644 --- a/ext/bcmath/libbcmath/src/private.h +++ b/ext/bcmath/libbcmath/src/private.h @@ -67,6 +67,8 @@ /* 64-bytes for 64-bit */ #define BC_STACK_VECTOR_SIZE 8 +#define BC_ARR_SIZE_FROM_LEN(len) (((len) + BC_VECTOR_SIZE - 1) / BC_VECTOR_SIZE) + /* * Adding more than this many times may cause uint32_t/uint64_t to overflow. * Typically this is 1844 for 64bit and 42 for 32bit. diff --git a/ext/bcmath/libbcmath/src/recmul.c b/ext/bcmath/libbcmath/src/recmul.c index fc7efb37ebf02..26ce1641db410 100644 --- a/ext/bcmath/libbcmath/src/recmul.c +++ b/ext/bcmath/libbcmath/src/recmul.c @@ -107,27 +107,8 @@ static inline void bc_mul_finish_from_vector(BC_VECTOR *prod_vector, size_t prod *prod = bc_new_num_nonzeroed(prodlen, 0); char *pptr = (*prod)->n_value; char *pend = pptr + prodlen - 1; - size_t i = 0; - while (i < prod_arr_size - 1) { -#if BC_VECTOR_SIZE == 4 - bc_write_bcd_representation(prod_vector[i], pend - 3); - pend -= 4; -#else - bc_write_bcd_representation(prod_vector[i] / 10000, pend - 7); - bc_write_bcd_representation(prod_vector[i] % 10000, pend - 3); - pend -= 8; -#endif - i++; - } - /* - * The last digit may carry over. - * Also need to fill it to the end with zeros, so loop until the end of the string. - */ - while (pend >= pptr) { - *pend-- = prod_vector[i] % BASE; - prod_vector[i] /= BASE; - } + bc_convert_vector_to_char(prod_vector, pptr, pend, prod_arr_size); } /* @@ -145,9 +126,9 @@ static void bc_standard_mul(bc_num n1, size_t n1len, bc_num n2, size_t n2len, bc const char *n2end = n2->n_value + n2len - 1; size_t prodlen = n1len + n2len; - size_t n1_arr_size = (n1len + BC_VECTOR_SIZE - 1) / BC_VECTOR_SIZE; - size_t n2_arr_size = (n2len + BC_VECTOR_SIZE - 1) / BC_VECTOR_SIZE; - size_t prod_arr_size = (prodlen + BC_VECTOR_SIZE - 1) / BC_VECTOR_SIZE; + size_t n1_arr_size = BC_ARR_SIZE_FROM_LEN(n1len); + size_t n2_arr_size = BC_ARR_SIZE_FROM_LEN(n2len); + size_t prod_arr_size = BC_ARR_SIZE_FROM_LEN(prodlen); BC_VECTOR stack_vectors[BC_STACK_VECTOR_SIZE]; size_t allocation_arr_size = n1_arr_size + n2_arr_size + prod_arr_size; @@ -206,8 +187,8 @@ static void bc_standard_square(bc_num n1, size_t n1len, bc_num *prod) const char *n1end = n1->n_value + n1len - 1; size_t prodlen = n1len + n1len; - size_t n1_arr_size = (n1len + BC_VECTOR_SIZE - 1) / BC_VECTOR_SIZE; - size_t prod_arr_size = (prodlen + BC_VECTOR_SIZE - 1) / BC_VECTOR_SIZE; + size_t n1_arr_size = BC_ARR_SIZE_FROM_LEN(n1len); + size_t prod_arr_size = BC_ARR_SIZE_FROM_LEN(prodlen); BC_VECTOR *buf = safe_emalloc(n1_arr_size + n1_arr_size + prod_arr_size, sizeof(BC_VECTOR), 0);