diff options
Diffstat (limited to 'vendor/brick/math')
-rw-r--r-- | vendor/brick/math/CHANGELOG.md | 34 | ||||
-rw-r--r-- | vendor/brick/math/composer.json | 13 | ||||
-rw-r--r-- | vendor/brick/math/psalm-baseline.xml | 70 | ||||
-rw-r--r-- | vendor/brick/math/src/BigDecimal.php | 92 | ||||
-rw-r--r-- | vendor/brick/math/src/BigInteger.php | 59 | ||||
-rw-r--r-- | vendor/brick/math/src/BigNumber.php | 243 | ||||
-rw-r--r-- | vendor/brick/math/src/BigRational.php | 59 | ||||
-rw-r--r-- | vendor/brick/math/src/Exception/NumberFormatException.php | 10 | ||||
-rw-r--r-- | vendor/brick/math/src/Internal/Calculator.php | 44 | ||||
-rw-r--r-- | vendor/brick/math/src/Internal/Calculator/BcMathCalculator.php | 20 | ||||
-rw-r--r-- | vendor/brick/math/src/Internal/Calculator/GmpCalculator.php | 17 | ||||
-rw-r--r-- | vendor/brick/math/src/Internal/Calculator/NativeCalculator.php | 53 | ||||
-rw-r--r-- | vendor/brick/math/src/RoundingMode.php | 31 |
13 files changed, 425 insertions, 320 deletions
diff --git a/vendor/brick/math/CHANGELOG.md b/vendor/brick/math/CHANGELOG.md index 17cea8d9f..4b47b48dd 100644 --- a/vendor/brick/math/CHANGELOG.md +++ b/vendor/brick/math/CHANGELOG.md @@ -2,6 +2,40 @@ All notable changes to this project will be documented in this file. +## [0.12.3](https://github.com/brick/math/releases/tag/0.12.3) - 2025-02-28 + +✨ **New features** + +- `BigDecimal::getPrecision()` Returns the number of significant digits in a decimal number + +## [0.12.2](https://github.com/brick/math/releases/tag/0.12.2) - 2025-02-26 + +⚡️ **Performance improvements** + +- Division in `NativeCalculator` is now faster for small divisors, thanks to [@Izumi-kun](https://github.com/Izumi-kun) in [#87](https://github.com/brick/math/pull/87). + +👌 **Improvements** + +- Add missing `RoundingNecessaryException` to the `@throws` annotation of `BigNumber::of()` + +## [0.12.1](https://github.com/brick/math/releases/tag/0.12.1) - 2023-11-29 + +⚡️ **Performance improvements** + +- `BigNumber::of()` is now faster, thanks to [@SebastienDug](https://github.com/SebastienDug) in [#77](https://github.com/brick/math/pull/77). + +## [0.12.0](https://github.com/brick/math/releases/tag/0.12.0) - 2023-11-26 + +💥 **Breaking changes** + +- Minimum PHP version is now 8.1 +- `RoundingMode` is now an `enum`; if you're type-hinting rounding modes, you need to type-hint against `RoundingMode` instead of `int` now +- `BigNumber` classes do not implement the `Serializable` interface anymore (they use the [new custom object serialization mechanism](https://wiki.php.net/rfc/custom_object_serialization)) +- The following breaking changes only affect you if you're creating your own `BigNumber` subclasses: + - the return type of `BigNumber::of()` is now `static` + - `BigNumber` has a new abstract method `from()` + - all `public` and `protected` functions of `BigNumber` are now `final` + ## [0.11.0](https://github.com/brick/math/releases/tag/0.11.0) - 2023-01-16 💥 **Breaking changes** diff --git a/vendor/brick/math/composer.json b/vendor/brick/math/composer.json index ed817bdd0..f400aa447 100644 --- a/vendor/brick/math/composer.json +++ b/vendor/brick/math/composer.json @@ -5,21 +5,26 @@ "keywords": [ "Brick", "Math", + "Mathematics", "Arbitrary-precision", "Arithmetic", "BigInteger", "BigDecimal", "BigRational", - "Bignum" + "BigNumber", + "Bignum", + "Decimal", + "Rational", + "Integer" ], "license": "MIT", "require": { - "php": "^8.0" + "php": "^8.1" }, "require-dev": { - "phpunit/phpunit": "^9.0", + "phpunit/phpunit": "^10.1", "php-coveralls/php-coveralls": "^2.2", - "vimeo/psalm": "5.0.0" + "vimeo/psalm": "6.8.8" }, "autoload": { "psr-4": { diff --git a/vendor/brick/math/psalm-baseline.xml b/vendor/brick/math/psalm-baseline.xml new file mode 100644 index 000000000..112adf451 --- /dev/null +++ b/vendor/brick/math/psalm-baseline.xml @@ -0,0 +1,70 @@ +<?xml version="1.0" encoding="UTF-8"?> +<files psalm-version="6.8.8@1361cd33008feb3ae2b4a93f1860e14e538ec8c2"> + <file src="src/BigInteger.php"> + <FalsableReturnStatement> + <code><![CDATA[\hex2bin($hex)]]></code> + </FalsableReturnStatement> + <InvalidFalsableReturnType> + <code><![CDATA[string]]></code> + </InvalidFalsableReturnType> + </file> + <file src="src/Exception/DivisionByZeroException.php"> + <ClassMustBeFinal> + <code><![CDATA[DivisionByZeroException]]></code> + </ClassMustBeFinal> + </file> + <file src="src/Exception/IntegerOverflowException.php"> + <ClassMustBeFinal> + <code><![CDATA[IntegerOverflowException]]></code> + </ClassMustBeFinal> + </file> + <file src="src/Exception/NegativeNumberException.php"> + <ClassMustBeFinal> + <code><![CDATA[NegativeNumberException]]></code> + </ClassMustBeFinal> + </file> + <file src="src/Exception/NumberFormatException.php"> + <ClassMustBeFinal> + <code><![CDATA[NumberFormatException]]></code> + </ClassMustBeFinal> + </file> + <file src="src/Exception/RoundingNecessaryException.php"> + <ClassMustBeFinal> + <code><![CDATA[RoundingNecessaryException]]></code> + </ClassMustBeFinal> + </file> + <file src="src/Internal/Calculator/BcMathCalculator.php"> + <ClassMustBeFinal> + <code><![CDATA[BcMathCalculator]]></code> + </ClassMustBeFinal> + </file> + <file src="src/Internal/Calculator/GmpCalculator.php"> + <ClassMustBeFinal> + <code><![CDATA[GmpCalculator]]></code> + </ClassMustBeFinal> + </file> + <file src="src/Internal/Calculator/NativeCalculator.php"> + <ClassMustBeFinal> + <code><![CDATA[NativeCalculator]]></code> + </ClassMustBeFinal> + <InvalidOperand> + <code><![CDATA[$a * $b]]></code> + <code><![CDATA[$a * 1]]></code> + <code><![CDATA[$a + $b]]></code> + <code><![CDATA[$b * 1]]></code> + <code><![CDATA[$b * 1]]></code> + <code><![CDATA[$blockA * $blockB + $carry]]></code> + <code><![CDATA[$blockA + $blockB]]></code> + <code><![CDATA[$blockA + $blockB + $carry]]></code> + <code><![CDATA[$blockA - $blockB]]></code> + <code><![CDATA[$blockA - $blockB - $carry]]></code> + <code><![CDATA[$carry]]></code> + <code><![CDATA[$mul % $complement]]></code> + <code><![CDATA[$mul - $value]]></code> + <code><![CDATA[$nb - 1]]></code> + <code><![CDATA[$sum += $complement]]></code> + <code><![CDATA[($mul - $value) / $complement]]></code> + <code><![CDATA[($nb - 1) * 10]]></code> + </InvalidOperand> + </file> +</files> diff --git a/vendor/brick/math/src/BigDecimal.php b/vendor/brick/math/src/BigDecimal.php index 02fc65612..21d1c4ae3 100644 --- a/vendor/brick/math/src/BigDecimal.php +++ b/vendor/brick/math/src/BigDecimal.php @@ -8,6 +8,7 @@ use Brick\Math\Exception\DivisionByZeroException; use Brick\Math\Exception\MathException; use Brick\Math\Exception\NegativeNumberException; use Brick\Math\Internal\Calculator; +use Override; /** * Immutable, arbitrary-precision signed decimal numbers. @@ -23,14 +24,14 @@ final class BigDecimal extends BigNumber * No leading zero must be present. * No leading minus sign must be present if the value is 0. */ - private string $value; + private readonly string $value; /** * The scale (number of digits after the decimal point) of this decimal number. * * This must be zero or more. */ - private int $scale; + private readonly int $scale; /** * Protected constructor. Use a factory method to obtain an instance. @@ -45,15 +46,12 @@ final class BigDecimal extends BigNumber } /** - * Creates a BigDecimal of the given value. - * - * @throws MathException If the value cannot be converted to a BigDecimal. - * * @psalm-pure */ - public static function of(BigNumber|int|float|string $value) : BigDecimal + #[Override] + protected static function from(BigNumber $number): static { - return parent::of($value)->toBigDecimal(); + return $number->toBigDecimal(); } /** @@ -223,12 +221,12 @@ final class BigDecimal extends BigNumber * * @param BigNumber|int|float|string $that The divisor. * @param int|null $scale The desired scale, or null to use the scale of this number. - * @param int $roundingMode An optional rounding mode. + * @param RoundingMode $roundingMode An optional rounding mode, defaults to UNNECESSARY. * * @throws \InvalidArgumentException If the scale or rounding mode is invalid. * @throws MathException If the number is invalid, is zero, or rounding was necessary. */ - public function dividedBy(BigNumber|int|float|string $that, ?int $scale = null, int $roundingMode = RoundingMode::UNNECESSARY) : BigDecimal + public function dividedBy(BigNumber|int|float|string $that, ?int $scale = null, RoundingMode $roundingMode = RoundingMode::UNNECESSARY) : BigDecimal { $that = BigDecimal::of($that); @@ -324,7 +322,7 @@ final class BigDecimal extends BigNumber } /** - * Returns the quotient of the division of this number by this given one. + * Returns the quotient of the division of this number by the given one. * * The quotient has a scale of `0`. * @@ -349,7 +347,7 @@ final class BigDecimal extends BigNumber } /** - * Returns the remainder of the division of this number by this given one. + * Returns the remainder of the division of this number by the given one. * * The remainder has a scale of `max($this->scale, $that->scale)`. * @@ -384,6 +382,8 @@ final class BigDecimal extends BigNumber * * @return BigDecimal[] An array containing the quotient and the remainder. * + * @psalm-return array{BigDecimal, BigDecimal} + * * @throws MathException If the divisor is not a valid decimal number, or is zero. */ public function quotientAndRemainder(BigNumber|int|float|string $that) : array @@ -537,6 +537,7 @@ final class BigDecimal extends BigNumber return new BigDecimal(Calculator::get()->neg($this->value), $this->scale); } + #[Override] public function compareTo(BigNumber|int|float|string $that) : int { $that = BigNumber::of($that); @@ -554,6 +555,7 @@ final class BigDecimal extends BigNumber return - $that->compareTo($this); } + #[Override] public function getSign() : int { return ($this->value === '0') ? 0 : (($this->value[0] === '-') ? -1 : 1); @@ -570,6 +572,33 @@ final class BigDecimal extends BigNumber } /** + * Returns the number of significant digits in the number. + * + * This is the number of digits to both sides of the decimal point, stripped of leading zeros. + * The sign has no impact on the result. + * + * Examples: + * 0 => 0 + * 0.0 => 0 + * 123 => 3 + * 123.456 => 6 + * 0.00123 => 3 + * 0.0012300 => 5 + */ + public function getPrecision(): int + { + $value = $this->value; + + if ($value === '0') { + return 0; + } + + $length = \strlen($value); + + return ($value[0] === '-') ? $length - 1 : $length; + } + + /** * Returns a string representing the integral part of this decimal number. * * Example: `-123.456` => `-123`. @@ -611,6 +640,7 @@ final class BigDecimal extends BigNumber return $this->getFractionalPart() !== \str_repeat('0', $this->scale); } + #[Override] public function toBigInteger() : BigInteger { $zeroScaleDecimal = $this->scale === 0 ? $this : $this->dividedBy(1, 0); @@ -618,11 +648,13 @@ final class BigDecimal extends BigNumber return self::newBigInteger($zeroScaleDecimal->value); } + #[Override] public function toBigDecimal() : BigDecimal { return $this; } + #[Override] public function toBigRational() : BigRational { $numerator = self::newBigInteger($this->value); @@ -631,7 +663,8 @@ final class BigDecimal extends BigNumber return self::newBigRational($numerator, $denominator, false); } - public function toScale(int $scale, int $roundingMode = RoundingMode::UNNECESSARY) : BigDecimal + #[Override] + public function toScale(int $scale, RoundingMode $roundingMode = RoundingMode::UNNECESSARY) : BigDecimal { if ($scale === $this->scale) { return $this; @@ -640,16 +673,19 @@ final class BigDecimal extends BigNumber return $this->dividedBy(BigDecimal::one(), $scale, $roundingMode); } + #[Override] public function toInt() : int { return $this->toBigInteger()->toInt(); } + #[Override] public function toFloat() : float { return (float) (string) $this; } + #[Override] public function __toString() : string { if ($this->scale === 0) { @@ -694,36 +730,6 @@ final class BigDecimal extends BigNumber } /** - * This method is required by interface Serializable and SHOULD NOT be accessed directly. - * - * @internal - */ - public function serialize() : string - { - return $this->value . ':' . $this->scale; - } - - /** - * This method is only here to implement interface Serializable and cannot be accessed directly. - * - * @internal - * @psalm-suppress RedundantPropertyInitializationCheck - * - * @throws \LogicException - */ - public function unserialize($value) : void - { - if (isset($this->value)) { - throw new \LogicException('unserialize() is an internal function, it must not be called directly.'); - } - - [$value, $scale] = \explode(':', $value); - - $this->value = $value; - $this->scale = (int) $scale; - } - - /** * Puts the internal values of the given decimal numbers on the same scale. * * @return array{string, string} The scaled integer values of $x and $y. diff --git a/vendor/brick/math/src/BigInteger.php b/vendor/brick/math/src/BigInteger.php index 435679331..72424810d 100644 --- a/vendor/brick/math/src/BigInteger.php +++ b/vendor/brick/math/src/BigInteger.php @@ -10,6 +10,7 @@ use Brick\Math\Exception\MathException; use Brick\Math\Exception\NegativeNumberException; use Brick\Math\Exception\NumberFormatException; use Brick\Math\Internal\Calculator; +use Override; /** * An arbitrary-size integer. @@ -27,7 +28,7 @@ final class BigInteger extends BigNumber * No leading zeros must be present. * No leading minus sign must be present if the number is zero. */ - private string $value; + private readonly string $value; /** * Protected constructor. Use a factory method to obtain an instance. @@ -40,15 +41,12 @@ final class BigInteger extends BigNumber } /** - * Creates a BigInteger of the given value. - * - * @throws MathException If the value cannot be converted to a BigInteger. - * * @psalm-pure */ - public static function of(BigNumber|int|float|string $value) : BigInteger + #[Override] + protected static function from(BigNumber $number): static { - return parent::of($value)->toBigInteger(); + return $number->toBigInteger(); } /** @@ -225,9 +223,10 @@ final class BigInteger extends BigNumber } if ($randomBytesGenerator === null) { - $randomBytesGenerator = 'random_bytes'; + $randomBytesGenerator = random_bytes(...); } + /** @var int<1, max> $byteLength */ $byteLength = \intdiv($numBits - 1, 8) + 1; $extraBits = ($byteLength * 8 - $numBits); @@ -429,12 +428,12 @@ final class BigInteger extends BigNumber * Returns the result of the division of this number by the given one. * * @param BigNumber|int|float|string $that The divisor. Must be convertible to a BigInteger. - * @param int $roundingMode An optional rounding mode. + * @param RoundingMode $roundingMode An optional rounding mode, defaults to UNNECESSARY. * * @throws MathException If the divisor is not a valid number, is not convertible to a BigInteger, is zero, * or RoundingMode::UNNECESSARY is used and the remainder is not zero. */ - public function dividedBy(BigNumber|int|float|string $that, int $roundingMode = RoundingMode::UNNECESSARY) : BigInteger + public function dividedBy(BigNumber|int|float|string $that, RoundingMode $roundingMode = RoundingMode::UNNECESSARY) : BigInteger { $that = BigInteger::of($that); @@ -534,6 +533,8 @@ final class BigInteger extends BigNumber * * @return BigInteger[] An array containing the quotient and the remainder. * + * @psalm-return array{BigInteger, BigInteger} + * * @throws DivisionByZeroException If the divisor is zero. */ public function quotientAndRemainder(BigNumber|int|float|string $that) : array @@ -857,6 +858,7 @@ final class BigInteger extends BigNumber return $this->shiftedRight($n)->isOdd(); } + #[Override] public function compareTo(BigNumber|int|float|string $that) : int { $that = BigNumber::of($that); @@ -868,31 +870,37 @@ final class BigInteger extends BigNumber return - $that->compareTo($this); } + #[Override] public function getSign() : int { return ($this->value === '0') ? 0 : (($this->value[0] === '-') ? -1 : 1); } + #[Override] public function toBigInteger() : BigInteger { return $this; } + #[Override] public function toBigDecimal() : BigDecimal { return self::newBigDecimal($this->value); } + #[Override] public function toBigRational() : BigRational { return self::newBigRational($this, BigInteger::one(), false); } - public function toScale(int $scale, int $roundingMode = RoundingMode::UNNECESSARY) : BigDecimal + #[Override] + public function toScale(int $scale, RoundingMode $roundingMode = RoundingMode::UNNECESSARY) : BigDecimal { return $this->toBigDecimal()->toScale($scale, $roundingMode); } + #[Override] public function toInt() : int { $intValue = (int) $this->value; @@ -904,6 +912,7 @@ final class BigInteger extends BigNumber return $intValue; } + #[Override] public function toFloat() : float { return (float) $this->value; @@ -1014,6 +1023,7 @@ final class BigInteger extends BigNumber return \hex2bin($hex); } + #[Override] public function __toString() : string { return $this->value; @@ -1049,31 +1059,4 @@ final class BigInteger extends BigNumber $this->value = $data['value']; } - - /** - * This method is required by interface Serializable and SHOULD NOT be accessed directly. - * - * @internal - */ - public function serialize() : string - { - return $this->value; - } - - /** - * This method is only here to implement interface Serializable and cannot be accessed directly. - * - * @internal - * @psalm-suppress RedundantPropertyInitializationCheck - * - * @throws \LogicException - */ - public function unserialize($value) : void - { - if (isset($this->value)) { - throw new \LogicException('unserialize() is an internal function, it must not be called directly.'); - } - - $this->value = $value; - } } diff --git a/vendor/brick/math/src/BigNumber.php b/vendor/brick/math/src/BigNumber.php index 80146d207..5dabd314b 100644 --- a/vendor/brick/math/src/BigNumber.php +++ b/vendor/brick/math/src/BigNumber.php @@ -8,32 +8,36 @@ use Brick\Math\Exception\DivisionByZeroException; use Brick\Math\Exception\MathException; use Brick\Math\Exception\NumberFormatException; use Brick\Math\Exception\RoundingNecessaryException; +use Override; /** * Common interface for arbitrary-precision rational numbers. * * @psalm-immutable */ -abstract class BigNumber implements \Serializable, \JsonSerializable +abstract class BigNumber implements \JsonSerializable { /** - * The regular expression used to parse integer, decimal and rational numbers. + * The regular expression used to parse integer or decimal numbers. */ - private const PARSE_REGEXP = + private const PARSE_REGEXP_NUMERICAL = '/^' . '(?<sign>[\-\+])?' . - '(?:' . - '(?:' . - '(?<integral>[0-9]+)?' . - '(?<point>\.)?' . - '(?<fractional>[0-9]+)?' . - '(?:[eE](?<exponent>[\-\+]?[0-9]+))?' . - ')|(?:' . - '(?<numerator>[0-9]+)' . - '\/?' . - '(?<denominator>[0-9]+)' . - ')' . - ')' . + '(?<integral>[0-9]+)?' . + '(?<point>\.)?' . + '(?<fractional>[0-9]+)?' . + '(?:[eE](?<exponent>[\-\+]?[0-9]+))?' . + '$/'; + + /** + * The regular expression used to parse rational numbers. + */ + private const PARSE_REGEXP_RATIONAL = + '/^' . + '(?<sign>[\-\+])?' . + '(?<numerator>[0-9]+)' . + '\/?' . + '(?<denominator>[0-9]+)' . '$/'; /** @@ -48,12 +52,33 @@ abstract class BigNumber implements \Serializable, \JsonSerializable * - strings containing a `.` character or using an exponential notation are returned as BigDecimal * - strings containing only digits with an optional leading `+` or `-` sign are returned as BigInteger * - * @throws NumberFormatException If the format of the number is not valid. + * @throws NumberFormatException If the format of the number is not valid. + * @throws DivisionByZeroException If the value represents a rational number with a denominator of zero. + * @throws RoundingNecessaryException If the value cannot be converted to an instance of the subclass without rounding. + * + * @psalm-pure + */ + final public static function of(BigNumber|int|float|string $value) : static + { + $value = self::_of($value); + + if (static::class === BigNumber::class) { + // https://github.com/vimeo/psalm/issues/10309 + assert($value instanceof static); + + return $value; + } + + return static::from($value); + } + + /** + * @throws NumberFormatException If the format of the number is not valid. * @throws DivisionByZeroException If the value represents a rational number with a denominator of zero. * * @psalm-pure */ - public static function of(BigNumber|int|float|string $value) : BigNumber + private static function _of(BigNumber|int|float|string $value) : BigNumber { if ($value instanceof BigNumber) { return $value; @@ -63,34 +88,25 @@ abstract class BigNumber implements \Serializable, \JsonSerializable return new BigInteger((string) $value); } - $value = \is_float($value) ? self::floatToString($value) : $value; - - $throw = static function() use ($value) : void { - throw new NumberFormatException(\sprintf( - 'The given value "%s" does not represent a valid number.', - $value - )); - }; - - if (\preg_match(self::PARSE_REGEXP, $value, $matches) !== 1) { - $throw(); + if (is_float($value)) { + $value = (string) $value; } - $getMatch = static fn(string $value): ?string => (($matches[$value] ?? '') !== '') ? $matches[$value] : null; + if (str_contains($value, '/')) { + // Rational number + if (\preg_match(self::PARSE_REGEXP_RATIONAL, $value, $matches, PREG_UNMATCHED_AS_NULL) !== 1) { + throw NumberFormatException::invalidFormat($value); + } - $sign = $getMatch('sign'); - $numerator = $getMatch('numerator'); - $denominator = $getMatch('denominator'); + $sign = $matches['sign']; + $numerator = $matches['numerator']; + $denominator = $matches['denominator']; - if ($numerator !== null) { + assert($numerator !== null); assert($denominator !== null); - if ($sign !== null) { - $numerator = $sign . $numerator; - } - - $numerator = self::cleanUp($numerator); - $denominator = self::cleanUp($denominator); + $numerator = self::cleanUp($sign, $numerator); + $denominator = self::cleanUp(null, $denominator); if ($denominator === '0') { throw DivisionByZeroException::denominatorMustNotBeZero(); @@ -101,67 +117,62 @@ abstract class BigNumber implements \Serializable, \JsonSerializable new BigInteger($denominator), false ); - } + } else { + // Integer or decimal number + if (\preg_match(self::PARSE_REGEXP_NUMERICAL, $value, $matches, PREG_UNMATCHED_AS_NULL) !== 1) { + throw NumberFormatException::invalidFormat($value); + } - $point = $getMatch('point'); - $integral = $getMatch('integral'); - $fractional = $getMatch('fractional'); - $exponent = $getMatch('exponent'); + $sign = $matches['sign']; + $point = $matches['point']; + $integral = $matches['integral']; + $fractional = $matches['fractional']; + $exponent = $matches['exponent']; - if ($integral === null && $fractional === null) { - $throw(); - } + if ($integral === null && $fractional === null) { + throw NumberFormatException::invalidFormat($value); + } - if ($integral === null) { - $integral = '0'; - } + if ($integral === null) { + $integral = '0'; + } - if ($point !== null || $exponent !== null) { - $fractional = ($fractional ?? ''); - $exponent = ($exponent !== null) ? (int) $exponent : 0; + if ($point !== null || $exponent !== null) { + $fractional = ($fractional ?? ''); + $exponent = ($exponent !== null) ? (int)$exponent : 0; - if ($exponent === PHP_INT_MIN || $exponent === PHP_INT_MAX) { - throw new NumberFormatException('Exponent too large.'); - } + if ($exponent === PHP_INT_MIN || $exponent === PHP_INT_MAX) { + throw new NumberFormatException('Exponent too large.'); + } - $unscaledValue = self::cleanUp(($sign ?? ''). $integral . $fractional); + $unscaledValue = self::cleanUp($sign, $integral . $fractional); - $scale = \strlen($fractional) - $exponent; + $scale = \strlen($fractional) - $exponent; - if ($scale < 0) { - if ($unscaledValue !== '0') { - $unscaledValue .= \str_repeat('0', - $scale); + if ($scale < 0) { + if ($unscaledValue !== '0') { + $unscaledValue .= \str_repeat('0', -$scale); + } + $scale = 0; } - $scale = 0; - } - return new BigDecimal($unscaledValue, $scale); - } + return new BigDecimal($unscaledValue, $scale); + } - $integral = self::cleanUp(($sign ?? '') . $integral); + $integral = self::cleanUp($sign, $integral); - return new BigInteger($integral); + return new BigInteger($integral); + } } /** - * Safely converts float to string, avoiding locale-dependent issues. + * Overridden by subclasses to convert a BigNumber to an instance of the subclass. * - * @see https://github.com/brick/math/pull/20 + * @throws RoundingNecessaryException If the value cannot be converted. * * @psalm-pure - * @psalm-suppress ImpureFunctionCall */ - private static function floatToString(float $float) : string - { - $currentLocale = \setlocale(LC_NUMERIC, '0'); - \setlocale(LC_NUMERIC, 'C'); - - $result = (string) $float; - - \setlocale(LC_NUMERIC, $currentLocale); - - return $result; - } + abstract protected static function from(BigNumber $number): static; /** * Proxy method to access BigInteger's protected constructor from sibling classes. @@ -169,7 +180,7 @@ abstract class BigNumber implements \Serializable, \JsonSerializable * @internal * @psalm-pure */ - protected function newBigInteger(string $value) : BigInteger + final protected function newBigInteger(string $value) : BigInteger { return new BigInteger($value); } @@ -180,7 +191,7 @@ abstract class BigNumber implements \Serializable, \JsonSerializable * @internal * @psalm-pure */ - protected function newBigDecimal(string $value, int $scale = 0) : BigDecimal + final protected function newBigDecimal(string $value, int $scale = 0) : BigDecimal { return new BigDecimal($value, $scale); } @@ -191,7 +202,7 @@ abstract class BigNumber implements \Serializable, \JsonSerializable * @internal * @psalm-pure */ - protected function newBigRational(BigInteger $numerator, BigInteger $denominator, bool $checkDenominator) : BigRational + final protected function newBigRational(BigInteger $numerator, BigInteger $denominator, bool $checkDenominator) : BigRational { return new BigRational($numerator, $denominator, $checkDenominator); } @@ -205,11 +216,9 @@ abstract class BigNumber implements \Serializable, \JsonSerializable * @throws \InvalidArgumentException If no values are given. * @throws MathException If an argument is not valid. * - * @psalm-suppress LessSpecificReturnStatement - * @psalm-suppress MoreSpecificReturnType * @psalm-pure */ - public static function min(BigNumber|int|float|string ...$values) : static + final public static function min(BigNumber|int|float|string ...$values) : static { $min = null; @@ -237,11 +246,9 @@ abstract class BigNumber implements \Serializable, \JsonSerializable * @throws \InvalidArgumentException If no values are given. * @throws MathException If an argument is not valid. * - * @psalm-suppress LessSpecificReturnStatement - * @psalm-suppress MoreSpecificReturnType * @psalm-pure */ - public static function max(BigNumber|int|float|string ...$values) : static + final public static function max(BigNumber|int|float|string ...$values) : static { $max = null; @@ -271,7 +278,7 @@ abstract class BigNumber implements \Serializable, \JsonSerializable * * @psalm-pure */ - public static function sum(BigNumber|int|float|string ...$values) : static + final public static function sum(BigNumber|int|float|string ...$values) : static { /** @var static|null $sum */ $sum = null; @@ -323,37 +330,28 @@ abstract class BigNumber implements \Serializable, \JsonSerializable } /** - * Removes optional leading zeros and + sign from the given number. + * Removes optional leading zeros and applies sign. * - * @param string $number The number, validated as a non-empty string of digits with optional leading sign. + * @param string|null $sign The sign, '+' or '-', optional. Null is allowed for convenience and treated as '+'. + * @param string $number The number, validated as a non-empty string of digits. * * @psalm-pure */ - private static function cleanUp(string $number) : string + private static function cleanUp(string|null $sign, string $number) : string { - $firstChar = $number[0]; - - if ($firstChar === '+' || $firstChar === '-') { - $number = \substr($number, 1); - } - $number = \ltrim($number, '0'); if ($number === '') { return '0'; } - if ($firstChar === '-') { - return '-' . $number; - } - - return $number; + return $sign === '-' ? '-' . $number : $number; } /** * Checks if this number is equal to the given one. */ - public function isEqualTo(BigNumber|int|float|string $that) : bool + final public function isEqualTo(BigNumber|int|float|string $that) : bool { return $this->compareTo($that) === 0; } @@ -361,7 +359,7 @@ abstract class BigNumber implements \Serializable, \JsonSerializable /** * Checks if this number is strictly lower than the given one. */ - public function isLessThan(BigNumber|int|float|string $that) : bool + final public function isLessThan(BigNumber|int|float|string $that) : bool { return $this->compareTo($that) < 0; } @@ -369,7 +367,7 @@ abstract class BigNumber implements \Serializable, \JsonSerializable /** * Checks if this number is lower than or equal to the given one. */ - public function isLessThanOrEqualTo(BigNumber|int|float|string $that) : bool + final public function isLessThanOrEqualTo(BigNumber|int|float|string $that) : bool { return $this->compareTo($that) <= 0; } @@ -377,7 +375,7 @@ abstract class BigNumber implements \Serializable, \JsonSerializable /** * Checks if this number is strictly greater than the given one. */ - public function isGreaterThan(BigNumber|int|float|string $that) : bool + final public function isGreaterThan(BigNumber|int|float|string $that) : bool { return $this->compareTo($that) > 0; } @@ -385,7 +383,7 @@ abstract class BigNumber implements \Serializable, \JsonSerializable /** * Checks if this number is greater than or equal to the given one. */ - public function isGreaterThanOrEqualTo(BigNumber|int|float|string $that) : bool + final public function isGreaterThanOrEqualTo(BigNumber|int|float|string $that) : bool { return $this->compareTo($that) >= 0; } @@ -393,7 +391,7 @@ abstract class BigNumber implements \Serializable, \JsonSerializable /** * Checks if this number equals zero. */ - public function isZero() : bool + final public function isZero() : bool { return $this->getSign() === 0; } @@ -401,7 +399,7 @@ abstract class BigNumber implements \Serializable, \JsonSerializable /** * Checks if this number is strictly negative. */ - public function isNegative() : bool + final public function isNegative() : bool { return $this->getSign() < 0; } @@ -409,7 +407,7 @@ abstract class BigNumber implements \Serializable, \JsonSerializable /** * Checks if this number is negative or zero. */ - public function isNegativeOrZero() : bool + final public function isNegativeOrZero() : bool { return $this->getSign() <= 0; } @@ -417,7 +415,7 @@ abstract class BigNumber implements \Serializable, \JsonSerializable /** * Checks if this number is strictly positive. */ - public function isPositive() : bool + final public function isPositive() : bool { return $this->getSign() > 0; } @@ -425,7 +423,7 @@ abstract class BigNumber implements \Serializable, \JsonSerializable /** * Checks if this number is positive or zero. */ - public function isPositiveOrZero() : bool + final public function isPositiveOrZero() : bool { return $this->getSign() >= 0; } @@ -433,6 +431,8 @@ abstract class BigNumber implements \Serializable, \JsonSerializable /** * Returns the sign of this number. * + * @psalm-return -1|0|1 + * * @return int -1 if the number is negative, 0 if zero, 1 if positive. */ abstract public function getSign() : int; @@ -440,7 +440,9 @@ abstract class BigNumber implements \Serializable, \JsonSerializable /** * Compares this number to the given one. * - * @return int [-1,0,1] If `$this` is lower than, equal to, or greater than `$that`. + * @psalm-return -1|0|1 + * + * @return int -1 if `$this` is lower than, 0 if equal to, 1 if greater than `$that`. * * @throws MathException If the number is not valid. */ @@ -468,13 +470,13 @@ abstract class BigNumber implements \Serializable, \JsonSerializable /** * Converts this number to a BigDecimal with the given scale, using rounding if necessary. * - * @param int $scale The scale of the resulting `BigDecimal`. - * @param int $roundingMode A `RoundingMode` constant. + * @param int $scale The scale of the resulting `BigDecimal`. + * @param RoundingMode $roundingMode An optional rounding mode, defaults to UNNECESSARY. * * @throws RoundingNecessaryException If this number cannot be converted to the given scale without rounding. * This only applies when RoundingMode::UNNECESSARY is used. */ - abstract public function toScale(int $scale, int $roundingMode = RoundingMode::UNNECESSARY) : BigDecimal; + abstract public function toScale(int $scale, RoundingMode $roundingMode = RoundingMode::UNNECESSARY) : BigDecimal; /** * Returns the exact value of this number as a native integer. @@ -505,7 +507,8 @@ abstract class BigNumber implements \Serializable, \JsonSerializable */ abstract public function __toString() : string; - public function jsonSerialize() : string + #[Override] + final public function jsonSerialize() : string { return $this->__toString(); } diff --git a/vendor/brick/math/src/BigRational.php b/vendor/brick/math/src/BigRational.php index 31f2904fa..fc36e5573 100644 --- a/vendor/brick/math/src/BigRational.php +++ b/vendor/brick/math/src/BigRational.php @@ -8,6 +8,7 @@ use Brick\Math\Exception\DivisionByZeroException; use Brick\Math\Exception\MathException; use Brick\Math\Exception\NumberFormatException; use Brick\Math\Exception\RoundingNecessaryException; +use Override; /** * An arbitrarily large rational number. @@ -21,12 +22,12 @@ final class BigRational extends BigNumber /** * The numerator. */ - private BigInteger $numerator; + private readonly BigInteger $numerator; /** * The denominator. Always strictly positive. */ - private BigInteger $denominator; + private readonly BigInteger $denominator; /** * Protected constructor. Use a factory method to obtain an instance. @@ -55,15 +56,12 @@ final class BigRational extends BigNumber } /** - * Creates a BigRational of the given value. - * - * @throws MathException If the value cannot be converted to a BigRational. - * * @psalm-pure */ - public static function of(BigNumber|int|float|string $value) : BigRational + #[Override] + protected static function from(BigNumber $number): static { - return parent::of($value)->toBigRational(); + return $number->toBigRational(); } /** @@ -181,6 +179,8 @@ final class BigRational extends BigNumber * Returns the quotient and remainder of the division of the numerator by the denominator. * * @return BigInteger[] + * + * @psalm-return array{BigInteger, BigInteger} */ public function quotientAndRemainder() : array { @@ -322,16 +322,19 @@ final class BigRational extends BigNumber return new BigRational($numerator, $denominator, false); } + #[Override] public function compareTo(BigNumber|int|float|string $that) : int { return $this->minus($that)->getSign(); } + #[Override] public function getSign() : int { return $this->numerator->getSign(); } + #[Override] public function toBigInteger() : BigInteger { $simplified = $this->simplified(); @@ -343,32 +346,38 @@ final class BigRational extends BigNumber return $simplified->numerator; } + #[Override] public function toBigDecimal() : BigDecimal { return $this->numerator->toBigDecimal()->exactlyDividedBy($this->denominator); } + #[Override] public function toBigRational() : BigRational { return $this; } - public function toScale(int $scale, int $roundingMode = RoundingMode::UNNECESSARY) : BigDecimal + #[Override] + public function toScale(int $scale, RoundingMode $roundingMode = RoundingMode::UNNECESSARY) : BigDecimal { return $this->numerator->toBigDecimal()->dividedBy($this->denominator, $scale, $roundingMode); } + #[Override] public function toInt() : int { return $this->toBigInteger()->toInt(); } + #[Override] public function toFloat() : float { $simplified = $this->simplified(); return $simplified->numerator->toFloat() / $simplified->denominator->toFloat(); } + #[Override] public function __toString() : string { $numerator = (string) $this->numerator; @@ -378,7 +387,7 @@ final class BigRational extends BigNumber return $numerator; } - return $this->numerator . '/' . $this->denominator; + return $numerator . '/' . $denominator; } /** @@ -412,34 +421,4 @@ final class BigRational extends BigNumber $this->numerator = $data['numerator']; $this->denominator = $data['denominator']; } - - /** - * This method is required by interface Serializable and SHOULD NOT be accessed directly. - * - * @internal - */ - public function serialize() : string - { - return $this->numerator . '/' . $this->denominator; - } - - /** - * This method is only here to implement interface Serializable and cannot be accessed directly. - * - * @internal - * @psalm-suppress RedundantPropertyInitializationCheck - * - * @throws \LogicException - */ - public function unserialize($value) : void - { - if (isset($this->numerator)) { - throw new \LogicException('unserialize() is an internal function, it must not be called directly.'); - } - - [$numerator, $denominator] = \explode('/', $value); - - $this->numerator = BigInteger::of($numerator); - $this->denominator = BigInteger::of($denominator); - } } diff --git a/vendor/brick/math/src/Exception/NumberFormatException.php b/vendor/brick/math/src/Exception/NumberFormatException.php index d9cf6ff5f..119cadbb4 100644 --- a/vendor/brick/math/src/Exception/NumberFormatException.php +++ b/vendor/brick/math/src/Exception/NumberFormatException.php @@ -9,6 +9,14 @@ namespace Brick\Math\Exception; */ class NumberFormatException extends MathException { + public static function invalidFormat(string $value) : self + { + return new self(\sprintf( + 'The given value "%s" does not represent a valid number.', + $value, + )); + } + /** * @param string $char The failing character. * @@ -28,6 +36,6 @@ class NumberFormatException extends MathException $char = '"' . $char . '"'; } - return new self(sprintf('Char %s is not a valid character in the given alphabet.', $char)); + return new self(\sprintf('Char %s is not a valid character in the given alphabet.', $char)); } } 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 } /** diff --git a/vendor/brick/math/src/RoundingMode.php b/vendor/brick/math/src/RoundingMode.php index 06936d8db..e8ee6a8b4 100644 --- a/vendor/brick/math/src/RoundingMode.php +++ b/vendor/brick/math/src/RoundingMode.php @@ -13,24 +13,15 @@ namespace Brick\Math; * regardless the digits' contribution to the value of the number. In other words, considered * as a numerical value, the discarded fraction could have an absolute value greater than one. */ -final class RoundingMode +enum RoundingMode { /** - * Private constructor. This class is not instantiable. - * - * @codeCoverageIgnore - */ - private function __construct() - { - } - - /** * Asserts that the requested operation has an exact result, hence no rounding is necessary. * * If this rounding mode is specified on an operation that yields a result that * cannot be represented at the requested scale, a RoundingNecessaryException is thrown. */ - public const UNNECESSARY = 0; + case UNNECESSARY; /** * Rounds away from zero. @@ -38,7 +29,7 @@ final class RoundingMode * Always increments the digit prior to a nonzero discarded fraction. * Note that this rounding mode never decreases the magnitude of the calculated value. */ - public const UP = 1; + case UP; /** * Rounds towards zero. @@ -46,7 +37,7 @@ final class RoundingMode * Never increments the digit prior to a discarded fraction (i.e., truncates). * Note that this rounding mode never increases the magnitude of the calculated value. */ - public const DOWN = 2; + case DOWN; /** * Rounds towards positive infinity. @@ -54,7 +45,7 @@ final class RoundingMode * If the result is positive, behaves as for UP; if negative, behaves as for DOWN. * Note that this rounding mode never decreases the calculated value. */ - public const CEILING = 3; + case CEILING; /** * Rounds towards negative infinity. @@ -62,7 +53,7 @@ final class RoundingMode * If the result is positive, behave as for DOWN; if negative, behave as for UP. * Note that this rounding mode never increases the calculated value. */ - public const FLOOR = 4; + case FLOOR; /** * Rounds towards "nearest neighbor" unless both neighbors are equidistant, in which case round up. @@ -70,28 +61,28 @@ final class RoundingMode * Behaves as for UP if the discarded fraction is >= 0.5; otherwise, behaves as for DOWN. * Note that this is the rounding mode commonly taught at school. */ - public const HALF_UP = 5; + case HALF_UP; /** * Rounds towards "nearest neighbor" unless both neighbors are equidistant, in which case round down. * * Behaves as for UP if the discarded fraction is > 0.5; otherwise, behaves as for DOWN. */ - public const HALF_DOWN = 6; + case HALF_DOWN; /** * Rounds towards "nearest neighbor" unless both neighbors are equidistant, in which case round towards positive infinity. * * If the result is positive, behaves as for HALF_UP; if negative, behaves as for HALF_DOWN. */ - public const HALF_CEILING = 7; + case HALF_CEILING; /** * Rounds towards "nearest neighbor" unless both neighbors are equidistant, in which case round towards negative infinity. * * If the result is positive, behaves as for HALF_DOWN; if negative, behaves as for HALF_UP. */ - public const HALF_FLOOR = 8; + case HALF_FLOOR; /** * Rounds towards the "nearest neighbor" unless both neighbors are equidistant, in which case rounds towards the even neighbor. @@ -103,5 +94,5 @@ final class RoundingMode * cumulative error when applied repeatedly over a sequence of calculations. * It is sometimes known as "Banker's rounding", and is chiefly used in the USA. */ - public const HALF_EVEN = 9; + case HALF_EVEN; } |