mirror of
https://github.com/php/php-src.git
synced 2025-08-16 05:58:45 +02:00
ext/bcmath: Use an enum for comparison result (#14374)
Improve logic of callers of bc_compare
This commit is contained in:
parent
cba3891d53
commit
ec54edb9e1
7 changed files with 63 additions and 53 deletions
|
@ -50,16 +50,16 @@ bc_num bc_add(bc_num n1, bc_num n2, size_t scale_min)
|
||||||
/* subtraction must be done. */
|
/* subtraction must be done. */
|
||||||
/* Compare magnitudes. */
|
/* Compare magnitudes. */
|
||||||
switch (_bc_do_compare(n1, n2, false)) {
|
switch (_bc_do_compare(n1, n2, false)) {
|
||||||
case -1:
|
case BCMATH_RIGHT_GREATER:
|
||||||
/* n1 is less than n2, subtract n1 from n2. */
|
/* n1 is less than n2, subtract n1 from n2. */
|
||||||
sum = _bc_do_sub(n2, n1);
|
sum = _bc_do_sub(n2, n1);
|
||||||
sum->n_sign = n2->n_sign;
|
sum->n_sign = n2->n_sign;
|
||||||
break;
|
break;
|
||||||
case 0:
|
case BCMATH_EQUAL:
|
||||||
/* They are equal! return zero with the correct scale! */
|
/* They are equal! return zero with the correct scale! */
|
||||||
sum = bc_new_num (1, MAX(scale_min, MAX(n1->n_scale, n2->n_scale)));
|
sum = bc_new_num (1, MAX(scale_min, MAX(n1->n_scale, n2->n_scale)));
|
||||||
break;
|
break;
|
||||||
case 1:
|
case BCMATH_LEFT_GREATER:
|
||||||
/* n2 is less than n1, subtract n2 from n1. */
|
/* n2 is less than n1, subtract n2 from n1. */
|
||||||
sum = _bc_do_sub(n1, n2);
|
sum = _bc_do_sub(n1, n2);
|
||||||
sum->n_sign = n1->n_sign;
|
sum->n_sign = n1->n_sign;
|
||||||
|
|
|
@ -106,7 +106,13 @@ void bc_int2num(bc_num *num, int val);
|
||||||
|
|
||||||
long bc_num2long(bc_num num);
|
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);
|
bool bc_is_zero(bc_num num);
|
||||||
|
|
||||||
|
|
|
@ -39,7 +39,7 @@
|
||||||
than N2 and +1 if N1 is greater than N2. If USE_SIGN is false, just
|
than N2 and +1 if N1 is greater than N2. If USE_SIGN is false, just
|
||||||
compare the magnitudes. */
|
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;
|
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 (use_sign && n1->n_sign != n2->n_sign) {
|
||||||
if (n1->n_sign == PLUS) {
|
if (n1->n_sign == PLUS) {
|
||||||
/* Positive N1 > Negative N2 */
|
/* Positive N1 > Negative N2 */
|
||||||
return (1);
|
return BCMATH_LEFT_GREATER;
|
||||||
} else {
|
} else {
|
||||||
/* Negative N1 < Positive N1 */
|
/* 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) {
|
if (n1->n_len > n2->n_len) {
|
||||||
/* Magnitude of n1 > n2. */
|
/* Magnitude of n1 > n2. */
|
||||||
if (!use_sign || n1->n_sign == PLUS) {
|
if (!use_sign || n1->n_sign == PLUS) {
|
||||||
return (1);
|
return BCMATH_LEFT_GREATER;
|
||||||
} else {
|
} else {
|
||||||
return (-1);
|
return BCMATH_RIGHT_GREATER;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* Magnitude of n1 < n2. */
|
/* Magnitude of n1 < n2. */
|
||||||
if (!use_sign || n1->n_sign == PLUS) {
|
if (!use_sign || n1->n_sign == PLUS) {
|
||||||
return (-1);
|
return BCMATH_RIGHT_GREATER;
|
||||||
} else {
|
} 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) {
|
if (*n1ptr > *n2ptr) {
|
||||||
/* Magnitude of n1 > n2. */
|
/* Magnitude of n1 > n2. */
|
||||||
if (!use_sign || n1->n_sign == PLUS) {
|
if (!use_sign || n1->n_sign == PLUS) {
|
||||||
return (1);
|
return BCMATH_LEFT_GREATER;
|
||||||
} else {
|
} else {
|
||||||
return (-1);
|
return BCMATH_RIGHT_GREATER;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* Magnitude of n1 < n2. */
|
/* Magnitude of n1 < n2. */
|
||||||
if (!use_sign || n1->n_sign == PLUS) {
|
if (!use_sign || n1->n_sign == PLUS) {
|
||||||
return (-1);
|
return BCMATH_RIGHT_GREATER;
|
||||||
} else {
|
} 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) {
|
if (*n1ptr++ != 0) {
|
||||||
/* Magnitude of n1 > n2. */
|
/* Magnitude of n1 > n2. */
|
||||||
if (!use_sign || n1->n_sign == PLUS) {
|
if (!use_sign || n1->n_sign == PLUS) {
|
||||||
return (1);
|
return BCMATH_LEFT_GREATER;
|
||||||
} else {
|
} 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) {
|
if (*n2ptr++ != 0) {
|
||||||
/* Magnitude of n1 < n2. */
|
/* Magnitude of n1 < n2. */
|
||||||
if (!use_sign || n1->n_sign == PLUS) {
|
if (!use_sign || n1->n_sign == PLUS) {
|
||||||
return (-1);
|
return BCMATH_RIGHT_GREATER;
|
||||||
} else {
|
} 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! */
|
/* They must be equal! */
|
||||||
return (0);
|
return BCMATH_EQUAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* This is the "user callable" routine to compare numbers N1 and N2. */
|
/* 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);
|
return _bc_do_compare(n1, n2, true);
|
||||||
}
|
}
|
||||||
|
|
|
@ -97,7 +97,7 @@ static inline uint64_t BC_BSWAP64(uint64_t u)
|
||||||
|
|
||||||
|
|
||||||
/* routines */
|
/* 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_add (bc_num n1, bc_num n2);
|
||||||
bc_num _bc_do_sub (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);
|
void _bc_rm_leading_zeros (bc_num num);
|
||||||
|
|
|
@ -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;
|
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. */
|
/* Set initial values. */
|
||||||
power = bc_copy_num(base);
|
power = bc_copy_num(base);
|
||||||
exponent = bc_copy_num(expo);
|
exponent = bc_copy_num(expo);
|
||||||
|
@ -66,10 +73,6 @@ raise_mod_status bc_raisemod(bc_num base, bc_num expo, bc_num mod, bc_num *resul
|
||||||
bc_init_num(&parity);
|
bc_init_num(&parity);
|
||||||
|
|
||||||
/* Do the calculation. */
|
/* 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)) {
|
while (!bc_is_zero(exponent)) {
|
||||||
(void) bc_divmod(exponent, BCG(_two_), &exponent, &parity, 0);
|
(void) bc_divmod(exponent, BCG(_two_), &exponent, &parity, 0);
|
||||||
if (!bc_is_zero(parity)) {
|
if (!bc_is_zero(parity)) {
|
||||||
|
@ -79,7 +82,6 @@ raise_mod_status bc_raisemod(bc_num base, bc_num expo, bc_num mod, bc_num *resul
|
||||||
bc_multiply_ex(power, power, &power, scale);
|
bc_multiply_ex(power, power, &power, scale);
|
||||||
(void) bc_modulo(power, modulus, &power, scale);
|
(void) bc_modulo(power, modulus, &power, scale);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/* Assign the value. */
|
/* Assign the value. */
|
||||||
bc_free_num (&power);
|
bc_free_num (&power);
|
||||||
|
|
|
@ -38,30 +38,32 @@
|
||||||
|
|
||||||
bool bc_sqrt(bc_num *num, size_t scale)
|
bool bc_sqrt(bc_num *num, size_t scale)
|
||||||
{
|
{
|
||||||
|
const bc_num local_num = *num;
|
||||||
/* Initial checks. */
|
/* Initial checks. */
|
||||||
int cmp_res = bc_compare(*num, BCG(_zero_));
|
if (bc_is_neg(local_num)) {
|
||||||
if (cmp_res < 0) {
|
/* Cannot take the square root of a negative number */
|
||||||
return false; /* error */
|
return false;
|
||||||
} else {
|
}
|
||||||
if (cmp_res == 0) {
|
/* Square root of 0 is 0 */
|
||||||
|
if (bc_is_zero(local_num)) {
|
||||||
bc_free_num (num);
|
bc_free_num (num);
|
||||||
*num = bc_copy_num(BCG(_zero_));
|
*num = bc_copy_num(BCG(_zero_));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
cmp_res = bc_compare(*num, BCG(_one_));
|
bcmath_compare_result num_cmp_one = bc_compare(local_num, BCG(_one_));
|
||||||
if (cmp_res == 0) {
|
/* Square root of 1 is 1 */
|
||||||
|
if (num_cmp_one == BCMATH_EQUAL) {
|
||||||
bc_free_num (num);
|
bc_free_num (num);
|
||||||
*num = bc_copy_num(BCG(_one_));
|
*num = bc_copy_num(BCG(_one_));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Initialize the variables. */
|
/* Initialize the variables. */
|
||||||
size_t rscale;
|
|
||||||
size_t cscale;
|
size_t cscale;
|
||||||
bc_num guess, guess1, point5, diff;
|
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(&guess1);
|
||||||
bc_init_num(&diff);
|
bc_init_num(&diff);
|
||||||
point5 = bc_new_num (1, 1);
|
point5 = bc_new_num (1, 1);
|
||||||
|
@ -69,16 +71,16 @@ bool bc_sqrt(bc_num *num, size_t scale)
|
||||||
|
|
||||||
|
|
||||||
/* Calculate the initial guess. */
|
/* 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. */
|
/* The number is between 0 and 1. Guess should start at 1. */
|
||||||
guess = bc_copy_num(BCG(_one_));
|
guess = bc_copy_num(BCG(_one_));
|
||||||
cscale = (*num)->n_scale;
|
cscale = local_num->n_scale;
|
||||||
} else {
|
} else {
|
||||||
/* The number is greater than 1. Guess should start at 10^(exp/2). */
|
/* The number is greater than 1. Guess should start at 10^(exp/2). */
|
||||||
bc_init_num(&guess);
|
bc_init_num(&guess);
|
||||||
bc_int2num(&guess, 10);
|
bc_int2num(&guess, 10);
|
||||||
|
|
||||||
bc_int2num(&guess1, (*num)->n_len);
|
bc_int2num(&guess1, local_num->n_len);
|
||||||
bc_multiply_ex(guess1, point5, &guess1, 0);
|
bc_multiply_ex(guess1, point5, &guess1, 0);
|
||||||
guess1->n_scale = 0;
|
guess1->n_scale = 0;
|
||||||
bc_raise_bc_exponent(guess, guess1, &guess, 0);
|
bc_raise_bc_exponent(guess, guess1, &guess, 0);
|
||||||
|
|
|
@ -50,18 +50,18 @@ bc_num bc_sub(bc_num n1, bc_num n2, size_t scale_min)
|
||||||
/* subtraction must be done. */
|
/* subtraction must be done. */
|
||||||
/* Compare magnitudes. */
|
/* Compare magnitudes. */
|
||||||
switch (_bc_do_compare(n1, n2, false)) {
|
switch (_bc_do_compare(n1, n2, false)) {
|
||||||
case -1:
|
case BCMATH_RIGHT_GREATER:
|
||||||
/* n1 is less than n2, subtract n1 from n2. */
|
/* n1 is less than n2, subtract n1 from n2. */
|
||||||
diff = _bc_do_sub(n2, n1);
|
diff = _bc_do_sub(n2, n1);
|
||||||
diff->n_sign = (n2->n_sign == PLUS ? MINUS : PLUS);
|
diff->n_sign = (n2->n_sign == PLUS ? MINUS : PLUS);
|
||||||
break;
|
break;
|
||||||
case 0: {
|
case BCMATH_EQUAL: {
|
||||||
/* They are equal! return zero! */
|
/* They are equal! return zero! */
|
||||||
size_t res_scale = MAX (scale_min, MAX(n1->n_scale, n2->n_scale));
|
size_t res_scale = MAX (scale_min, MAX(n1->n_scale, n2->n_scale));
|
||||||
diff = bc_new_num (1, res_scale);
|
diff = bc_new_num (1, res_scale);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 1:
|
case BCMATH_LEFT_GREATER:
|
||||||
/* n2 is less than n1, subtract n2 from n1. */
|
/* n2 is less than n1, subtract n2 from n1. */
|
||||||
diff = _bc_do_sub(n1, n2);
|
diff = _bc_do_sub(n1, n2);
|
||||||
diff->n_sign = n1->n_sign;
|
diff->n_sign = n1->n_sign;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue