From b05dd801541978931c532eb3bb7898cc523898bb Mon Sep 17 00:00:00 2001 From: Saki Takamachi Date: Fri, 14 Mar 2025 10:04:44 +0900 Subject: [PATCH 1/4] If the result is 0, n_scale is set to 0. --- ext/bcmath/libbcmath/src/div.c | 1 + ext/bcmath/libbcmath/src/divmod.c | 1 + ext/bcmath/libbcmath/src/recmul.c | 1 + ext/bcmath/libbcmath/src/round.c | 1 + 4 files changed, 4 insertions(+) diff --git a/ext/bcmath/libbcmath/src/div.c b/ext/bcmath/libbcmath/src/div.c index cda452569dedc..ec7619fb77090 100644 --- a/ext/bcmath/libbcmath/src/div.c +++ b/ext/bcmath/libbcmath/src/div.c @@ -430,6 +430,7 @@ 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; } diff --git a/ext/bcmath/libbcmath/src/divmod.c b/ext/bcmath/libbcmath/src/divmod.c index 294a281b2e687..477ec30e916ea 100644 --- a/ext/bcmath/libbcmath/src/divmod.c +++ b/ext/bcmath/libbcmath/src/divmod.c @@ -74,6 +74,7 @@ bool bc_divmod(bc_num num1, bc_num num2, bc_num *quot, bc_num *rem, size_t scale (*rem)->n_scale = MIN(scale, (*rem)->n_scale); if (bc_is_zero(*rem)) { (*rem)->n_sign = PLUS; + (*rem)->n_scale = 0; } return true; diff --git a/ext/bcmath/libbcmath/src/recmul.c b/ext/bcmath/libbcmath/src/recmul.c index b92a1045ac3b5..de06a4ca037ec 100644 --- a/ext/bcmath/libbcmath/src/recmul.c +++ b/ext/bcmath/libbcmath/src/recmul.c @@ -264,6 +264,7 @@ bc_num bc_multiply(bc_num n1, bc_num n2, size_t scale) _bc_rm_leading_zeros(prod); if (bc_is_zero(prod)) { prod->n_sign = PLUS; + prod->n_scale = 0; } return prod; } diff --git a/ext/bcmath/libbcmath/src/round.c b/ext/bcmath/libbcmath/src/round.c index ac3c7c41a315e..5229009a3f12d 100644 --- a/ext/bcmath/libbcmath/src/round.c +++ b/ext/bcmath/libbcmath/src/round.c @@ -224,5 +224,6 @@ void bc_round(bc_num num, zend_long precision, zend_long mode, bc_num *result) check_zero: if (bc_is_zero(*result)) { (*result)->n_sign = PLUS; + (*result)->n_scale = 0; } } From 2fdd2d4a492f4e04ac7e8cb7fee31991c480b9f7 Mon Sep 17 00:00:00 2001 From: Saki Takamachi Date: Fri, 14 Mar 2025 10:23:33 +0900 Subject: [PATCH 2/4] The return value of round returns the scale before removing unnecessary zeros, and uses that. --- ext/bcmath/bcmath.c | 9 +++++---- ext/bcmath/libbcmath/src/bcmath.h | 2 +- ext/bcmath/libbcmath/src/round.c | 24 ++++++++++++++---------- 3 files changed, 20 insertions(+), 15 deletions(-) diff --git a/ext/bcmath/bcmath.c b/ext/bcmath/bcmath.c index 233045bd7cd7e..962f839ba83f4 100644 --- a/ext/bcmath/bcmath.c +++ b/ext/bcmath/bcmath.c @@ -807,8 +807,8 @@ PHP_FUNCTION(bcround) goto cleanup; } - bc_round(num, precision, mode, &result); - RETVAL_NEW_STR(bc_num2str_ex(result, result->n_scale)); + size_t scale = bc_round(num, precision, mode, &result); + RETVAL_NEW_STR(bc_num2str_ex(result, scale)); cleanup: { bc_free_num(&num); @@ -1799,9 +1799,10 @@ PHP_METHOD(BcMath_Number, round) bcmath_number_obj_t *intern = get_bcmath_number_from_zval(ZEND_THIS); bc_num ret = NULL; - bc_round(intern->num, precision, rounding_mode, &ret); + size_t scale = bc_round(intern->num, precision, rounding_mode, &ret); + bc_rm_trailing_zeros(ret); - bcmath_number_obj_t *new_intern = bcmath_number_new_obj(ret, ret->n_scale); + bcmath_number_obj_t *new_intern = bcmath_number_new_obj(ret, scale); RETURN_OBJ(&new_intern->std); } diff --git a/ext/bcmath/libbcmath/src/bcmath.h b/ext/bcmath/libbcmath/src/bcmath.h index f7e14019bd336..1f05ad51f7f26 100644 --- a/ext/bcmath/libbcmath/src/bcmath.h +++ b/ext/bcmath/libbcmath/src/bcmath.h @@ -157,7 +157,7 @@ bool bc_divmod(bc_num num1, bc_num num2, bc_num *quo, bc_num *rem, size_t scale) bc_num bc_floor_or_ceil(bc_num num, bool is_floor); -void bc_round(bc_num num, zend_long places, zend_long mode, bc_num *result); +size_t bc_round(bc_num num, zend_long places, zend_long mode, bc_num *result); typedef enum { OK, diff --git a/ext/bcmath/libbcmath/src/round.c b/ext/bcmath/libbcmath/src/round.c index 5229009a3f12d..3ab8f1490a9a7 100644 --- a/ext/bcmath/libbcmath/src/round.c +++ b/ext/bcmath/libbcmath/src/round.c @@ -18,7 +18,7 @@ #include "private.h" #include -void bc_round(bc_num num, zend_long precision, zend_long mode, bc_num *result) +size_t bc_round(bc_num num, zend_long precision, zend_long mode, bc_num *result) { /* clear result */ bc_free_num(result); @@ -43,19 +43,19 @@ void bc_round(bc_num num, zend_long precision, zend_long mode, bc_num *result) case PHP_ROUND_HALF_ODD: case PHP_ROUND_TOWARD_ZERO: *result = bc_copy_num(BCG(_zero_)); - return; + return 0; case PHP_ROUND_CEILING: if (num->n_sign == MINUS) { *result = bc_copy_num(BCG(_zero_)); - return; + return 0; } break; case PHP_ROUND_FLOOR: if (num->n_sign == PLUS) { *result = bc_copy_num(BCG(_zero_)); - return; + return 0; } break; @@ -67,7 +67,7 @@ void bc_round(bc_num num, zend_long precision, zend_long mode, bc_num *result) if (bc_is_zero(num)) { *result = bc_copy_num(BCG(_zero_)); - return; + return 0; } /* If precision is -3, it becomes 1000. */ @@ -78,7 +78,7 @@ void bc_round(bc_num num, zend_long precision, zend_long mode, bc_num *result) } (*result)->n_value[0] = 1; (*result)->n_sign = num->n_sign; - return; + return 0; } /* Just like bcadd('1', '1', 4) becomes '2.0000', it pads with zeros at the end if necessary. */ @@ -90,7 +90,7 @@ void bc_round(bc_num num, zend_long precision, zend_long mode, bc_num *result) (*result)->n_sign = num->n_sign; memcpy((*result)->n_value, num->n_value, num->n_len + num->n_scale); } - return; + return precision; } /* @@ -222,8 +222,12 @@ void bc_round(bc_num num, zend_long precision, zend_long mode, bc_num *result) } check_zero: - if (bc_is_zero(*result)) { - (*result)->n_sign = PLUS; - (*result)->n_scale = 0; + { + size_t scale = (*result)->n_scale; + if (bc_is_zero(*result)) { + (*result)->n_sign = PLUS; + (*result)->n_scale = 0; + } + return scale; } } From cfd14fabafec7a7cd4b8e7213a7be21ef7e940f8 Mon Sep 17 00:00:00 2001 From: Saki Takamachi Date: Fri, 14 Mar 2025 17:49:50 +0900 Subject: [PATCH 3/4] [skip ci] Added a comment --- ext/bcmath/libbcmath/src/round.c | 1 + 1 file changed, 1 insertion(+) diff --git a/ext/bcmath/libbcmath/src/round.c b/ext/bcmath/libbcmath/src/round.c index 3ab8f1490a9a7..44df6036cbe3b 100644 --- a/ext/bcmath/libbcmath/src/round.c +++ b/ext/bcmath/libbcmath/src/round.c @@ -18,6 +18,7 @@ #include "private.h" #include +/* Returns the scale of the value after rounding. */ size_t bc_round(bc_num num, zend_long precision, zend_long mode, bc_num *result) { /* clear result */ From 141b9fe436533976706e1caf11ebf5e960d40563 Mon Sep 17 00:00:00 2001 From: Saki Takamachi Date: Fri, 14 Mar 2025 17:50:57 +0900 Subject: [PATCH 4/4] [skip ci] NEWS --- NEWS | 1 + 1 file changed, 1 insertion(+) diff --git a/NEWS b/NEWS index f941ce90e47f1..bd7c6b3a26ae0 100644 --- a/NEWS +++ b/NEWS @@ -4,6 +4,7 @@ PHP NEWS - BCMath: . Simplify `bc_divide()` code. (SakiTakamachi) + . If the result is 0, n_scale is set to 0. (SakiTakamachi) - CLI: . Add --ini=diff to print INI settings changed from the builtin default.