diff --git a/ext/bcmath/libbcmath/src/add.c b/ext/bcmath/libbcmath/src/add.c index c5f1c6cb45f94..5d039a252e813 100644 --- a/ext/bcmath/libbcmath/src/add.c +++ b/ext/bcmath/libbcmath/src/add.c @@ -50,16 +50,16 @@ bc_num bc_add(bc_num n1, bc_num n2, size_t scale_min) /* subtraction must be done. */ /* Compare magnitudes. */ switch (_bc_do_compare(n1, n2, false)) { - case -1: + case BCMATH_RIGHT_GREATER: /* n1 is less than n2, subtract n1 from n2. */ sum = _bc_do_sub(n2, n1); sum->n_sign = n2->n_sign; break; - case 0: + case BCMATH_EQUAL: /* They are equal! return zero with the correct scale! */ sum = bc_new_num (1, MAX(scale_min, MAX(n1->n_scale, n2->n_scale))); break; - case 1: + case BCMATH_LEFT_GREATER: /* n2 is less than n1, subtract n2 from n1. */ sum = _bc_do_sub(n1, n2); sum->n_sign = n1->n_sign; diff --git a/ext/bcmath/libbcmath/src/bcmath.h b/ext/bcmath/libbcmath/src/bcmath.h index b8e3b4c7fb86a..42eb67e599fae 100644 --- a/ext/bcmath/libbcmath/src/bcmath.h +++ b/ext/bcmath/libbcmath/src/bcmath.h @@ -106,7 +106,13 @@ void bc_int2num(bc_num *num, int val); long bc_num2long(bc_num num); -int bc_compare(bc_num n1, bc_num n2); +typedef enum { + BCMATH_EQUAL = 0, + BCMATH_LEFT_GREATER = 1, + BCMATH_RIGHT_GREATER = -1 +} bcmath_compare_result; + +bcmath_compare_result bc_compare(bc_num n1, bc_num n2); bool bc_is_zero(bc_num num); diff --git a/ext/bcmath/libbcmath/src/compare.c b/ext/bcmath/libbcmath/src/compare.c index 9604828e08ccc..95f3430e843a9 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. */ -int _bc_do_compare(bc_num n1, bc_num n2, bool use_sign) +bcmath_compare_result _bc_do_compare(bc_num n1, bc_num n2, bool use_sign) { char *n1ptr, *n2ptr; @@ -47,10 +47,10 @@ int _bc_do_compare(bc_num n1, bc_num n2, bool use_sign) if (use_sign && n1->n_sign != n2->n_sign) { if (n1->n_sign == PLUS) { /* Positive N1 > Negative N2 */ - return (1); + return BCMATH_LEFT_GREATER; } else { /* Negative N1 < Positive N1 */ - return (-1); + return BCMATH_RIGHT_GREATER; } } @@ -59,16 +59,16 @@ int _bc_do_compare(bc_num n1, bc_num n2, bool use_sign) if (n1->n_len > n2->n_len) { /* Magnitude of n1 > n2. */ if (!use_sign || n1->n_sign == PLUS) { - return (1); + return BCMATH_LEFT_GREATER; } else { - return (-1); + return BCMATH_RIGHT_GREATER; } } else { /* Magnitude of n1 < n2. */ if (!use_sign || n1->n_sign == PLUS) { - return (-1); + return BCMATH_RIGHT_GREATER; } else { - return (1); + return BCMATH_LEFT_GREATER; } } } @@ -89,16 +89,16 @@ int _bc_do_compare(bc_num n1, bc_num n2, bool use_sign) if (*n1ptr > *n2ptr) { /* Magnitude of n1 > n2. */ if (!use_sign || n1->n_sign == PLUS) { - return (1); + return BCMATH_LEFT_GREATER; } else { - return (-1); + return BCMATH_RIGHT_GREATER; } } else { /* Magnitude of n1 < n2. */ if (!use_sign || n1->n_sign == PLUS) { - return (-1); + return BCMATH_RIGHT_GREATER; } else { - return (1); + return BCMATH_LEFT_GREATER; } } } @@ -110,9 +110,9 @@ int _bc_do_compare(bc_num n1, bc_num n2, bool use_sign) if (*n1ptr++ != 0) { /* Magnitude of n1 > n2. */ if (!use_sign || n1->n_sign == PLUS) { - return (1); + return BCMATH_LEFT_GREATER; } else { - return (-1); + return BCMATH_RIGHT_GREATER; } } } @@ -121,9 +121,9 @@ int _bc_do_compare(bc_num n1, bc_num n2, bool use_sign) if (*n2ptr++ != 0) { /* Magnitude of n1 < n2. */ if (!use_sign || n1->n_sign == PLUS) { - return (-1); + return BCMATH_RIGHT_GREATER; } else { - return (1); + return BCMATH_LEFT_GREATER; } } } @@ -131,12 +131,12 @@ int _bc_do_compare(bc_num n1, bc_num n2, bool use_sign) } /* They must be equal! */ - return (0); + return BCMATH_EQUAL; } /* This is the "user callable" routine to compare numbers N1 and N2. */ -int bc_compare(bc_num n1, bc_num n2) +bcmath_compare_result bc_compare(bc_num n1, bc_num n2) { return _bc_do_compare(n1, n2, true); } diff --git a/ext/bcmath/libbcmath/src/private.h b/ext/bcmath/libbcmath/src/private.h index 6035d73dd716e..812767aa5c55c 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 */ -int _bc_do_compare (bc_num n1, bc_num n2, bool use_sign); +bcmath_compare_result _bc_do_compare (bc_num n1, bc_num n2, 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 cf351394a437a..1991a2daea00f 100644 --- a/ext/bcmath/libbcmath/src/raisemod.c +++ b/ext/bcmath/libbcmath/src/raisemod.c @@ -58,6 +58,13 @@ raise_mod_status bc_raisemod(bc_num base, bc_num expo, bc_num mod, bc_num *resul return MOD_IS_ZERO; } + /* Any integer number mod 1 (or -1) must be equal to 0 */ + if (_bc_do_compare(mod, BCG(_one_), false) == BCMATH_EQUAL) { + bc_free_num (result); + *result = bc_new_num(1, scale); + return OK; + } + /* Set initial values. */ power = bc_copy_num(base); exponent = bc_copy_num(expo); @@ -66,19 +73,14 @@ raise_mod_status bc_raisemod(bc_num base, bc_num expo, bc_num mod, bc_num *resul bc_init_num(&parity); /* Do the calculation. */ - if (!_bc_do_compare(modulus, BCG(_one_), false)) { - bc_free_num (&temp); - temp = bc_new_num (1, scale); - } else { - while (!bc_is_zero(exponent)) { - (void) bc_divmod(exponent, BCG(_two_), &exponent, &parity, 0); - if (!bc_is_zero(parity)) { - bc_multiply_ex(temp, power, &temp, scale); - (void) bc_modulo(temp, modulus, &temp, scale); - } - bc_multiply_ex(power, power, &power, scale); - (void) bc_modulo(power, modulus, &power, scale); + while (!bc_is_zero(exponent)) { + (void) bc_divmod(exponent, BCG(_two_), &exponent, &parity, 0); + if (!bc_is_zero(parity)) { + bc_multiply_ex(temp, power, &temp, scale); + (void) bc_modulo(temp, modulus, &temp, scale); } + bc_multiply_ex(power, power, &power, scale); + (void) bc_modulo(power, modulus, &power, scale); } /* Assign the value. */ diff --git a/ext/bcmath/libbcmath/src/sqrt.c b/ext/bcmath/libbcmath/src/sqrt.c index 995bf076b54e7..95939b83ca925 100644 --- a/ext/bcmath/libbcmath/src/sqrt.c +++ b/ext/bcmath/libbcmath/src/sqrt.c @@ -38,30 +38,32 @@ bool bc_sqrt(bc_num *num, size_t scale) { + const bc_num local_num = *num; /* Initial checks. */ - int cmp_res = bc_compare(*num, BCG(_zero_)); - if (cmp_res < 0) { - return false; /* error */ - } else { - if (cmp_res == 0) { - bc_free_num (num); - *num = bc_copy_num(BCG(_zero_)); - return true; - } + if (bc_is_neg(local_num)) { + /* Cannot take the square root of a negative number */ + return false; + } + /* Square root of 0 is 0 */ + if (bc_is_zero(local_num)) { + bc_free_num (num); + *num = bc_copy_num(BCG(_zero_)); + return true; } - cmp_res = bc_compare(*num, BCG(_one_)); - if (cmp_res == 0) { + + bcmath_compare_result num_cmp_one = bc_compare(local_num, BCG(_one_)); + /* Square root of 1 is 1 */ + if (num_cmp_one == BCMATH_EQUAL) { bc_free_num (num); *num = bc_copy_num(BCG(_one_)); return true; } /* Initialize the variables. */ - size_t rscale; size_t cscale; bc_num guess, guess1, point5, diff; + size_t rscale = MAX(scale, local_num->n_scale); - rscale = MAX (scale, (*num)->n_scale); bc_init_num(&guess1); bc_init_num(&diff); point5 = bc_new_num (1, 1); @@ -69,16 +71,16 @@ bool bc_sqrt(bc_num *num, size_t scale) /* Calculate the initial guess. */ - if (cmp_res < 0) { + if (num_cmp_one == BCMATH_RIGHT_GREATER) { /* The number is between 0 and 1. Guess should start at 1. */ guess = bc_copy_num(BCG(_one_)); - cscale = (*num)->n_scale; + cscale = local_num->n_scale; } else { /* The number is greater than 1. Guess should start at 10^(exp/2). */ bc_init_num(&guess); bc_int2num(&guess, 10); - bc_int2num(&guess1, (*num)->n_len); + bc_int2num(&guess1, local_num->n_len); bc_multiply_ex(guess1, point5, &guess1, 0); guess1->n_scale = 0; bc_raise_bc_exponent(guess, guess1, &guess, 0); diff --git a/ext/bcmath/libbcmath/src/sub.c b/ext/bcmath/libbcmath/src/sub.c index fc6b6b9d8e7b6..4113f147d28c5 100644 --- a/ext/bcmath/libbcmath/src/sub.c +++ b/ext/bcmath/libbcmath/src/sub.c @@ -50,18 +50,18 @@ bc_num bc_sub(bc_num n1, bc_num n2, size_t scale_min) /* subtraction must be done. */ /* Compare magnitudes. */ switch (_bc_do_compare(n1, n2, false)) { - case -1: + case BCMATH_RIGHT_GREATER: /* n1 is less than n2, subtract n1 from n2. */ diff = _bc_do_sub(n2, n1); diff->n_sign = (n2->n_sign == PLUS ? MINUS : PLUS); break; - case 0: { + case BCMATH_EQUAL: { /* They are equal! return zero! */ size_t res_scale = MAX (scale_min, MAX(n1->n_scale, n2->n_scale)); diff = bc_new_num (1, res_scale); break; } - case 1: + case BCMATH_LEFT_GREATER: /* n2 is less than n1, subtract n2 from n1. */ diff = _bc_do_sub(n1, n2); diff->n_sign = n1->n_sign;