From 6f611eecf2db5e094d2ccad922b705c56be76447 Mon Sep 17 00:00:00 2001 From: Saki Takamachi Date: Thu, 4 Jul 2024 08:30:06 +0900 Subject: [PATCH] Added scale to bc_compare argument In the original specification, the scale of bc_num was directly changed and compared. This becomes a problem when objects are supported, so we will modify it to compare without changing bc_num. --- ext/bcmath/bcmath.c | 2 +- ext/bcmath/libbcmath/src/add.c | 2 +- ext/bcmath/libbcmath/src/bcmath.h | 2 +- ext/bcmath/libbcmath/src/compare.c | 19 +++++++++++-------- ext/bcmath/libbcmath/src/private.h | 2 +- ext/bcmath/libbcmath/src/raisemod.c | 2 +- ext/bcmath/libbcmath/src/sqrt.c | 2 +- ext/bcmath/libbcmath/src/sub.c | 2 +- 8 files changed, 18 insertions(+), 15 deletions(-) diff --git a/ext/bcmath/bcmath.c b/ext/bcmath/bcmath.c index 0258c0cd3a53..f91f4398f8f7 100644 --- a/ext/bcmath/bcmath.c +++ b/ext/bcmath/bcmath.c @@ -638,7 +638,7 @@ PHP_FUNCTION(bccomp) goto cleanup; } - RETVAL_LONG(bc_compare(first, second)); + RETVAL_LONG(bc_compare(first, second, scale)); cleanup: { bc_free_num(&first); diff --git a/ext/bcmath/libbcmath/src/add.c b/ext/bcmath/libbcmath/src/add.c index 5d039a252e81..9a11b98b4877 100644 --- a/ext/bcmath/libbcmath/src/add.c +++ b/ext/bcmath/libbcmath/src/add.c @@ -49,7 +49,7 @@ bc_num bc_add(bc_num n1, bc_num n2, size_t scale_min) } else { /* subtraction must be done. */ /* Compare magnitudes. */ - switch (_bc_do_compare(n1, n2, false)) { + switch (_bc_do_compare(n1, n2, scale_min, false)) { case BCMATH_RIGHT_GREATER: /* n1 is less than n2, subtract n1 from n2. */ sum = _bc_do_sub(n2, n1); diff --git a/ext/bcmath/libbcmath/src/bcmath.h b/ext/bcmath/libbcmath/src/bcmath.h index 42eb67e599fa..3ca5db6d408b 100644 --- a/ext/bcmath/libbcmath/src/bcmath.h +++ b/ext/bcmath/libbcmath/src/bcmath.h @@ -112,7 +112,7 @@ typedef enum { BCMATH_RIGHT_GREATER = -1 } bcmath_compare_result; -bcmath_compare_result bc_compare(bc_num n1, bc_num n2); +bcmath_compare_result bc_compare(bc_num n1, bc_num n2, size_t scale); bool bc_is_zero(bc_num num); diff --git a/ext/bcmath/libbcmath/src/compare.c b/ext/bcmath/libbcmath/src/compare.c index 95f3430e843a..f2df5cc24c57 100644 --- a/ext/bcmath/libbcmath/src/compare.c +++ b/ext/bcmath/libbcmath/src/compare.c @@ -39,7 +39,7 @@ than N2 and +1 if N1 is greater than N2. If USE_SIGN is false, just compare the magnitudes. */ -bcmath_compare_result _bc_do_compare(bc_num n1, bc_num n2, bool use_sign) +bcmath_compare_result _bc_do_compare(bc_num n1, bc_num n2, size_t scale, bool use_sign) { char *n1ptr, *n2ptr; @@ -73,9 +73,12 @@ bcmath_compare_result _bc_do_compare(bc_num n1, bc_num n2, bool use_sign) } } + size_t n1_scale = MIN(n1->n_scale, scale); + size_t n2_scale = MIN(n2->n_scale, scale); + /* If we get here, they have the same number of integer digits. check the integer part and the equal length part of the fraction. */ - size_t count = n1->n_len + MIN (n1->n_scale, n2->n_scale); + size_t count = n1->n_len + MIN (n1_scale, n2_scale); n1ptr = n1->n_value; n2ptr = n2->n_value; @@ -104,9 +107,9 @@ bcmath_compare_result _bc_do_compare(bc_num n1, bc_num n2, bool use_sign) } /* They are equal up to the last part of the equal part of the fraction. */ - if (n1->n_scale != n2->n_scale) { - if (n1->n_scale > n2->n_scale) { - for (count = n1->n_scale - n2->n_scale; count > 0; count--) { + if (n1_scale != n2_scale) { + if (n1_scale > n2_scale) { + for (count = n1_scale - n2_scale; count > 0; count--) { if (*n1ptr++ != 0) { /* Magnitude of n1 > n2. */ if (!use_sign || n1->n_sign == PLUS) { @@ -117,7 +120,7 @@ bcmath_compare_result _bc_do_compare(bc_num n1, bc_num n2, bool use_sign) } } } else { - for (count = n2->n_scale - n1->n_scale; count > 0; count--) { + for (count = n2_scale - n1_scale; count > 0; count--) { if (*n2ptr++ != 0) { /* Magnitude of n1 < n2. */ if (!use_sign || n1->n_sign == PLUS) { @@ -136,7 +139,7 @@ bcmath_compare_result _bc_do_compare(bc_num n1, bc_num n2, bool use_sign) /* This is the "user callable" routine to compare numbers N1 and N2. */ -bcmath_compare_result bc_compare(bc_num n1, bc_num n2) +bcmath_compare_result bc_compare(bc_num n1, bc_num n2, size_t scale) { - return _bc_do_compare(n1, n2, true); + return _bc_do_compare(n1, n2, scale, true); } diff --git a/ext/bcmath/libbcmath/src/private.h b/ext/bcmath/libbcmath/src/private.h index 4b72ce7040c8..50a0dfd3a922 100644 --- a/ext/bcmath/libbcmath/src/private.h +++ b/ext/bcmath/libbcmath/src/private.h @@ -97,7 +97,7 @@ static inline uint64_t BC_BSWAP64(uint64_t u) /* routines */ -bcmath_compare_result _bc_do_compare (bc_num n1, bc_num n2, bool use_sign); +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); diff --git a/ext/bcmath/libbcmath/src/raisemod.c b/ext/bcmath/libbcmath/src/raisemod.c index 1991a2daea00..696fbe882f00 100644 --- a/ext/bcmath/libbcmath/src/raisemod.c +++ b/ext/bcmath/libbcmath/src/raisemod.c @@ -59,7 +59,7 @@ raise_mod_status bc_raisemod(bc_num base, bc_num expo, bc_num mod, bc_num *resul } /* Any integer number mod 1 (or -1) must be equal to 0 */ - if (_bc_do_compare(mod, BCG(_one_), false) == BCMATH_EQUAL) { + if (_bc_do_compare(mod, BCG(_one_), mod->n_scale, false) == BCMATH_EQUAL) { bc_free_num (result); *result = bc_new_num(1, scale); return OK; diff --git a/ext/bcmath/libbcmath/src/sqrt.c b/ext/bcmath/libbcmath/src/sqrt.c index 95939b83ca92..82f71be82810 100644 --- a/ext/bcmath/libbcmath/src/sqrt.c +++ b/ext/bcmath/libbcmath/src/sqrt.c @@ -51,7 +51,7 @@ bool bc_sqrt(bc_num *num, size_t scale) return true; } - bcmath_compare_result num_cmp_one = bc_compare(local_num, BCG(_one_)); + bcmath_compare_result num_cmp_one = bc_compare(local_num, BCG(_one_), local_num->n_scale); /* Square root of 1 is 1 */ if (num_cmp_one == BCMATH_EQUAL) { bc_free_num (num); diff --git a/ext/bcmath/libbcmath/src/sub.c b/ext/bcmath/libbcmath/src/sub.c index 4113f147d28c..9e71c4856f81 100644 --- a/ext/bcmath/libbcmath/src/sub.c +++ b/ext/bcmath/libbcmath/src/sub.c @@ -49,7 +49,7 @@ bc_num bc_sub(bc_num n1, bc_num n2, size_t scale_min) } else { /* subtraction must be done. */ /* Compare magnitudes. */ - switch (_bc_do_compare(n1, n2, false)) { + switch (_bc_do_compare(n1, n2, scale_min, false)) { case BCMATH_RIGHT_GREATER: /* n1 is less than n2, subtract n1 from n2. */ diff = _bc_do_sub(n2, n1);