diff options
Diffstat (limited to 'vendor/brick/math/src/Internal')
4 files changed, 80 insertions, 54 deletions
diff --git a/vendor/brick/math/src/Internal/Calculator.php b/vendor/brick/math/src/Internal/Calculator.php index b8cecda96..44dd66924 100644 --- a/vendor/brick/math/src/Internal/Calculator.php +++ b/vendor/brick/math/src/Internal/Calculator.php @@ -25,7 +25,7 @@ abstract class Calculator /** * The maximum exponent value allowed for the pow() method. */ - public const MAX_POWER = 1000000; + public const MAX_POWER = 1_000_000; /** * The alphabet for converting from and to base 2 to 36, lowercase. @@ -128,7 +128,9 @@ abstract class Calculator /** * Compares two numbers. * - * @return int [-1, 0, 1] If the first number is less than, equal to, or greater than the second number. + * @psalm-return -1|0|1 + * + * @return int -1 if the first number is less than, 0 if equal to, 1 if greater than the second number. */ final public function cmp(string $a, string $b) : int { @@ -428,16 +430,16 @@ abstract class Calculator * * Rounding is performed when the remainder of the division is not zero. * - * @param string $a The dividend. - * @param string $b The divisor, must not be zero. - * @param int $roundingMode The rounding mode. + * @param string $a The dividend. + * @param string $b The divisor, must not be zero. + * @param RoundingMode $roundingMode The rounding mode. * * @throws \InvalidArgumentException If the rounding mode is invalid. * @throws RoundingNecessaryException If RoundingMode::UNNECESSARY is provided but rounding is necessary. * * @psalm-suppress ImpureFunctionCall */ - final public function divRound(string $a, string $b, int $roundingMode) : string + final public function divRound(string $a, string $b, RoundingMode $roundingMode) : string { [$quotient, $remainder] = $this->divQR($a, $b); @@ -571,27 +573,17 @@ abstract class Calculator $bBin = $this->twosComplement($bBin); } - switch ($operator) { - case 'and': - $value = $aBin & $bBin; - $negative = ($aNeg and $bNeg); - break; - - case 'or': - $value = $aBin | $bBin; - $negative = ($aNeg or $bNeg); - break; - - case 'xor': - $value = $aBin ^ $bBin; - $negative = ($aNeg xor $bNeg); - break; + $value = match ($operator) { + 'and' => $aBin & $bBin, + 'or' => $aBin | $bBin, + 'xor' => $aBin ^ $bBin, + }; - // @codeCoverageIgnoreStart - default: - throw new \InvalidArgumentException('Invalid bitwise operator.'); - // @codeCoverageIgnoreEnd - } + $negative = match ($operator) { + 'and' => $aNeg and $bNeg, + 'or' => $aNeg or $bNeg, + 'xor' => $aNeg xor $bNeg, + }; if ($negative) { $value = $this->twosComplement($value); diff --git a/vendor/brick/math/src/Internal/Calculator/BcMathCalculator.php b/vendor/brick/math/src/Internal/Calculator/BcMathCalculator.php index 5457a3c98..93a27ff81 100644 --- a/vendor/brick/math/src/Internal/Calculator/BcMathCalculator.php +++ b/vendor/brick/math/src/Internal/Calculator/BcMathCalculator.php @@ -5,6 +5,7 @@ declare(strict_types=1); namespace Brick\Math\Internal\Calculator; use Brick\Math\Internal\Calculator; +use Override; /** * Calculator implementation built around the bcmath library. @@ -15,59 +16,58 @@ use Brick\Math\Internal\Calculator; */ class BcMathCalculator extends Calculator { + #[Override] public function add(string $a, string $b) : string { return \bcadd($a, $b, 0); } + #[Override] public function sub(string $a, string $b) : string { return \bcsub($a, $b, 0); } + #[Override] public function mul(string $a, string $b) : string { return \bcmul($a, $b, 0); } + #[Override] public function divQ(string $a, string $b) : string { return \bcdiv($a, $b, 0); } - /** - * @psalm-suppress InvalidNullableReturnType - * @psalm-suppress NullableReturnStatement - */ + #[Override] public function divR(string $a, string $b) : string { return \bcmod($a, $b, 0); } + #[Override] public function divQR(string $a, string $b) : array { $q = \bcdiv($a, $b, 0); $r = \bcmod($a, $b, 0); - assert($r !== null); - return [$q, $r]; } + #[Override] public function pow(string $a, int $e) : string { return \bcpow($a, (string) $e, 0); } + #[Override] public function modPow(string $base, string $exp, string $mod) : string { return \bcpowmod($base, $exp, $mod, 0); } - /** - * @psalm-suppress InvalidNullableReturnType - * @psalm-suppress NullableReturnStatement - */ + #[Override] public function sqrt(string $n) : string { return \bcsqrt($n, 0); diff --git a/vendor/brick/math/src/Internal/Calculator/GmpCalculator.php b/vendor/brick/math/src/Internal/Calculator/GmpCalculator.php index 42d4c6927..0e44deeb3 100644 --- a/vendor/brick/math/src/Internal/Calculator/GmpCalculator.php +++ b/vendor/brick/math/src/Internal/Calculator/GmpCalculator.php @@ -5,6 +5,7 @@ declare(strict_types=1); namespace Brick\Math\Internal\Calculator; use Brick\Math\Internal\Calculator; +use Override; /** * Calculator implementation built around the GMP library. @@ -15,31 +16,37 @@ use Brick\Math\Internal\Calculator; */ class GmpCalculator extends Calculator { + #[Override] public function add(string $a, string $b) : string { return \gmp_strval(\gmp_add($a, $b)); } + #[Override] public function sub(string $a, string $b) : string { return \gmp_strval(\gmp_sub($a, $b)); } + #[Override] public function mul(string $a, string $b) : string { return \gmp_strval(\gmp_mul($a, $b)); } + #[Override] public function divQ(string $a, string $b) : string { return \gmp_strval(\gmp_div_q($a, $b)); } + #[Override] public function divR(string $a, string $b) : string { return \gmp_strval(\gmp_div_r($a, $b)); } + #[Override] public function divQR(string $a, string $b) : array { [$q, $r] = \gmp_div_qr($a, $b); @@ -50,11 +57,13 @@ class GmpCalculator extends Calculator ]; } + #[Override] public function pow(string $a, int $e) : string { return \gmp_strval(\gmp_pow($a, $e)); } + #[Override] public function modInverse(string $x, string $m) : ?string { $result = \gmp_invert($x, $m); @@ -66,41 +75,49 @@ class GmpCalculator extends Calculator return \gmp_strval($result); } + #[Override] public function modPow(string $base, string $exp, string $mod) : string { return \gmp_strval(\gmp_powm($base, $exp, $mod)); } + #[Override] public function gcd(string $a, string $b) : string { return \gmp_strval(\gmp_gcd($a, $b)); } + #[Override] public function fromBase(string $number, int $base) : string { return \gmp_strval(\gmp_init($number, $base)); } + #[Override] public function toBase(string $number, int $base) : string { return \gmp_strval($number, $base); } + #[Override] public function and(string $a, string $b) : string { return \gmp_strval(\gmp_and($a, $b)); } + #[Override] public function or(string $a, string $b) : string { return \gmp_strval(\gmp_or($a, $b)); } + #[Override] public function xor(string $a, string $b) : string { return \gmp_strval(\gmp_xor($a, $b)); } + #[Override] public function sqrt(string $n) : string { return \gmp_strval(\gmp_sqrt($n)); diff --git a/vendor/brick/math/src/Internal/Calculator/NativeCalculator.php b/vendor/brick/math/src/Internal/Calculator/NativeCalculator.php index 7c679d24d..f71c55bed 100644 --- a/vendor/brick/math/src/Internal/Calculator/NativeCalculator.php +++ b/vendor/brick/math/src/Internal/Calculator/NativeCalculator.php @@ -5,6 +5,7 @@ declare(strict_types=1); namespace Brick\Math\Internal\Calculator; use Brick\Math\Internal\Calculator; +use Override; /** * Calculator implementation using only native PHP code. @@ -23,27 +24,21 @@ class NativeCalculator extends Calculator * Example: 32-bit: max number 1,999,999,999 (9 digits + carry) * 64-bit: max number 1,999,999,999,999,999,999 (18 digits + carry) */ - private int $maxDigits; + private readonly int $maxDigits; /** * @codeCoverageIgnore */ public function __construct() { - switch (PHP_INT_SIZE) { - case 4: - $this->maxDigits = 9; - break; - - case 8: - $this->maxDigits = 18; - break; - - default: - throw new \RuntimeException('The platform is not 32-bit or 64-bit as expected.'); - } + $this->maxDigits = match (PHP_INT_SIZE) { + 4 => 9, + 8 => 18, + default => throw new \RuntimeException('The platform is not 32-bit or 64-bit as expected.') + }; } + #[Override] public function add(string $a, string $b) : string { /** @@ -75,11 +70,13 @@ class NativeCalculator extends Calculator return $result; } + #[Override] public function sub(string $a, string $b) : string { return $this->add($a, $this->neg($b)); } + #[Override] public function mul(string $a, string $b) : string { /** @@ -123,16 +120,19 @@ class NativeCalculator extends Calculator return $result; } + #[Override] public function divQ(string $a, string $b) : string { return $this->divQR($a, $b)[0]; } + #[Override] public function divR(string $a, string $b): string { return $this->divQR($a, $b)[1]; } + #[Override] public function divQR(string $a, string $b) : array { if ($a === '0') { @@ -161,10 +161,8 @@ class NativeCalculator extends Calculator if (is_int($nb)) { // the only division that may overflow is PHP_INT_MIN / -1, // which cannot happen here as we've already handled a divisor of -1 above. + $q = intdiv($na, $nb); $r = $na % $nb; - $q = ($na - $r) / $nb; - - assert(is_int($q)); return [ (string) $q, @@ -188,6 +186,7 @@ class NativeCalculator extends Calculator return [$q, $r]; } + #[Override] public function pow(string $a, int $e) : string { if ($e === 0) { @@ -216,6 +215,7 @@ class NativeCalculator extends Calculator /** * Algorithm from: https://www.geeksforgeeks.org/modular-exponentiation-power-in-modular-arithmetic/ */ + #[Override] public function modPow(string $base, string $exp, string $mod) : string { // special case: the algorithm below fails with 0 power 0 mod 1 (returns 1 instead of 0) @@ -250,6 +250,7 @@ class NativeCalculator extends Calculator /** * Adapted from https://cp-algorithms.com/num_methods/roots_newton.html */ + #[Override] public function sqrt(string $n) : string { if ($n === '0') { @@ -497,6 +498,22 @@ class NativeCalculator extends Calculator $r = $a; // remainder $z = $y; // focus length, always $y or $y+1 + /** @psalm-var numeric-string $b */ + $nb = $b * 1; // cast to number + // performance optimization in cases where the remainder will never cause int overflow + if (is_int(($nb - 1) * 10 + 9)) { + $r = (int) \substr($a, 0, $z - 1); + + for ($i = $z - 1; $i < $x; $i++) { + $n = $r * 10 + (int) $a[$i]; + /** @psalm-var int $nb */ + $q .= \intdiv($n, $nb); + $r = $n % $nb; + } + + return [\ltrim($q, '0') ?: '0', (string) $r]; + } + for (;;) { $focus = \substr($a, 0, $z); @@ -536,7 +553,7 @@ class NativeCalculator extends Calculator /** * Compares two non-signed large numbers. * - * @return int [-1, 0, 1] + * @psalm-return -1|0|1 */ private function doCmp(string $a, string $b) : int { @@ -549,7 +566,7 @@ class NativeCalculator extends Calculator return $cmp; } - return \strcmp($a, $b) <=> 0; // enforce [-1, 0, 1] + return \strcmp($a, $b) <=> 0; // enforce -1|0|1 } /** |