changes
This commit is contained in:
18
vendor/brick/math/CHANGELOG.md
vendored
18
vendor/brick/math/CHANGELOG.md
vendored
@ -2,6 +2,24 @@
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
## [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**
|
||||
|
13
vendor/brick/math/composer.json
vendored
13
vendor/brick/math/composer.json
vendored
@ -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": "5.16.0"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
|
54
vendor/brick/math/src/BigDecimal.php
vendored
54
vendor/brick/math/src/BigDecimal.php
vendored
@ -23,14 +23,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 +45,11 @@ 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
|
||||
protected static function from(BigNumber $number): static
|
||||
{
|
||||
return parent::of($value)->toBigDecimal();
|
||||
return $number->toBigDecimal();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -223,12 +219,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 +320,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 +345,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 +380,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
|
||||
@ -631,7 +629,7 @@ final class BigDecimal extends BigNumber
|
||||
return self::newBigRational($numerator, $denominator, false);
|
||||
}
|
||||
|
||||
public function toScale(int $scale, int $roundingMode = RoundingMode::UNNECESSARY) : BigDecimal
|
||||
public function toScale(int $scale, RoundingMode $roundingMode = RoundingMode::UNNECESSARY) : BigDecimal
|
||||
{
|
||||
if ($scale === $this->scale) {
|
||||
return $this;
|
||||
@ -693,36 +691,6 @@ final class BigDecimal extends BigNumber
|
||||
$this->scale = $data['scale'];
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
|
48
vendor/brick/math/src/BigInteger.php
vendored
48
vendor/brick/math/src/BigInteger.php
vendored
@ -27,7 +27,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 +40,11 @@ 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
|
||||
protected static function from(BigNumber $number): static
|
||||
{
|
||||
return parent::of($value)->toBigInteger();
|
||||
return $number->toBigInteger();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -225,9 +221,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 +426,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 +531,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
|
||||
@ -888,7 +887,7 @@ final class BigInteger extends BigNumber
|
||||
return self::newBigRational($this, BigInteger::one(), false);
|
||||
}
|
||||
|
||||
public function toScale(int $scale, int $roundingMode = RoundingMode::UNNECESSARY) : BigDecimal
|
||||
public function toScale(int $scale, RoundingMode $roundingMode = RoundingMode::UNNECESSARY) : BigDecimal
|
||||
{
|
||||
return $this->toBigDecimal()->toScale($scale, $roundingMode);
|
||||
}
|
||||
@ -1049,31 +1048,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;
|
||||
}
|
||||
}
|
||||
|
247
vendor/brick/math/src/BigNumber.php
vendored
247
vendor/brick/math/src/BigNumber.php
vendored
@ -14,26 +14,29 @@ use Brick\Math\Exception\RoundingNecessaryException;
|
||||
*
|
||||
* @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]+)' .
|
||||
'$/';
|
||||
|
||||
/**
|
||||
@ -53,7 +56,24 @@ abstract class BigNumber implements \Serializable, \JsonSerializable
|
||||
*
|
||||
* @psalm-pure
|
||||
*/
|
||||
public static function of(BigNumber|int|float|string $value) : BigNumber
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
* @psalm-pure
|
||||
*/
|
||||
private static function _of(BigNumber|int|float|string $value) : BigNumber
|
||||
{
|
||||
if ($value instanceof BigNumber) {
|
||||
return $value;
|
||||
@ -63,34 +83,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;
|
||||
|
||||
$sign = $getMatch('sign');
|
||||
$numerator = $getMatch('numerator');
|
||||
$denominator = $getMatch('denominator');
|
||||
|
||||
if ($numerator !== null) {
|
||||
assert($denominator !== null);
|
||||
|
||||
if ($sign !== null) {
|
||||
$numerator = $sign . $numerator;
|
||||
if (str_contains($value, '/')) {
|
||||
// Rational number
|
||||
if (\preg_match(self::PARSE_REGEXP_RATIONAL, $value, $matches, PREG_UNMATCHED_AS_NULL) !== 1) {
|
||||
throw NumberFormatException::invalidFormat($value);
|
||||
}
|
||||
|
||||
$numerator = self::cleanUp($numerator);
|
||||
$denominator = self::cleanUp($denominator);
|
||||
$sign = $matches['sign'];
|
||||
$numerator = $matches['numerator'];
|
||||
$denominator = $matches['denominator'];
|
||||
|
||||
assert($numerator !== null);
|
||||
assert($denominator !== null);
|
||||
|
||||
$numerator = self::cleanUp($sign, $numerator);
|
||||
$denominator = self::cleanUp(null, $denominator);
|
||||
|
||||
if ($denominator === '0') {
|
||||
throw DivisionByZeroException::denominatorMustNotBeZero();
|
||||
@ -101,67 +112,62 @@ abstract class BigNumber implements \Serializable, \JsonSerializable
|
||||
new BigInteger($denominator),
|
||||
false
|
||||
);
|
||||
}
|
||||
|
||||
$point = $getMatch('point');
|
||||
$integral = $getMatch('integral');
|
||||
$fractional = $getMatch('fractional');
|
||||
$exponent = $getMatch('exponent');
|
||||
|
||||
if ($integral === null && $fractional === null) {
|
||||
$throw();
|
||||
}
|
||||
|
||||
if ($integral === null) {
|
||||
$integral = '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.');
|
||||
} else {
|
||||
// Integer or decimal number
|
||||
if (\preg_match(self::PARSE_REGEXP_NUMERICAL, $value, $matches, PREG_UNMATCHED_AS_NULL) !== 1) {
|
||||
throw NumberFormatException::invalidFormat($value);
|
||||
}
|
||||
|
||||
$unscaledValue = self::cleanUp(($sign ?? ''). $integral . $fractional);
|
||||
$sign = $matches['sign'];
|
||||
$point = $matches['point'];
|
||||
$integral = $matches['integral'];
|
||||
$fractional = $matches['fractional'];
|
||||
$exponent = $matches['exponent'];
|
||||
|
||||
$scale = \strlen($fractional) - $exponent;
|
||||
if ($integral === null && $fractional === null) {
|
||||
throw NumberFormatException::invalidFormat($value);
|
||||
}
|
||||
|
||||
if ($scale < 0) {
|
||||
if ($unscaledValue !== '0') {
|
||||
$unscaledValue .= \str_repeat('0', - $scale);
|
||||
if ($integral === null) {
|
||||
$integral = '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.');
|
||||
}
|
||||
$scale = 0;
|
||||
|
||||
$unscaledValue = self::cleanUp($sign, $integral . $fractional);
|
||||
|
||||
$scale = \strlen($fractional) - $exponent;
|
||||
|
||||
if ($scale < 0) {
|
||||
if ($unscaledValue !== '0') {
|
||||
$unscaledValue .= \str_repeat('0', -$scale);
|
||||
}
|
||||
$scale = 0;
|
||||
}
|
||||
|
||||
return new BigDecimal($unscaledValue, $scale);
|
||||
}
|
||||
|
||||
return new BigDecimal($unscaledValue, $scale);
|
||||
$integral = self::cleanUp($sign, $integral);
|
||||
|
||||
return new BigInteger($integral);
|
||||
}
|
||||
|
||||
$integral = self::cleanUp(($sign ?? '') . $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 MathException 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 +175,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 +186,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 +197,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 +211,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 +241,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 +273,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 +325,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 +354,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 +362,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 +370,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 +378,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 +386,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 +394,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 +402,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 +410,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 +418,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 +426,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 +435,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 +465,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 +502,7 @@ abstract class BigNumber implements \Serializable, \JsonSerializable
|
||||
*/
|
||||
abstract public function __toString() : string;
|
||||
|
||||
public function jsonSerialize() : string
|
||||
final public function jsonSerialize() : string
|
||||
{
|
||||
return $this->__toString();
|
||||
}
|
||||
|
46
vendor/brick/math/src/BigRational.php
vendored
46
vendor/brick/math/src/BigRational.php
vendored
@ -21,12 +21,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 +55,11 @@ 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
|
||||
protected static function from(BigNumber $number): static
|
||||
{
|
||||
return parent::of($value)->toBigRational();
|
||||
return $number->toBigRational();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -181,6 +177,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
|
||||
{
|
||||
@ -353,7 +351,7 @@ final class BigRational extends BigNumber
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function toScale(int $scale, int $roundingMode = RoundingMode::UNNECESSARY) : BigDecimal
|
||||
public function toScale(int $scale, RoundingMode $roundingMode = RoundingMode::UNNECESSARY) : BigDecimal
|
||||
{
|
||||
return $this->numerator->toBigDecimal()->dividedBy($this->denominator, $scale, $roundingMode);
|
||||
}
|
||||
@ -412,34 +410,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);
|
||||
}
|
||||
}
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
44
vendor/brick/math/src/Internal/Calculator.php
vendored
44
vendor/brick/math/src/Internal/Calculator.php
vendored
@ -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;
|
||||
$value = match ($operator) {
|
||||
'and' => $aBin & $bBin,
|
||||
'or' => $aBin | $bBin,
|
||||
'xor' => $aBin ^ $bBin,
|
||||
};
|
||||
|
||||
case 'or':
|
||||
$value = $aBin | $bBin;
|
||||
$negative = ($aNeg or $bNeg);
|
||||
break;
|
||||
|
||||
case 'xor':
|
||||
$value = $aBin ^ $bBin;
|
||||
$negative = ($aNeg xor $bNeg);
|
||||
break;
|
||||
|
||||
// @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);
|
||||
|
@ -35,10 +35,6 @@ class BcMathCalculator extends Calculator
|
||||
return \bcdiv($a, $b, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @psalm-suppress InvalidNullableReturnType
|
||||
* @psalm-suppress NullableReturnStatement
|
||||
*/
|
||||
public function divR(string $a, string $b) : string
|
||||
{
|
||||
return \bcmod($a, $b, 0);
|
||||
@ -49,8 +45,6 @@ class BcMathCalculator extends Calculator
|
||||
$q = \bcdiv($a, $b, 0);
|
||||
$r = \bcmod($a, $b, 0);
|
||||
|
||||
assert($r !== null);
|
||||
|
||||
return [$q, $r];
|
||||
}
|
||||
|
||||
@ -64,10 +58,6 @@ class BcMathCalculator extends Calculator
|
||||
return \bcpowmod($base, $exp, $mod, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @psalm-suppress InvalidNullableReturnType
|
||||
* @psalm-suppress NullableReturnStatement
|
||||
*/
|
||||
public function sqrt(string $n) : string
|
||||
{
|
||||
return \bcsqrt($n, 0);
|
||||
|
@ -23,25 +23,18 @@ 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.')
|
||||
};
|
||||
}
|
||||
|
||||
public function add(string $a, string $b) : string
|
||||
@ -161,10 +154,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,
|
||||
@ -536,7 +527,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 +540,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
|
||||
}
|
||||
|
||||
/**
|
||||
|
31
vendor/brick/math/src/RoundingMode.php
vendored
31
vendor/brick/math/src/RoundingMode.php
vendored
@ -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;
|
||||
}
|
||||
|
Reference in New Issue
Block a user