From 884e909e47a04ada7da15eabf955beb258afef50 Mon Sep 17 00:00:00 2001 From: Saki Takamachi Date: Fri, 7 Mar 2025 11:23:43 +0900 Subject: [PATCH 01/10] replaced "quot_arr_size - 1" with quot_top_index --- ext/bcmath/libbcmath/src/div.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/bcmath/libbcmath/src/div.c b/ext/bcmath/libbcmath/src/div.c index ce9ae1e1dd792..d0d6eedae0c2e 100644 --- a/ext/bcmath/libbcmath/src/div.c +++ b/ext/bcmath/libbcmath/src/div.c @@ -51,7 +51,7 @@ static inline void bc_fast_div( { size_t numerator_top_index = numerator_arr_size - 1; size_t quot_top_index = quot_arr_size - 1; - for (size_t i = 0; i < quot_arr_size - 1; i++) { + for (size_t i = 0; i < quot_top_index; i++) { if (numerator_vectors[numerator_top_index - i] < divisor_vector) { quot_vectors[quot_top_index - i] = 0; /* numerator_vectors[numerator_top_index - i] < divisor_vector, so there will be no overflow. */ From 19e09bbf977e73b279b9867596c8ac083215e8e0 Mon Sep 17 00:00:00 2001 From: Saki Takamachi Date: Fri, 7 Mar 2025 12:12:33 +0900 Subject: [PATCH 02/10] moved POW_10_LUT to private.h --- ext/bcmath/libbcmath/src/div.c | 10 +++------- ext/bcmath/libbcmath/src/private.h | 9 +++++++++ 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/ext/bcmath/libbcmath/src/div.c b/ext/bcmath/libbcmath/src/div.c index d0d6eedae0c2e..c52a7c15f42d4 100644 --- a/ext/bcmath/libbcmath/src/div.c +++ b/ext/bcmath/libbcmath/src/div.c @@ -37,10 +37,6 @@ #include #include "zend_alloc.h" -static const BC_VECTOR POW_10_LUT[9] = { - 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000 -}; - /* * This function should be used when the divisor is not split into multiple chunks, i.e. when the size of the array is one. * This is because the algorithm can be simplified. @@ -174,8 +170,8 @@ static inline void bc_standard_div( divisor_top_digits = BC_VECTOR_SIZE; } - size_t high_part_shift = POW_10_LUT[BC_VECTOR_SIZE - divisor_top_digits + 1]; - size_t low_part_shift = POW_10_LUT[divisor_top_digits - 1]; + size_t high_part_shift = BC_POW_10_LUT[BC_VECTOR_SIZE - divisor_top_digits + 1]; + size_t low_part_shift = BC_POW_10_LUT[divisor_top_digits - 1]; BC_VECTOR divisor_high_part = divisor_vectors[divisor_top_index] * high_part_shift + divisor_vectors[divisor_top_index - 1] / low_part_shift; for (size_t i = 0; i < quot_arr_size; i++) { BC_VECTOR numerator_high_part = numerator_vectors[numerator_top_index - i] * high_part_shift + numerator_vectors[numerator_top_index - i - 1] / low_part_shift; @@ -281,7 +277,7 @@ static void bc_do_div( size_t numerator_read = 0; if (numerator_bottom_read_len < BC_VECTOR_SIZE) { numerator_read = MIN(numerator_bottom_read_len, numerator_readable_len); - base = POW_10_LUT[numerator_bottom_extension]; + base = BC_POW_10_LUT[numerator_bottom_extension]; numerator_vectors[numerator_vector_count] = 0; for (size_t i = 0; i < numerator_read; i++) { numerator_vectors[numerator_vector_count] += *numerator * base; diff --git a/ext/bcmath/libbcmath/src/private.h b/ext/bcmath/libbcmath/src/private.h index 5c0087901a4a2..1a911442dc9a1 100644 --- a/ext/bcmath/libbcmath/src/private.h +++ b/ext/bcmath/libbcmath/src/private.h @@ -35,6 +35,9 @@ #include #include "zend_portability.h" +#ifndef _BCMATH_PRIV_H_ +#define _BCMATH_PRIV_H_ + /* This will be 0x01010101 for 32-bit and 0x0101010101010101 for 64-bit */ #define SWAR_ONES (~((size_t) 0) / 0xFF) /* This repeats a byte `x` into an entire 32/64-bit word. @@ -67,9 +70,15 @@ */ #define BC_VECTOR_NO_OVERFLOW_ADD_COUNT (~((BC_VECTOR) 0) / (BC_VECTOR_BOUNDARY_NUM * BC_VECTOR_BOUNDARY_NUM)) +static const BC_VECTOR BC_POW_10_LUT[9] = { + 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000 +}; + /* routines */ bcmath_compare_result _bc_do_compare (bc_num n1, bc_num n2, size_t scale, bool use_sign); bc_num _bc_do_add (bc_num n1, bc_num n2); bc_num _bc_do_sub (bc_num n1, bc_num n2); void _bc_rm_leading_zeros (bc_num num); + +#endif From d0167431f62dd919d151549f42de4cc6bdf36fc8 Mon Sep 17 00:00:00 2001 From: Saki Takamachi Date: Sat, 8 Mar 2025 01:35:38 +0900 Subject: [PATCH 03/10] Refactored divide --- ext/bcmath/libbcmath/src/convert.h | 28 ++++ ext/bcmath/libbcmath/src/div.c | 218 ++++++++++------------------- 2 files changed, 102 insertions(+), 144 deletions(-) diff --git a/ext/bcmath/libbcmath/src/convert.h b/ext/bcmath/libbcmath/src/convert.h index 6ddd447c8048e..da6c5fc162c38 100644 --- a/ext/bcmath/libbcmath/src/convert.h +++ b/ext/bcmath/libbcmath/src/convert.h @@ -57,4 +57,32 @@ static inline void bc_convert_to_vector(BC_VECTOR *n_vector, const char *nend, s } } +static inline void bc_convert_to_vector_with_zero_pad(BC_VECTOR *n_vector, const char *nend, size_t nlen, size_t zeros) +{ + while (zeros >= BC_VECTOR_SIZE) { + *n_vector = 0; + n_vector++; + zeros -= BC_VECTOR_SIZE; + } + + if (zeros > 0) { + *n_vector = 0; + BC_VECTOR base = BC_POW_10_LUT[zeros]; + size_t tmp_len = MIN(BC_VECTOR_SIZE - zeros, nlen); + for (size_t i = 0; i < tmp_len; i++) { + *n_vector += *nend * base; + base *= BASE; + nend--; + } + n_vector++; + nlen -= tmp_len; + } + + if (nlen == 0) { + return; + } + + bc_convert_to_vector(n_vector, nend, nlen); +} + #endif diff --git a/ext/bcmath/libbcmath/src/div.c b/ext/bcmath/libbcmath/src/div.c index c52a7c15f42d4..74191a5172766 100644 --- a/ext/bcmath/libbcmath/src/div.c +++ b/ext/bcmath/libbcmath/src/div.c @@ -251,58 +251,39 @@ static inline void bc_standard_div( } static void bc_do_div( - const char *numerator, size_t numerator_readable_len, size_t numerator_bottom_extension, - const char *divisor, size_t divisor_len, bc_num *quot, size_t quot_len + const char *numerator, size_t numerator_size, size_t numerator_readable_size, + const char *divisor, size_t divisor_size, + bc_num *quot, size_t quot_size ) { - size_t divisor_arr_size = (divisor_len + BC_VECTOR_SIZE - 1) / BC_VECTOR_SIZE; - size_t numerator_arr_size = (numerator_readable_len + numerator_bottom_extension + BC_VECTOR_SIZE - 1) / BC_VECTOR_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 quot_arr_size = numerator_arr_size - divisor_arr_size + 1; - size_t quot_real_arr_size = MIN(quot_arr_size, (quot_len + BC_VECTOR_SIZE - 1) / BC_VECTOR_SIZE); + size_t quot_real_arr_size = MIN(quot_arr_size, (quot_size + BC_VECTOR_SIZE - 1) / BC_VECTOR_SIZE); BC_VECTOR *numerator_vectors = safe_emalloc(numerator_arr_size + divisor_arr_size + quot_arr_size, sizeof(BC_VECTOR), 0); BC_VECTOR *divisor_vectors = numerator_vectors + numerator_arr_size; BC_VECTOR *quot_vectors = divisor_vectors + divisor_arr_size; - /* Fill with zeros and convert as many vector elements as needed */ - size_t numerator_vector_count = 0; - while (numerator_bottom_extension >= BC_VECTOR_SIZE) { - numerator_vectors[numerator_vector_count] = 0; - numerator_bottom_extension -= BC_VECTOR_SIZE; - numerator_vector_count++; - } - - size_t numerator_bottom_read_len = BC_VECTOR_SIZE - numerator_bottom_extension; - - size_t base; - size_t numerator_read = 0; - if (numerator_bottom_read_len < BC_VECTOR_SIZE) { - numerator_read = MIN(numerator_bottom_read_len, numerator_readable_len); - base = BC_POW_10_LUT[numerator_bottom_extension]; - numerator_vectors[numerator_vector_count] = 0; - for (size_t i = 0; i < numerator_read; i++) { - numerator_vectors[numerator_vector_count] += *numerator * base; - base *= BASE; - numerator--; - } - numerator_vector_count++; - } + size_t numerator_extension = numerator_size > numerator_readable_size ? numerator_size - numerator_readable_size : 0; /* Bulk convert numerator and divisor to vectors */ - if (numerator_readable_len > numerator_read) { - bc_convert_to_vector(numerator_vectors + numerator_vector_count, numerator, numerator_readable_len - numerator_read); - } - bc_convert_to_vector(divisor_vectors, divisor, divisor_len); + size_t numerator_use_size = numerator_size - numerator_extension; + const char *numerator_end = numerator + numerator_use_size - 1; + bc_convert_to_vector_with_zero_pad(numerator_vectors, numerator_end, numerator_use_size, numerator_extension); + + const char *divisor_end = divisor + divisor_size - 1; + bc_convert_to_vector(divisor_vectors, divisor_end, divisor_size); /* Do the division */ if (divisor_arr_size == 1) { bc_fast_div(numerator_vectors, numerator_arr_size, divisor_vectors[0], quot_vectors, quot_arr_size); } else { - bc_standard_div(numerator_vectors, numerator_arr_size, divisor_vectors, divisor_arr_size, divisor_len, quot_vectors, quot_arr_size); + bc_standard_div(numerator_vectors, numerator_arr_size, divisor_vectors, divisor_arr_size, divisor_size, quot_vectors, quot_arr_size); } /* Convert to bc_num */ char *qptr = (*quot)->n_value; - char *qend = qptr + quot_len - 1; + char *qend = qptr + (*quot)->n_len + (*quot)->n_scale - 1; size_t i; for (i = 0; i < quot_real_arr_size - 1; i++) { @@ -332,166 +313,115 @@ bool bc_divide(bc_num numerator, bc_num divisor, bc_num *quot, size_t scale) } bc_free_num(quot); + size_t quot_scale = scale; /* If numerator is zero, the quotient is always zero. */ if (bc_is_zero(numerator)) { - *quot = bc_copy_num(BCG(_zero_)); - return true; + goto quot_zero; } /* If divisor is 1 / -1, the quotient's n_value is equal to numerator's n_value. */ if (_bc_do_compare(divisor, BCG(_one_), divisor->n_scale, false) == BCMATH_EQUAL) { - size_t quot_scale = MIN(numerator->n_scale, scale); + quot_scale = MIN(numerator->n_scale, quot_scale); *quot = bc_new_num_nonzeroed(numerator->n_len, quot_scale); char *qptr = (*quot)->n_value; memcpy(qptr, numerator->n_value, numerator->n_len + quot_scale); (*quot)->n_sign = numerator->n_sign == divisor->n_sign ? PLUS : MINUS; - _bc_rm_leading_zeros(*quot); return true; } char *numeratorptr = numerator->n_value; - char *numeratorend = numeratorptr + numerator->n_len + numerator->n_scale - 1; - size_t numerator_len = numerator->n_len; - size_t numerator_scale = numerator->n_scale; + size_t numerator_size = numerator->n_len + quot_scale + divisor->n_scale; char *divisorptr = divisor->n_value; - char *divisorend = divisorptr + divisor->n_len + divisor->n_scale - 1; - size_t divisor_len = divisor->n_len; - size_t divisor_scale = divisor->n_scale; - size_t divisor_int_right_zeros = 0; - - /* remove divisor trailing zeros */ - while (*divisorend == 0 && divisor_scale > 0) { - divisorend--; - divisor_scale--; - } - while (*divisorend == 0) { - divisorend--; - divisor_int_right_zeros++; - } + size_t divisor_size = divisor->n_len + divisor->n_scale; - if (*numeratorptr == 0 && numerator_len == 1) { + /* check and remove numerator leading zeros */ + size_t numerator_leading_zeros = 0; + while (*numeratorptr == 0) { numeratorptr++; - numerator_len = 0; + numerator_leading_zeros++; } - - size_t numerator_top_extension = 0; - size_t numerator_bottom_extension = 0; - if (divisor_scale > 0) { - /* - * e.g. divisor_scale = 4 - * divisor = .0002, to be 2 or divisor = 200.001, to be 200001 - * numerator = .03, to be 300 or numerator = .000003, to be .03 - * numerator may become longer than the original data length due to the addition of - * trailing zeros in the integer part. - */ - numerator_len += divisor_scale; - numerator_bottom_extension = numerator_scale < divisor_scale ? divisor_scale - numerator_scale : 0; - numerator_scale = numerator_scale > divisor_scale ? numerator_scale - divisor_scale : 0; - divisor_len += divisor_scale; - divisor_scale = 0; - } else if (divisor_int_right_zeros > 0) { - /* - * e.g. divisor_int_right_zeros = 4 - * divisor = 2000, to be 2 - * numerator = 30, to be .03 or numerator = 30000, to be 30 - * Also, numerator may become longer than the original data length due to the addition of - * leading zeros in the fractional part. - */ - numerator_top_extension = numerator_len < divisor_int_right_zeros ? divisor_int_right_zeros - numerator_len : 0; - numerator_len = numerator_len > divisor_int_right_zeros ? numerator_len - divisor_int_right_zeros : 0; - numerator_scale += divisor_int_right_zeros; - divisor_len -= divisor_int_right_zeros; - divisor_scale = 0; + if (numerator_size > numerator_leading_zeros) { + numerator_size -= numerator_leading_zeros; + } else { + goto quot_zero; } - /* remove numerator leading zeros */ - while (*numeratorptr == 0 && numerator_len > 0) { - numeratorptr++; - numerator_len--; - } - /* remove divisor leading zeros */ + /* check and remove divisor leading zeros */ while (*divisorptr == 0) { divisorptr++; - divisor_len--; + divisor_size--; } - /* Considering the scale specification, the quotient is always 0 if this condition is met */ - if (divisor_len > numerator_len + scale) { - *quot = bc_copy_num(BCG(_zero_)); - return true; + if (divisor_size > numerator_size) { + goto quot_zero; } - /* Length of numerator data that can be read */ - size_t numerator_readable_len = numeratorend - numeratorptr + 1; - - /* set scale to numerator */ - if (numerator_scale > scale) { - size_t scale_diff = numerator_scale - scale; - if (numerator_bottom_extension > scale_diff) { - numerator_bottom_extension -= scale_diff; - } else { - numerator_bottom_extension = 0; - if (EXPECTED(numerator_readable_len > scale_diff)) { - numerator_readable_len -= scale_diff; - numeratorend -= scale_diff; - } else { - numerator_readable_len = 0; - numeratorend = numeratorptr; - } + /* check and remove divisor trailing zeros. The divisor is not 0, so leave only one digit */ + size_t divisor_trailing_zeros = 0; + for (size_t i = divisor_size - 1; i > 0; i--) { + if (divisorptr[i] != 0) { + break; } - numerator_top_extension = MIN(numerator_top_extension, scale); + divisor_trailing_zeros++; + } + divisor_size -= divisor_trailing_zeros; + + if (numerator_size > divisor_trailing_zeros) { + numerator_size -= divisor_trailing_zeros; } else { - numerator_bottom_extension += scale - numerator_scale; + goto quot_zero; } - numerator_scale = scale; - if (divisor_len > numerator_readable_len + numerator_bottom_extension) { - *quot = bc_copy_num(BCG(_zero_)); - return true; + size_t quot_size = numerator_size - divisor_size + 1; /* numerator_size >= divisor_size */ + if (quot_size > quot_scale) { + *quot = bc_new_num_nonzeroed(quot_size - quot_scale, quot_scale); + } else { + *quot = bc_new_num_nonzeroed(1, quot_scale); /* 1 is for 0 */ } - /* If divisor is 1 here, return the result of adjusting the decimal point position of numerator. */ - if (divisor_len == 1 && *divisorptr == 1) { - if (numerator_len == 0) { - numerator_len = 1; - numerator_top_extension++; - } - size_t quot_scale = numerator_scale > numerator_bottom_extension ? numerator_scale - numerator_bottom_extension : 0; - numerator_bottom_extension = numerator_scale < numerator_bottom_extension ? numerator_bottom_extension - numerator_scale : 0; + /* Size that can be read from numeratorptr */ + size_t numerator_readable_size = numerator->n_len + numerator->n_scale - numerator_leading_zeros; - *quot = bc_new_num_nonzeroed(numerator_len, quot_scale); + /* If divisor is 1 here, return the result of adjusting the decimal point position of numerator. */ + if (divisor_size == 1 && *divisorptr == 1) { char *qptr = (*quot)->n_value; - for (size_t i = 0; i < numerator_top_extension; i++) { + if (quot_size <= quot_scale) { + /* int is 0 */ *qptr++ = 0; + for (size_t i = quot_size; i < quot_scale; i++) { + *qptr++ = 0; + } } - memcpy(qptr, numeratorptr, numerator_readable_len); - qptr += numerator_readable_len; - for (size_t i = 0; i < numerator_bottom_extension; i++) { + size_t numerator_use_size = quot_size > numerator_readable_size ? numerator_readable_size : quot_size; + memcpy(qptr, numeratorptr, numerator_use_size); + qptr += numerator_use_size; + for (size_t i = 0; i < quot_size - numerator_use_size; i++) { *qptr++ = 0; } + bc_rm_trailing_zeros(*quot); (*quot)->n_sign = numerator->n_sign == divisor->n_sign ? PLUS : MINUS; return true; } - size_t quot_full_len; - if (divisor_len > numerator_len) { - *quot = bc_new_num_nonzeroed(1, scale); - quot_full_len = 1 + scale; - } else { - *quot = bc_new_num_nonzeroed(numerator_len - divisor_len + 1, scale); - quot_full_len = numerator_len - divisor_len + 1 + scale; - } - /* do divide */ - bc_do_div(numeratorend, numerator_readable_len, numerator_bottom_extension, divisorend, divisor_len, quot, quot_full_len); + bc_do_div( + numeratorptr, numerator_size, numerator_readable_size, + divisorptr, divisor_size, + quot, quot_size + ); + _bc_rm_leading_zeros(*quot); if (bc_is_zero(*quot)) { - (*quot)->n_sign = PLUS; + bc_free_num(quot); + goto quot_zero; } else { (*quot)->n_sign = numerator->n_sign == divisor->n_sign ? PLUS : MINUS; } + return true; +quot_zero: + *quot = bc_copy_num(BCG(_zero_)); return true; } From da0916ca700d2e0666ed45742b1bded2ce04e2da Mon Sep 17 00:00:00 2001 From: Saki Takamachi Date: Sat, 8 Mar 2025 20:28:13 +0900 Subject: [PATCH 04/10] Made it a little easier to see and avoid unnecessary zero padding in early return cases --- ext/bcmath/libbcmath/src/div.c | 59 ++++++++++++++++++++++------------ 1 file changed, 39 insertions(+), 20 deletions(-) diff --git a/ext/bcmath/libbcmath/src/div.c b/ext/bcmath/libbcmath/src/div.c index 74191a5172766..3a69cbe4f6970 100644 --- a/ext/bcmath/libbcmath/src/div.c +++ b/ext/bcmath/libbcmath/src/div.c @@ -305,6 +305,42 @@ static void bc_do_div( efree(numerator_vectors); } +static inline void bc_divide_by_one(bc_num numerator, bc_num *quot, size_t quot_scale) +{ + quot_scale = MIN(numerator->n_scale, quot_scale); + *quot = bc_new_num_nonzeroed(numerator->n_len, quot_scale); + char *qptr = (*quot)->n_value; + memcpy(qptr, numerator->n_value, numerator->n_len + quot_scale); +} + +static inline void bc_divide_by_pow_10( + const char *numeratorptr, size_t numerator_readable_size, bc_num *quot, size_t quot_size, size_t quot_scale) +{ + char *qptr = (*quot)->n_value; + if (quot_size <= quot_scale) { + /* int is 0 */ + *qptr++ = 0; + for (size_t i = quot_size; i < quot_scale; i++) { + *qptr++ = 0; + } + } + + size_t numerator_use_size = quot_size > numerator_readable_size ? numerator_readable_size : quot_size; + memcpy(qptr, numeratorptr, numerator_use_size); + qptr += numerator_use_size; + + if (numerator_use_size < (*quot)->n_len) { + /* e.g. 12.3 / 0.01 <=> 1230 */ + for (size_t i = numerator_use_size; i < (*quot)->n_len; i++) { + *qptr++ = 0; + } + (*quot)->n_scale = 0; + } else { + char *qend = (*quot)->n_value + (*quot)->n_len + (*quot)->n_scale; + (*quot)->n_scale -= qend - qptr; + } +} + bool bc_divide(bc_num numerator, bc_num divisor, bc_num *quot, size_t scale) { /* divide by zero */ @@ -322,10 +358,7 @@ bool bc_divide(bc_num numerator, bc_num divisor, bc_num *quot, size_t scale) /* If divisor is 1 / -1, the quotient's n_value is equal to numerator's n_value. */ if (_bc_do_compare(divisor, BCG(_one_), divisor->n_scale, false) == BCMATH_EQUAL) { - quot_scale = MIN(numerator->n_scale, quot_scale); - *quot = bc_new_num_nonzeroed(numerator->n_len, quot_scale); - char *qptr = (*quot)->n_value; - memcpy(qptr, numerator->n_value, numerator->n_len + quot_scale); + bc_divide_by_one(numerator, quot, quot_scale); (*quot)->n_sign = numerator->n_sign == divisor->n_sign ? PLUS : MINUS; return true; } @@ -386,22 +419,8 @@ bool bc_divide(bc_num numerator, bc_num divisor, bc_num *quot, size_t scale) /* If divisor is 1 here, return the result of adjusting the decimal point position of numerator. */ if (divisor_size == 1 && *divisorptr == 1) { - char *qptr = (*quot)->n_value; - if (quot_size <= quot_scale) { - /* int is 0 */ - *qptr++ = 0; - for (size_t i = quot_size; i < quot_scale; i++) { - *qptr++ = 0; - } - } - size_t numerator_use_size = quot_size > numerator_readable_size ? numerator_readable_size : quot_size; - memcpy(qptr, numeratorptr, numerator_use_size); - qptr += numerator_use_size; - for (size_t i = 0; i < quot_size - numerator_use_size; i++) { - *qptr++ = 0; - } - bc_rm_trailing_zeros(*quot); - (*quot)->n_sign = numerator->n_sign == divisor->n_sign ? PLUS : MINUS; + bc_divide_by_pow_10(numeratorptr, numerator_readable_size, quot, quot_size, quot_scale); + (*quot)->n_sign = numerator->n_sign == divisor->n_sign ? PLUS : MINUS;; return true; } From 8ea5dd604e907a263622a9175faf081c42479ac7 Mon Sep 17 00:00:00 2001 From: Saki Takamachi Date: Mon, 10 Mar 2025 10:55:06 +0900 Subject: [PATCH 05/10] At the end of the process, the code for when quot is 0 is restored. --- ext/bcmath/libbcmath/src/div.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ext/bcmath/libbcmath/src/div.c b/ext/bcmath/libbcmath/src/div.c index 3a69cbe4f6970..6886887981d8c 100644 --- a/ext/bcmath/libbcmath/src/div.c +++ b/ext/bcmath/libbcmath/src/div.c @@ -433,8 +433,8 @@ bool bc_divide(bc_num numerator, bc_num divisor, bc_num *quot, size_t scale) _bc_rm_leading_zeros(*quot); if (bc_is_zero(*quot)) { - bc_free_num(quot); - goto quot_zero; + (*quot)->n_sign = PLUS; + (*quot)->n_scale = 0; } else { (*quot)->n_sign = numerator->n_sign == divisor->n_sign ? PLUS : MINUS; } From 8ecf97445df083b6bce04382aae95a4b69c8b169 Mon Sep 17 00:00:00 2001 From: Saki Takamachi Date: Mon, 10 Mar 2025 23:30:08 +0900 Subject: [PATCH 06/10] typo --- ext/bcmath/libbcmath/src/div.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/bcmath/libbcmath/src/div.c b/ext/bcmath/libbcmath/src/div.c index 6886887981d8c..e595ce690f87d 100644 --- a/ext/bcmath/libbcmath/src/div.c +++ b/ext/bcmath/libbcmath/src/div.c @@ -420,7 +420,7 @@ bool bc_divide(bc_num numerator, bc_num divisor, bc_num *quot, size_t scale) /* If divisor is 1 here, return the result of adjusting the decimal point position of numerator. */ if (divisor_size == 1 && *divisorptr == 1) { bc_divide_by_pow_10(numeratorptr, numerator_readable_size, quot, quot_size, quot_scale); - (*quot)->n_sign = numerator->n_sign == divisor->n_sign ? PLUS : MINUS;; + (*quot)->n_sign = numerator->n_sign == divisor->n_sign ? PLUS : MINUS; return true; } From 56a90280e6044f247ebd5e5edd71264cd400f8a0 Mon Sep 17 00:00:00 2001 From: Saki Takamachi <34942839+SakiTakamachi@users.noreply.github.com> Date: Thu, 13 Mar 2025 11:16:20 +0900 Subject: [PATCH 07/10] Simpler code suggestions Co-authored-by: Niels Dossche <7771979+nielsdos@users.noreply.github.com> --- ext/bcmath/libbcmath/src/div.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/ext/bcmath/libbcmath/src/div.c b/ext/bcmath/libbcmath/src/div.c index e595ce690f87d..ec7619fb77090 100644 --- a/ext/bcmath/libbcmath/src/div.c +++ b/ext/bcmath/libbcmath/src/div.c @@ -317,12 +317,8 @@ static inline void bc_divide_by_pow_10( const char *numeratorptr, size_t numerator_readable_size, bc_num *quot, size_t quot_size, size_t quot_scale) { char *qptr = (*quot)->n_value; - if (quot_size <= quot_scale) { - /* int is 0 */ + for (size_t i = quot_size; i <= quot_scale; i++) { *qptr++ = 0; - for (size_t i = quot_size; i < quot_scale; i++) { - *qptr++ = 0; - } } size_t numerator_use_size = quot_size > numerator_readable_size ? numerator_readable_size : quot_size; From 1c9199d09e23a360a630823df55abfa120abbd15 Mon Sep 17 00:00:00 2001 From: Saki Takamachi Date: Thu, 13 Mar 2025 11:31:23 +0900 Subject: [PATCH 08/10] Address comments --- ext/bcmath/libbcmath/src/convert.h | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/ext/bcmath/libbcmath/src/convert.h b/ext/bcmath/libbcmath/src/convert.h index da6c5fc162c38..e278ae5fef1aa 100644 --- a/ext/bcmath/libbcmath/src/convert.h +++ b/ext/bcmath/libbcmath/src/convert.h @@ -34,11 +34,11 @@ static inline BC_VECTOR bc_partial_convert_to_vector(const char *n, size_t len) } BC_VECTOR num = 0; - BC_VECTOR base = 1; + BC_VECTOR digit_base_value = 1; for (size_t i = 0; i < len; i++) { - num += *n * base; - base *= BASE; + num += *n * digit_base_value; + digit_base_value *= BASE; n--; } @@ -67,15 +67,15 @@ static inline void bc_convert_to_vector_with_zero_pad(BC_VECTOR *n_vector, const if (zeros > 0) { *n_vector = 0; - BC_VECTOR base = BC_POW_10_LUT[zeros]; - size_t tmp_len = MIN(BC_VECTOR_SIZE - zeros, nlen); - for (size_t i = 0; i < tmp_len; i++) { - *n_vector += *nend * base; - base *= BASE; + BC_VECTOR digit_base_value = BC_POW_10_LUT[zeros]; + size_t len_to_write = MIN(BC_VECTOR_SIZE - zeros, nlen); + for (size_t i = 0; i < len_to_write; i++) { + *n_vector += *nend * digit_base_value; + digit_base_value *= BASE; nend--; } n_vector++; - nlen -= tmp_len; + nlen -= len_to_write; } if (nlen == 0) { From 5ed3c74662214ec461e99f87004597cd5588e9be Mon Sep 17 00:00:00 2001 From: Saki Takamachi Date: Thu, 13 Mar 2025 11:56:09 +0900 Subject: [PATCH 09/10] (*quot)->n_scale = 0; into a separate PR. --- ext/bcmath/libbcmath/src/div.c | 1 - 1 file changed, 1 deletion(-) diff --git a/ext/bcmath/libbcmath/src/div.c b/ext/bcmath/libbcmath/src/div.c index ec7619fb77090..cda452569dedc 100644 --- a/ext/bcmath/libbcmath/src/div.c +++ b/ext/bcmath/libbcmath/src/div.c @@ -430,7 +430,6 @@ bool bc_divide(bc_num numerator, bc_num divisor, bc_num *quot, size_t scale) _bc_rm_leading_zeros(*quot); if (bc_is_zero(*quot)) { (*quot)->n_sign = PLUS; - (*quot)->n_scale = 0; } else { (*quot)->n_sign = numerator->n_sign == divisor->n_sign ? PLUS : MINUS; } From ff28c14e1fdf122ad05eef0f701f5eeb4bbdcd4f Mon Sep 17 00:00:00 2001 From: Saki Takamachi Date: Fri, 14 Mar 2025 08:52:45 +0900 Subject: [PATCH 10/10] [skip ci] NEWS --- NEWS | 3 +++ 1 file changed, 3 insertions(+) diff --git a/NEWS b/NEWS index cf57d0a36b676..a654ea866873f 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,9 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ?? ??? ????, PHP 8.5.0alpha1 +- BCMath: + . Simplify `bc_divide()` code. (SakiTakamachi) + - CLI: . Add --ini=diff to print INI settings changed from the builtin default. (timwolla)