Skip to content

Commit

Permalink
Merge branch 'PHP-8.4'
Browse files Browse the repository at this point in the history
* PHP-8.4:
  Fixed a bug in BcMath\Number::pow() and bcpow() when raising negative powers of 0. (#16694)
  • Loading branch information
SakiTakamachi committed Nov 19, 2024
2 parents cc308de + 2c8662d commit 9b3af02
Show file tree
Hide file tree
Showing 8 changed files with 147 additions and 20 deletions.
10 changes: 8 additions & 2 deletions ext/bcmath/bcmath.c
Original file line number Diff line number Diff line change
Expand Up @@ -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));

Expand Down Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion ext/bcmath/libbcmath/src/bcmath.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
21 changes: 13 additions & 8 deletions ext/bcmath/libbcmath/src/raise.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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. */
Expand All @@ -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);
Expand All @@ -92,14 +92,19 @@ 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);
*result = temp;
(*result)->n_scale = MIN(scale, (*result)->n_scale);
}
bc_free_num (&power);
return true;
}

/* This is used internally by BCMath */
Expand Down
16 changes: 8 additions & 8 deletions ext/bcmath/tests/bcpow.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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

Expand Down
29 changes: 29 additions & 0 deletions ext/bcmath/tests/bcpow_div_by_zero.phpt
Original file line number Diff line number Diff line change
@@ -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 changes: 41 additions & 0 deletions ext/bcmath/tests/number/methods/pow_div_by_zero.phpt
Original file line number Diff line number Diff line change
@@ -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 changes: 41 additions & 0 deletions ext/bcmath/tests/number/operators/pow_div_by_zero.phpt
Original file line number Diff line number Diff line change
@@ -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
7 changes: 6 additions & 1 deletion ext/bcmath/tests/run_bcmath_tests_function.inc
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down

0 comments on commit 9b3af02

Please sign in to comment.