mirror of
https://github.com/php/php-src.git
synced 2024-11-23 01:44:06 +08:00
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:
commit
9b3af0253f
@ -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;
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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 */
|
||||
|
@ -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
|
||||
|
||||
|
29
ext/bcmath/tests/bcpow_div_by_zero.phpt
Normal file
29
ext/bcmath/tests/bcpow_div_by_zero.phpt
Normal 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
|
41
ext/bcmath/tests/number/methods/pow_div_by_zero.phpt
Normal file
41
ext/bcmath/tests/number/methods/pow_div_by_zero.phpt
Normal 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
|
41
ext/bcmath/tests/number/operators/pow_div_by_zero.phpt
Normal file
41
ext/bcmath/tests/number/operators/pow_div_by_zero.phpt
Normal 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
|
@ -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";
|
||||
|
Loading…
Reference in New Issue
Block a user