Merge branch 'PHP-8.4'

* PHP-8.4:
  Fixed a bug in BcMath\Number::pow() and bcpow() when raising negative powers of 0. (#16694)
This commit is contained in:
Saki Takamachi 2024-11-20 00:17:38 +09:00
commit 9b3af0253f
No known key found for this signature in database
GPG Key ID: 770426E17EBBB3DD
8 changed files with 147 additions and 20 deletions

View File

@ -615,7 +615,10 @@ PHP_FUNCTION(bcpow)
goto cleanup;
}
bc_raise(first, exponent, &result, scale);
if (!bc_raise(first, exponent, &result, scale)) {
zend_throw_exception_ex(zend_ce_division_by_zero_error, 0, "Negative power of zero");
goto cleanup;
}
RETVAL_NEW_STR(bc_num2str_ex(result, scale));
@ -1141,7 +1144,10 @@ static zend_result bcmath_number_pow_internal(
}
return FAILURE;
}
bc_raise(n1, exponent, ret, *scale);
if (!bc_raise(n1, exponent, ret, *scale)) {
zend_throw_exception_ex(zend_ce_division_by_zero_error, 0, "Negative power of zero");
return FAILURE;
}
bc_rm_trailing_zeros(*ret);
if (scale_expand) {
size_t diff = *scale - (*ret)->n_scale;

View File

@ -168,7 +168,7 @@ typedef enum {
raise_mod_status bc_raisemod(bc_num base, bc_num exponent, bc_num mod, bc_num *result, size_t scale);
void bc_raise(bc_num base, long exponent, bc_num *resul, size_t scale);
bool bc_raise(bc_num base, long exponent, bc_num *result, size_t scale);
void bc_raise_bc_exponent(bc_num base, bc_num exponent, bc_num *resul, size_t scale);

View File

@ -40,10 +40,10 @@ void bc_square_ex(bc_num n1, bc_num *result, size_t scale_min) {
*(result) = square_ex;
}
/* Raise NUM1 to the NUM2 power. The result is placed in RESULT.
Maximum exponent is LONG_MAX. If a NUM2 is not an integer,
/* Raise "base" to the "exponent" power. The result is placed in RESULT.
Maximum exponent is LONG_MAX. If a "exponent" is not an integer,
only the integer part is used. */
void bc_raise(bc_num num1, long exponent, bc_num *result, size_t scale) {
bool bc_raise(bc_num base, long exponent, bc_num *result, size_t scale) {
bc_num temp, power;
size_t rscale;
size_t pwrscale;
@ -54,7 +54,7 @@ void bc_raise(bc_num num1, long exponent, bc_num *result, size_t scale) {
if (exponent == 0) {
bc_free_num (result);
*result = bc_copy_num(BCG(_one_));
return;
return true;
}
/* Other initializations. */
@ -64,12 +64,12 @@ void bc_raise(bc_num num1, long exponent, bc_num *result, size_t scale) {
rscale = scale;
} else {
is_neg = false;
rscale = MIN (num1->n_scale * exponent, MAX(scale, num1->n_scale));
rscale = MIN (base->n_scale * exponent, MAX(scale, base->n_scale));
}
/* Set initial value of temp. */
power = bc_copy_num(num1);
pwrscale = num1->n_scale;
power = bc_copy_num(base);
pwrscale = base->n_scale;
while ((exponent & 1) == 0) {
pwrscale = 2 * pwrscale;
bc_square_ex(power, &power, pwrscale);
@ -92,7 +92,11 @@ void bc_raise(bc_num num1, long exponent, bc_num *result, size_t scale) {
/* Assign the value. */
if (is_neg) {
bc_divide(BCG(_one_), temp, result, rscale);
if (bc_divide(BCG(_one_), temp, result, rscale) == false) {
bc_free_num (&temp);
bc_free_num (&power);
return false;
}
bc_free_num (&temp);
} else {
bc_free_num (result);
@ -100,6 +104,7 @@ void bc_raise(bc_num num1, long exponent, bc_num *result, size_t scale) {
(*result)->n_scale = MIN(scale, (*result)->n_scale);
}
bc_free_num (&power);
return true;
}
/* This is used internally by BCMath */

View File

@ -60,17 +60,17 @@ Number "-9" (scale 0)
Number "0" (scale 0)
0 ** 15 = 0
0 ** -15 = 0
0 ** -15 = Negative power of zero
0 ** 1 = 0
0 ** -9 = 0
0 ** -9 = Negative power of zero
0 ** 0 = 1
0 ** -0 = 1
Number "-0" (scale 0)
-0 ** 15 = 0
-0 ** -15 = 0
-0 ** -15 = Negative power of zero
-0 ** 1 = 0
-0 ** -9 = 0
-0 ** -9 = Negative power of zero
-0 ** 0 = 1
-0 ** -0 = 1
@ -188,17 +188,17 @@ Number "-9" (scale 10)
Number "0" (scale 10)
0 ** 15 = 0.0000000000
0 ** -15 = 0.0000000000
0 ** -15 = Negative power of zero
0 ** 1 = 0.0000000000
0 ** -9 = 0.0000000000
0 ** -9 = Negative power of zero
0 ** 0 = 1.0000000000
0 ** -0 = 1.0000000000
Number "-0" (scale 10)
-0 ** 15 = 0.0000000000
-0 ** -15 = 0.0000000000
-0 ** -15 = Negative power of zero
-0 ** 1 = 0.0000000000
-0 ** -9 = 0.0000000000
-0 ** -9 = Negative power of zero
-0 ** 0 = 1.0000000000
-0 ** -0 = 1.0000000000

View File

@ -0,0 +1,29 @@
--TEST--
bcpow() negative power of zero
--EXTENSIONS--
bcmath
--INI--
bcmath.scale=0
--FILE--
<?php
$exponents = ["-15", "-1", "-9"];
$baseNumbers = ['0', '-0'];
foreach ($baseNumbers as $baseNumber) {
foreach ($exponents as $exponent) {
try {
echo bcpow($baseNumber, $exponent), "\n";
} catch (Error $e) {
echo $e->getMessage(), "\n";
}
}
}
?>
--EXPECT--
Negative power of zero
Negative power of zero
Negative power of zero
Negative power of zero
Negative power of zero
Negative power of zero

View File

@ -0,0 +1,41 @@
--TEST--
BcMath\Number pow(): negative power of zero
--EXTENSIONS--
bcmath
--FILE--
<?php
$values = [0, '0'];
$exponents = [
[-3, 'int'],
['-2', 'string'],
[new BcMath\Number('-2'), 'object'],
];
foreach ($values as $value) {
$num = new BcMath\Number($value);
foreach ($exponents as [$exponent, $type]) {
echo "{$value} ** {$exponent}: {$type}\n";
try {
$num->pow($exponent);
} catch (Error $e) {
echo $e->getMessage() . "\n";
}
}
}
?>
--EXPECT--
0 ** -3: int
Negative power of zero
0 ** -2: string
Negative power of zero
0 ** -2: object
Negative power of zero
0 ** -3: int
Negative power of zero
0 ** -2: string
Negative power of zero
0 ** -2: object
Negative power of zero

View File

@ -0,0 +1,41 @@
--TEST--
BcMath\Number pow: negative power of zero by operator
--EXTENSIONS--
bcmath
--FILE--
<?php
$values = [0, '0'];
$exponents = [
[-3, 'int'],
['-2', 'string'],
[new BcMath\Number('-2'), 'object'],
];
foreach ($values as $value) {
$num = new BcMath\Number($value);
foreach ($exponents as [$exponent, $type]) {
echo "{$value} ** {$exponent}: {$type}\n";
try {
$num ** $exponent;
} catch (Error $e) {
echo $e->getMessage() . "\n";
}
}
}
?>
--EXPECT--
0 ** -3: int
Negative power of zero
0 ** -2: string
Negative power of zero
0 ** -2: object
Negative power of zero
0 ** -3: int
Negative power of zero
0 ** -2: string
Negative power of zero
0 ** -2: object
Negative power of zero

View File

@ -13,11 +13,16 @@ function run_bcmath_tests(
foreach ($firstTerms as $firstTerm) {
echo "Number \"$firstTerm\" (scale $scale)\n";
foreach ($secondTerms as $secondTerm) {
try {
$ret = $bcmath_function($firstTerm, $secondTerm, $scale);
} catch (Throwable $e) {
$ret = $e->getMessage();
}
echo $firstTerm,
" $symbol ",
str_pad($secondTerm, STRING_PADDING),
" = ",
$bcmath_function($firstTerm, $secondTerm, $scale),
$ret,
"\n";
}
echo "\n";