正在显示
29 个修改的文件
包含
0 行增加
和
4316 行删除
.env
已删除
100755 → 0
| 1 | -APP_NAME=Laravel | ||
| 2 | -APP_ENV=local | ||
| 3 | -APP_KEY=base64:/auyqKGh43iaRgeb1sFk3QO/3Ay43fEB3mxEh7XmmlQ= | ||
| 4 | -APP_DEBUG=true | ||
| 5 | -APP_URL=http://localhost | ||
| 6 | - | ||
| 7 | -LOG_CHANNEL=daily | ||
| 8 | -LOG_DEPRECATIONS_CHANNEL=null | ||
| 9 | -LOG_LEVEL=debug | ||
| 10 | - | ||
| 11 | -DB_CONNECTION=mysql | ||
| 12 | -DB_HOST=127.0.0.1 | ||
| 13 | -DB_PORT=3306 | ||
| 14 | -DB_DATABASE=forget | ||
| 15 | -DB_USERNAME=forget | ||
| 16 | -DB_PASSWORD=forget | ||
| 17 | - | ||
| 18 | -BROADCAST_DRIVER=log | ||
| 19 | -CACHE_DRIVER=file | ||
| 20 | -FILESYSTEM_DRIVER=local | ||
| 21 | -QUEUE_CONNECTION=redis | ||
| 22 | -SESSION_DRIVER=file | ||
| 23 | -SESSION_LIFETIME=120 | ||
| 24 | - | ||
| 25 | -MEMCACHED_HOST=127.0.0.1 | ||
| 26 | -REDIS_HOST=127.0.0.1 | ||
| 27 | -REDIS_PASSWORD=null | ||
| 28 | -REDIS_PORT=6379 | ||
| 29 | - | ||
| 30 | -MAIL_MAILER=smtp | ||
| 31 | -MAIL_HOST=mailhog | ||
| 32 | -MAIL_PORT=1025 | ||
| 33 | -MAIL_USERNAME=null | ||
| 34 | -MAIL_PASSWORD=null | ||
| 35 | -MAIL_ENCRYPTION=null | ||
| 36 | -MAIL_FROM_ADDRESS=null | ||
| 37 | -MAIL_FROM_NAME="${APP_NAME}" | ||
| 38 | - | ||
| 39 | -AWS_ACCESS_KEY_ID= | ||
| 40 | -AWS_SECRET_ACCESS_KEY= | ||
| 41 | -AWS_DEFAULT_REGION=us-east-1 | ||
| 42 | -AWS_BUCKET= | ||
| 43 | -AWS_USE_PATH_STYLE_ENDPOINT=false | ||
| 44 | - | ||
| 45 | -PUSHER_APP_ID= | ||
| 46 | -PUSHER_APP_KEY= | ||
| 47 | -PUSHER_APP_SECRET= | ||
| 48 | -PUSHER_APP_CLUSTER=mt1 | ||
| 49 | - | ||
| 50 | -MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}" | ||
| 51 | -MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}" | ||
| 52 | - | ||
| 53 | -API_URL=https://sitefile.globalso.com/ | ||
| 54 | -TRANSMIT_URL=https://hub.globalso.com/ | ||
| 55 | -MERCHANT_NUMBER=1288 | ||
| 56 | -SECRET_TOKEN=ni4w5ba983c5a805fd54655d015354e6c3bc |
composer.lock
已删除
100755 → 0
此 diff 太大无法显示。
vendor/asm89/stack-cors/LICENSE
已删除
100755 → 0
| 1 | -Copyright (c) 2013-2017 Alexander <iam.asm89@gmail.com> | ||
| 2 | - | ||
| 3 | -Permission is hereby granted, free of charge, to any person obtaining a copy | ||
| 4 | -of this software and associated documentation files (the "Software"), to deal | ||
| 5 | -in the Software without restriction, including without limitation the rights | ||
| 6 | -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
| 7 | -copies of the Software, and to permit persons to whom the Software is furnished | ||
| 8 | -to do so, subject to the following conditions: | ||
| 9 | - | ||
| 10 | -The above copyright notice and this permission notice shall be included in all | ||
| 11 | -copies or substantial portions of the Software. | ||
| 12 | - | ||
| 13 | -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 14 | -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 15 | -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
| 16 | -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| 17 | -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
| 18 | -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
| 19 | -THE SOFTWARE. |
vendor/asm89/stack-cors/README.md
已删除
100755 → 0
| 1 | -# Stack/Cors | ||
| 2 | - | ||
| 3 | -Library and middleware enabling cross-origin resource sharing for your | ||
| 4 | -http-{foundation,kernel} using application. It attempts to implement the | ||
| 5 | -[W3C Recommendation] for cross-origin resource sharing. | ||
| 6 | - | ||
| 7 | -[W3C Recommendation]: http://www.w3.org/TR/cors/ | ||
| 8 | - | ||
| 9 | -Build status:  | ||
| 10 | - | ||
| 11 | -## Installation | ||
| 12 | - | ||
| 13 | -Require `asm89/stack-cors` using composer. | ||
| 14 | - | ||
| 15 | -## Usage | ||
| 16 | - | ||
| 17 | -This package can be used as a library or as [stack middleware]. | ||
| 18 | - | ||
| 19 | -[stack middleware]: http://stackphp.com/ | ||
| 20 | - | ||
| 21 | -### Options | ||
| 22 | - | ||
| 23 | -| Option | Description | Default value | | ||
| 24 | -|------------------------|------------------------------------------------------------|---------------| | ||
| 25 | -| `allowedMethods` | Matches the request method. | `[]` | | ||
| 26 | -| `allowedOrigins` | Matches the request origin. | `[]` | | ||
| 27 | -| `allowedOriginsPatterns` | Matches the request origin with `preg_match`. | `[]` | | ||
| 28 | -| `allowedHeaders` | Sets the Access-Control-Allow-Headers response header. | `[]` | | ||
| 29 | -| `exposedHeaders` | Sets the Access-Control-Expose-Headers response header. | `false` | | ||
| 30 | -| `maxAge` | Sets the Access-Control-Max-Age response header.<br/>Set to `null` to omit the header/use browser default. | `0` | | ||
| 31 | -| `supportsCredentials` | Sets the Access-Control-Allow-Credentials header. | `false` | | ||
| 32 | - | ||
| 33 | -The _allowedMethods_ and _allowedHeaders_ options are case-insensitive. | ||
| 34 | - | ||
| 35 | -You don't need to provide both _allowedOrigins_ and _allowedOriginsPatterns_. If one of the strings passed matches, it is considered a valid origin. | ||
| 36 | - | ||
| 37 | -If `['*']` is provided to _allowedMethods_, _allowedOrigins_ or _allowedHeaders_ all methods / origins / headers are allowed. | ||
| 38 | - | ||
| 39 | -If _supportsCredentials_ is `true`, you must [explicitly set](https://fetch.spec.whatwg.org/#cors-protocol-and-credentials) `allowedHeaders` for any headers which are not CORS safelisted. | ||
| 40 | - | ||
| 41 | -### Example: using the library | ||
| 42 | - | ||
| 43 | -```php | ||
| 44 | -<?php | ||
| 45 | - | ||
| 46 | -use Asm89\Stack\CorsService; | ||
| 47 | - | ||
| 48 | -$cors = new CorsService([ | ||
| 49 | - 'allowedHeaders' => ['x-allowed-header', 'x-other-allowed-header'], | ||
| 50 | - 'allowedMethods' => ['DELETE', 'GET', 'POST', 'PUT'], | ||
| 51 | - 'allowedOrigins' => ['http://localhost'], | ||
| 52 | - 'allowedOriginsPatterns' => ['/localhost:\d/'], | ||
| 53 | - 'exposedHeaders' => false, | ||
| 54 | - 'maxAge' => 600, | ||
| 55 | - 'supportsCredentials' => true, | ||
| 56 | -]); | ||
| 57 | - | ||
| 58 | -$cors->addActualRequestHeaders(Response $response, $origin); | ||
| 59 | -$cors->handlePreflightRequest(Request $request); | ||
| 60 | -$cors->isActualRequestAllowed(Request $request); | ||
| 61 | -$cors->isCorsRequest(Request $request); | ||
| 62 | -$cors->isPreflightRequest(Request $request); | ||
| 63 | -``` | ||
| 64 | - | ||
| 65 | -## Example: using the stack middleware | ||
| 66 | - | ||
| 67 | -```php | ||
| 68 | -<?php | ||
| 69 | - | ||
| 70 | -use Asm89\Stack\Cors; | ||
| 71 | - | ||
| 72 | -$app = new Cors($app, [ | ||
| 73 | - // you can use ['*'] to allow any headers | ||
| 74 | - 'allowedHeaders' => ['x-allowed-header', 'x-other-allowed-header'], | ||
| 75 | - // you can use ['*'] to allow any methods | ||
| 76 | - 'allowedMethods' => ['DELETE', 'GET', 'POST', 'PUT'], | ||
| 77 | - // you can use ['*'] to allow requests from any origin | ||
| 78 | - 'allowedOrigins' => ['localhost'], | ||
| 79 | - // you can enter regexes that are matched to the origin request header | ||
| 80 | - 'allowedOriginsPatterns' => ['/localhost:\d/'], | ||
| 81 | - 'exposedHeaders' => false, | ||
| 82 | - 'maxAge' => 600, | ||
| 83 | - 'supportsCredentials' => false, | ||
| 84 | -]); | ||
| 85 | -``` |
vendor/asm89/stack-cors/composer.json
已删除
100755 → 0
| 1 | -{ | ||
| 2 | - "name": "asm89/stack-cors", | ||
| 3 | - "description": "Cross-origin resource sharing library and stack middleware", | ||
| 4 | - "keywords": ["stack", "cors"], | ||
| 5 | - "homepage": "https://github.com/asm89/stack-cors", | ||
| 6 | - "type": "library", | ||
| 7 | - "license": "MIT", | ||
| 8 | - "authors": [ | ||
| 9 | - { | ||
| 10 | - "name": "Alexander", | ||
| 11 | - "email": "iam.asm89@gmail.com" | ||
| 12 | - } | ||
| 13 | - ], | ||
| 14 | - "require": { | ||
| 15 | - "php": "^7.3|^8.0", | ||
| 16 | - "symfony/http-foundation": "^5.3|^6|^7", | ||
| 17 | - "symfony/http-kernel": "^5.3|^6|^7" | ||
| 18 | - }, | ||
| 19 | - "require-dev": { | ||
| 20 | - "phpunit/phpunit": "^9", | ||
| 21 | - "squizlabs/php_codesniffer": "^3.5" | ||
| 22 | - }, | ||
| 23 | - "autoload": { | ||
| 24 | - "psr-4": { | ||
| 25 | - "Asm89\\Stack\\": "src/" | ||
| 26 | - } | ||
| 27 | - }, | ||
| 28 | - "autoload-dev": { | ||
| 29 | - "psr-4": { | ||
| 30 | - "Asm89\\Stack\\Tests\\": "tests/" | ||
| 31 | - } | ||
| 32 | - }, | ||
| 33 | - "scripts": { | ||
| 34 | - "test": "phpunit", | ||
| 35 | - "check-style": "phpcs -p --standard=PSR12 --exclude=Generic.Files.LineLength --runtime-set ignore_errors_on_exit 1 --runtime-set ignore_warnings_on_exit 1 src", | ||
| 36 | - "fix-style": "phpcbf -p --standard=PSR12 --exclude=Generic.Files.LineLength --runtime-set ignore_errors_on_exit 1 --runtime-set ignore_warnings_on_exit 1 src" | ||
| 37 | - }, | ||
| 38 | - "extra": { | ||
| 39 | - "branch-alias": { | ||
| 40 | - "dev-master": "2.2-dev" | ||
| 41 | - } | ||
| 42 | - }, | ||
| 43 | - "minimum-stability": "beta", | ||
| 44 | - "prefer-stable": true | ||
| 45 | -} |
vendor/asm89/stack-cors/src/Cors.php
已删除
100755 → 0
| 1 | -<?php | ||
| 2 | - | ||
| 3 | -/* | ||
| 4 | - * This file is part of asm89/stack-cors. | ||
| 5 | - * | ||
| 6 | - * (c) Alexander <iam.asm89@gmail.com> | ||
| 7 | - * | ||
| 8 | - * For the full copyright and license information, please view the LICENSE | ||
| 9 | - * file that was distributed with this source code. | ||
| 10 | - */ | ||
| 11 | - | ||
| 12 | -namespace Asm89\Stack; | ||
| 13 | - | ||
| 14 | -use Symfony\Component\HttpFoundation\Response; | ||
| 15 | -use Symfony\Component\HttpKernel\HttpKernelInterface; | ||
| 16 | -use Symfony\Component\HttpFoundation\Request; | ||
| 17 | - | ||
| 18 | -class Cors implements HttpKernelInterface | ||
| 19 | -{ | ||
| 20 | - /** | ||
| 21 | - * @var \Symfony\Component\HttpKernel\HttpKernelInterface | ||
| 22 | - */ | ||
| 23 | - private $app; | ||
| 24 | - | ||
| 25 | - /** | ||
| 26 | - * @var \Asm89\Stack\CorsService | ||
| 27 | - */ | ||
| 28 | - private $cors; | ||
| 29 | - | ||
| 30 | - private $defaultOptions = [ | ||
| 31 | - 'allowedHeaders' => [], | ||
| 32 | - 'allowedMethods' => [], | ||
| 33 | - 'allowedOrigins' => [], | ||
| 34 | - 'allowedOriginsPatterns' => [], | ||
| 35 | - 'exposedHeaders' => [], | ||
| 36 | - 'maxAge' => 0, | ||
| 37 | - 'supportsCredentials' => false, | ||
| 38 | - ]; | ||
| 39 | - | ||
| 40 | - public function __construct(HttpKernelInterface $app, array $options = []) | ||
| 41 | - { | ||
| 42 | - $this->app = $app; | ||
| 43 | - $this->cors = new CorsService(array_merge($this->defaultOptions, $options)); | ||
| 44 | - } | ||
| 45 | - | ||
| 46 | - public function handle(Request $request, int $type = HttpKernelInterface::MAIN_REQUEST, bool $catch = true): Response | ||
| 47 | - { | ||
| 48 | - if ($this->cors->isPreflightRequest($request)) { | ||
| 49 | - $response = $this->cors->handlePreflightRequest($request); | ||
| 50 | - return $this->cors->varyHeader($response, 'Access-Control-Request-Method'); | ||
| 51 | - } | ||
| 52 | - | ||
| 53 | - $response = $this->app->handle($request, $type, $catch); | ||
| 54 | - | ||
| 55 | - if ($request->getMethod() === 'OPTIONS') { | ||
| 56 | - $this->cors->varyHeader($response, 'Access-Control-Request-Method'); | ||
| 57 | - } | ||
| 58 | - | ||
| 59 | - return $this->cors->addActualRequestHeaders($response, $request); | ||
| 60 | - } | ||
| 61 | -} |
| 1 | -<?php | ||
| 2 | - | ||
| 3 | -/* | ||
| 4 | - * This file is part of asm89/stack-cors. | ||
| 5 | - * | ||
| 6 | - * (c) Alexander <iam.asm89@gmail.com> | ||
| 7 | - * | ||
| 8 | - * For the full copyright and license information, please view the LICENSE | ||
| 9 | - * file that was distributed with this source code. | ||
| 10 | - */ | ||
| 11 | - | ||
| 12 | -namespace Asm89\Stack; | ||
| 13 | - | ||
| 14 | -use Symfony\Component\HttpFoundation\Request; | ||
| 15 | -use Symfony\Component\HttpFoundation\Response; | ||
| 16 | - | ||
| 17 | -class CorsService | ||
| 18 | -{ | ||
| 19 | - private $options; | ||
| 20 | - | ||
| 21 | - public function __construct(array $options = []) | ||
| 22 | - { | ||
| 23 | - $this->options = $this->normalizeOptions($options); | ||
| 24 | - } | ||
| 25 | - | ||
| 26 | - private function normalizeOptions(array $options = []): array | ||
| 27 | - { | ||
| 28 | - $options += [ | ||
| 29 | - 'allowedOrigins' => [], | ||
| 30 | - 'allowedOriginsPatterns' => [], | ||
| 31 | - 'supportsCredentials' => false, | ||
| 32 | - 'allowedHeaders' => [], | ||
| 33 | - 'exposedHeaders' => [], | ||
| 34 | - 'allowedMethods' => [], | ||
| 35 | - 'maxAge' => 0, | ||
| 36 | - ]; | ||
| 37 | - | ||
| 38 | - // normalize array('*') to true | ||
| 39 | - if (in_array('*', $options['allowedOrigins'])) { | ||
| 40 | - $options['allowedOrigins'] = true; | ||
| 41 | - } | ||
| 42 | - if (in_array('*', $options['allowedHeaders'])) { | ||
| 43 | - $options['allowedHeaders'] = true; | ||
| 44 | - } else { | ||
| 45 | - $options['allowedHeaders'] = array_map('strtolower', $options['allowedHeaders']); | ||
| 46 | - } | ||
| 47 | - | ||
| 48 | - if (in_array('*', $options['allowedMethods'])) { | ||
| 49 | - $options['allowedMethods'] = true; | ||
| 50 | - } else { | ||
| 51 | - $options['allowedMethods'] = array_map('strtoupper', $options['allowedMethods']); | ||
| 52 | - } | ||
| 53 | - | ||
| 54 | - return $options; | ||
| 55 | - } | ||
| 56 | - | ||
| 57 | - /** | ||
| 58 | - * @deprecated use isOriginAllowed | ||
| 59 | - */ | ||
| 60 | - public function isActualRequestAllowed(Request $request): bool | ||
| 61 | - { | ||
| 62 | - return $this->isOriginAllowed($request); | ||
| 63 | - } | ||
| 64 | - | ||
| 65 | - public function isCorsRequest(Request $request): bool | ||
| 66 | - { | ||
| 67 | - return $request->headers->has('Origin'); | ||
| 68 | - } | ||
| 69 | - | ||
| 70 | - public function isPreflightRequest(Request $request): bool | ||
| 71 | - { | ||
| 72 | - return $request->getMethod() === 'OPTIONS' && $request->headers->has('Access-Control-Request-Method'); | ||
| 73 | - } | ||
| 74 | - | ||
| 75 | - public function handlePreflightRequest(Request $request): Response | ||
| 76 | - { | ||
| 77 | - $response = new Response(); | ||
| 78 | - | ||
| 79 | - $response->setStatusCode(204); | ||
| 80 | - | ||
| 81 | - return $this->addPreflightRequestHeaders($response, $request); | ||
| 82 | - } | ||
| 83 | - | ||
| 84 | - public function addPreflightRequestHeaders(Response $response, Request $request): Response | ||
| 85 | - { | ||
| 86 | - $this->configureAllowedOrigin($response, $request); | ||
| 87 | - | ||
| 88 | - if ($response->headers->has('Access-Control-Allow-Origin')) { | ||
| 89 | - $this->configureAllowCredentials($response, $request); | ||
| 90 | - | ||
| 91 | - $this->configureAllowedMethods($response, $request); | ||
| 92 | - | ||
| 93 | - $this->configureAllowedHeaders($response, $request); | ||
| 94 | - | ||
| 95 | - $this->configureMaxAge($response, $request); | ||
| 96 | - } | ||
| 97 | - | ||
| 98 | - return $response; | ||
| 99 | - } | ||
| 100 | - | ||
| 101 | - public function isOriginAllowed(Request $request): bool | ||
| 102 | - { | ||
| 103 | - if ($this->options['allowedOrigins'] === true) { | ||
| 104 | - return true; | ||
| 105 | - } | ||
| 106 | - | ||
| 107 | - if (!$request->headers->has('Origin')) { | ||
| 108 | - return false; | ||
| 109 | - } | ||
| 110 | - | ||
| 111 | - $origin = $request->headers->get('Origin'); | ||
| 112 | - | ||
| 113 | - if (in_array($origin, $this->options['allowedOrigins'])) { | ||
| 114 | - return true; | ||
| 115 | - } | ||
| 116 | - | ||
| 117 | - foreach ($this->options['allowedOriginsPatterns'] as $pattern) { | ||
| 118 | - if (preg_match($pattern, $origin)) { | ||
| 119 | - return true; | ||
| 120 | - } | ||
| 121 | - } | ||
| 122 | - | ||
| 123 | - return false; | ||
| 124 | - } | ||
| 125 | - | ||
| 126 | - public function addActualRequestHeaders(Response $response, Request $request): Response | ||
| 127 | - { | ||
| 128 | - $this->configureAllowedOrigin($response, $request); | ||
| 129 | - | ||
| 130 | - if ($response->headers->has('Access-Control-Allow-Origin')) { | ||
| 131 | - $this->configureAllowCredentials($response, $request); | ||
| 132 | - | ||
| 133 | - $this->configureExposedHeaders($response, $request); | ||
| 134 | - } | ||
| 135 | - | ||
| 136 | - return $response; | ||
| 137 | - } | ||
| 138 | - | ||
| 139 | - private function configureAllowedOrigin(Response $response, Request $request) | ||
| 140 | - { | ||
| 141 | - if ($this->options['allowedOrigins'] === true && !$this->options['supportsCredentials']) { | ||
| 142 | - // Safe+cacheable, allow everything | ||
| 143 | - $response->headers->set('Access-Control-Allow-Origin', '*'); | ||
| 144 | - } elseif ($this->isSingleOriginAllowed()) { | ||
| 145 | - // Single origins can be safely set | ||
| 146 | - $response->headers->set('Access-Control-Allow-Origin', array_values($this->options['allowedOrigins'])[0]); | ||
| 147 | - } else { | ||
| 148 | - // For dynamic headers, set the requested Origin header when set and allowed | ||
| 149 | - if ($this->isCorsRequest($request) && $this->isOriginAllowed($request)) { | ||
| 150 | - $response->headers->set('Access-Control-Allow-Origin', $request->headers->get('Origin')); | ||
| 151 | - } | ||
| 152 | - | ||
| 153 | - $this->varyHeader($response, 'Origin'); | ||
| 154 | - } | ||
| 155 | - } | ||
| 156 | - | ||
| 157 | - private function isSingleOriginAllowed(): bool | ||
| 158 | - { | ||
| 159 | - if ($this->options['allowedOrigins'] === true || !empty($this->options['allowedOriginsPatterns'])) { | ||
| 160 | - return false; | ||
| 161 | - } | ||
| 162 | - | ||
| 163 | - return count($this->options['allowedOrigins']) === 1; | ||
| 164 | - } | ||
| 165 | - | ||
| 166 | - private function configureAllowedMethods(Response $response, Request $request) | ||
| 167 | - { | ||
| 168 | - if ($this->options['allowedMethods'] === true) { | ||
| 169 | - $allowMethods = strtoupper($request->headers->get('Access-Control-Request-Method')); | ||
| 170 | - $this->varyHeader($response, 'Access-Control-Request-Method'); | ||
| 171 | - } else { | ||
| 172 | - $allowMethods = implode(', ', $this->options['allowedMethods']); | ||
| 173 | - } | ||
| 174 | - | ||
| 175 | - $response->headers->set('Access-Control-Allow-Methods', $allowMethods); | ||
| 176 | - } | ||
| 177 | - | ||
| 178 | - private function configureAllowedHeaders(Response $response, Request $request) | ||
| 179 | - { | ||
| 180 | - if ($this->options['allowedHeaders'] === true) { | ||
| 181 | - $allowHeaders = $request->headers->get('Access-Control-Request-Headers'); | ||
| 182 | - $this->varyHeader($response, 'Access-Control-Request-Headers'); | ||
| 183 | - } else { | ||
| 184 | - $allowHeaders = implode(', ', $this->options['allowedHeaders']); | ||
| 185 | - } | ||
| 186 | - $response->headers->set('Access-Control-Allow-Headers', $allowHeaders); | ||
| 187 | - } | ||
| 188 | - | ||
| 189 | - private function configureAllowCredentials(Response $response, Request $request) | ||
| 190 | - { | ||
| 191 | - if ($this->options['supportsCredentials']) { | ||
| 192 | - $response->headers->set('Access-Control-Allow-Credentials', 'true'); | ||
| 193 | - } | ||
| 194 | - } | ||
| 195 | - | ||
| 196 | - private function configureExposedHeaders(Response $response, Request $request) | ||
| 197 | - { | ||
| 198 | - if ($this->options['exposedHeaders']) { | ||
| 199 | - $response->headers->set('Access-Control-Expose-Headers', implode(', ', $this->options['exposedHeaders'])); | ||
| 200 | - } | ||
| 201 | - } | ||
| 202 | - | ||
| 203 | - private function configureMaxAge(Response $response, Request $request) | ||
| 204 | - { | ||
| 205 | - if ($this->options['maxAge'] !== null) { | ||
| 206 | - $response->headers->set('Access-Control-Max-Age', (int) $this->options['maxAge']); | ||
| 207 | - } | ||
| 208 | - } | ||
| 209 | - | ||
| 210 | - public function varyHeader(Response $response, $header): Response | ||
| 211 | - { | ||
| 212 | - if (!$response->headers->has('Vary')) { | ||
| 213 | - $response->headers->set('Vary', $header); | ||
| 214 | - } elseif (!in_array($header, explode(', ', $response->headers->get('Vary')))) { | ||
| 215 | - $response->headers->set('Vary', $response->headers->get('Vary') . ', ' . $header); | ||
| 216 | - } | ||
| 217 | - | ||
| 218 | - return $response; | ||
| 219 | - } | ||
| 220 | - | ||
| 221 | - private function isSameHost(Request $request): bool | ||
| 222 | - { | ||
| 223 | - return $request->headers->get('Origin') === $request->getSchemeAndHttpHost(); | ||
| 224 | - } | ||
| 225 | -} |
vendor/autoload.php
已删除
100755 → 0
vendor/bin/carbon
已删除
120000 → 0
| 1 | -../nesbot/carbon/bin/carbon |
vendor/bin/patch-type-declarations
已删除
120000 → 0
| 1 | -../symfony/error-handler/Resources/bin/patch-type-declarations |
vendor/bin/php-parse
已删除
120000 → 0
| 1 | -../nikic/php-parser/bin/php-parse |
vendor/bin/phpunit
已删除
120000 → 0
| 1 | -../phpunit/phpunit/phpunit |
vendor/bin/psysh
已删除
120000 → 0
| 1 | -../psy/psysh/bin/psysh |
vendor/bin/sail
已删除
120000 → 0
| 1 | -../laravel/sail/bin/sail |
vendor/bin/var-dump-server
已删除
120000 → 0
| 1 | -../symfony/var-dumper/Resources/bin/var-dump-server |
vendor/brick/math/CHANGELOG.md
已删除
100755 → 0
| 1 | -# Changelog | ||
| 2 | - | ||
| 3 | -All notable changes to this project will be documented in this file. | ||
| 4 | - | ||
| 5 | -## [0.9.3](https://github.com/brick/math/releases/tag/0.9.3) - 2021-08-15 | ||
| 6 | - | ||
| 7 | -🚀 **Compatibility with PHP 8.1** | ||
| 8 | - | ||
| 9 | -- Support for custom object serialization; this removes a warning on PHP 8.1 due to the `Serializable` interface being deprecated (thanks @TRowbotham) | ||
| 10 | - | ||
| 11 | -## [0.9.2](https://github.com/brick/math/releases/tag/0.9.2) - 2021-01-20 | ||
| 12 | - | ||
| 13 | -🐛 **Bug fix** | ||
| 14 | - | ||
| 15 | -- Incorrect results could be returned when using the BCMath calculator, with a default scale set with `bcscale()`, on PHP >= 7.2 (#55). | ||
| 16 | - | ||
| 17 | -## [0.9.1](https://github.com/brick/math/releases/tag/0.9.1) - 2020-08-19 | ||
| 18 | - | ||
| 19 | -✨ New features | ||
| 20 | - | ||
| 21 | -- `BigInteger::not()` returns the bitwise `NOT` value | ||
| 22 | - | ||
| 23 | -🐛 **Bug fixes** | ||
| 24 | - | ||
| 25 | -- `BigInteger::toBytes()` could return an incorrect binary representation for some numbers | ||
| 26 | -- The bitwise operations `and()`, `or()`, `xor()` on `BigInteger` could return an incorrect result when the GMP extension is not available | ||
| 27 | - | ||
| 28 | -## [0.9.0](https://github.com/brick/math/releases/tag/0.9.0) - 2020-08-18 | ||
| 29 | - | ||
| 30 | -👌 **Improvements** | ||
| 31 | - | ||
| 32 | -- `BigNumber::of()` now accepts `.123` and `123.` formats, both of which return a `BigDecimal` | ||
| 33 | - | ||
| 34 | -💥 **Breaking changes** | ||
| 35 | - | ||
| 36 | -- Deprecated method `BigInteger::powerMod()` has been removed - use `modPow()` instead | ||
| 37 | -- Deprecated method `BigInteger::parse()` has been removed - use `fromBase()` instead | ||
| 38 | - | ||
| 39 | -## [0.8.17](https://github.com/brick/math/releases/tag/0.8.17) - 2020-08-19 | ||
| 40 | - | ||
| 41 | -🐛 **Bug fix** | ||
| 42 | - | ||
| 43 | -- `BigInteger::toBytes()` could return an incorrect binary representation for some numbers | ||
| 44 | -- The bitwise operations `and()`, `or()`, `xor()` on `BigInteger` could return an incorrect result when the GMP extension is not available | ||
| 45 | - | ||
| 46 | -## [0.8.16](https://github.com/brick/math/releases/tag/0.8.16) - 2020-08-18 | ||
| 47 | - | ||
| 48 | -🚑 **Critical fix** | ||
| 49 | - | ||
| 50 | -- This version reintroduces the deprecated `BigInteger::parse()` method, that has been removed by mistake in version `0.8.9` and should have lasted for the whole `0.8` release cycle. | ||
| 51 | - | ||
| 52 | -✨ **New features** | ||
| 53 | - | ||
| 54 | -- `BigInteger::modInverse()` calculates a modular multiplicative inverse | ||
| 55 | -- `BigInteger::fromBytes()` creates a `BigInteger` from a byte string | ||
| 56 | -- `BigInteger::toBytes()` converts a `BigInteger` to a byte string | ||
| 57 | -- `BigInteger::randomBits()` creates a pseudo-random `BigInteger` of a given bit length | ||
| 58 | -- `BigInteger::randomRange()` creates a pseudo-random `BigInteger` between two bounds | ||
| 59 | - | ||
| 60 | -💩 **Deprecations** | ||
| 61 | - | ||
| 62 | -- `BigInteger::powerMod()` is now deprecated in favour of `modPow()` | ||
| 63 | - | ||
| 64 | -## [0.8.15](https://github.com/brick/math/releases/tag/0.8.15) - 2020-04-15 | ||
| 65 | - | ||
| 66 | -🐛 **Fixes** | ||
| 67 | - | ||
| 68 | -- added missing `ext-json` requirement, due to `BigNumber` implementing `JsonSerializable` | ||
| 69 | - | ||
| 70 | -⚡️ **Optimizations** | ||
| 71 | - | ||
| 72 | -- additional optimization in `BigInteger::remainder()` | ||
| 73 | - | ||
| 74 | -## [0.8.14](https://github.com/brick/math/releases/tag/0.8.14) - 2020-02-18 | ||
| 75 | - | ||
| 76 | -✨ **New features** | ||
| 77 | - | ||
| 78 | -- `BigInteger::getLowestSetBit()` returns the index of the rightmost one bit | ||
| 79 | - | ||
| 80 | -## [0.8.13](https://github.com/brick/math/releases/tag/0.8.13) - 2020-02-16 | ||
| 81 | - | ||
| 82 | -✨ **New features** | ||
| 83 | - | ||
| 84 | -- `BigInteger::isEven()` tests whether the number is even | ||
| 85 | -- `BigInteger::isOdd()` tests whether the number is odd | ||
| 86 | -- `BigInteger::testBit()` tests if a bit is set | ||
| 87 | -- `BigInteger::getBitLength()` returns the number of bits in the minimal representation of the number | ||
| 88 | - | ||
| 89 | -## [0.8.12](https://github.com/brick/math/releases/tag/0.8.12) - 2020-02-03 | ||
| 90 | - | ||
| 91 | -🛠️ **Maintenance release** | ||
| 92 | - | ||
| 93 | -Classes are now annotated for better static analysis with [psalm](https://psalm.dev/). | ||
| 94 | - | ||
| 95 | -This is a maintenance release: no bug fixes, no new features, no breaking changes. | ||
| 96 | - | ||
| 97 | -## [0.8.11](https://github.com/brick/math/releases/tag/0.8.11) - 2020-01-23 | ||
| 98 | - | ||
| 99 | -✨ **New feature** | ||
| 100 | - | ||
| 101 | -`BigInteger::powerMod()` performs a power-with-modulo operation. Useful for crypto. | ||
| 102 | - | ||
| 103 | -## [0.8.10](https://github.com/brick/math/releases/tag/0.8.10) - 2020-01-21 | ||
| 104 | - | ||
| 105 | -✨ **New feature** | ||
| 106 | - | ||
| 107 | -`BigInteger::mod()` returns the **modulo** of two numbers. The *modulo* differs from the *remainder* when the signs of the operands are different. | ||
| 108 | - | ||
| 109 | -## [0.8.9](https://github.com/brick/math/releases/tag/0.8.9) - 2020-01-08 | ||
| 110 | - | ||
| 111 | -⚡️ **Performance improvements** | ||
| 112 | - | ||
| 113 | -A few additional optimizations in `BigInteger` and `BigDecimal` when one of the operands can be returned as is. Thanks to @tomtomsen in #24. | ||
| 114 | - | ||
| 115 | -## [0.8.8](https://github.com/brick/math/releases/tag/0.8.8) - 2019-04-25 | ||
| 116 | - | ||
| 117 | -🐛 **Bug fixes** | ||
| 118 | - | ||
| 119 | -- `BigInteger::toBase()` could return an empty string for zero values (BCMath & Native calculators only, GMP calculator unaffected) | ||
| 120 | - | ||
| 121 | -✨ **New features** | ||
| 122 | - | ||
| 123 | -- `BigInteger::toArbitraryBase()` converts a number to an arbitrary base, using a custom alphabet | ||
| 124 | -- `BigInteger::fromArbitraryBase()` converts a string in an arbitrary base, using a custom alphabet, back to a number | ||
| 125 | - | ||
| 126 | -These methods can be used as the foundation to convert strings between different bases/alphabets, using BigInteger as an intermediate representation. | ||
| 127 | - | ||
| 128 | -💩 **Deprecations** | ||
| 129 | - | ||
| 130 | -- `BigInteger::parse()` is now deprecated in favour of `fromBase()` | ||
| 131 | - | ||
| 132 | -`BigInteger::fromBase()` works the same way as `parse()`, with 2 minor differences: | ||
| 133 | - | ||
| 134 | -- the `$base` parameter is required, it does not default to `10` | ||
| 135 | -- it throws a `NumberFormatException` instead of an `InvalidArgumentException` when the number is malformed | ||
| 136 | - | ||
| 137 | -## [0.8.7](https://github.com/brick/math/releases/tag/0.8.7) - 2019-04-20 | ||
| 138 | - | ||
| 139 | -**Improvements** | ||
| 140 | - | ||
| 141 | -- Safer conversion from `float` when using custom locales | ||
| 142 | -- **Much faster** `NativeCalculator` implementation 🚀 | ||
| 143 | - | ||
| 144 | -You can expect **at least a 3x performance improvement** for common arithmetic operations when using the library on systems without GMP or BCMath; it gets exponentially faster on multiplications with a high number of digits. This is due to calculations now being performed on whole blocks of digits (the block size depending on the platform, 32-bit or 64-bit) instead of digit-by-digit as before. | ||
| 145 | - | ||
| 146 | -## [0.8.6](https://github.com/brick/math/releases/tag/0.8.6) - 2019-04-11 | ||
| 147 | - | ||
| 148 | -**New method** | ||
| 149 | - | ||
| 150 | -`BigNumber::sum()` returns the sum of one or more numbers. | ||
| 151 | - | ||
| 152 | -## [0.8.5](https://github.com/brick/math/releases/tag/0.8.5) - 2019-02-12 | ||
| 153 | - | ||
| 154 | -**Bug fix**: `of()` factory methods could fail when passing a `float` in environments using a `LC_NUMERIC` locale with a decimal separator other than `'.'` (#20). | ||
| 155 | - | ||
| 156 | -Thanks @manowark 👍 | ||
| 157 | - | ||
| 158 | -## [0.8.4](https://github.com/brick/math/releases/tag/0.8.4) - 2018-12-07 | ||
| 159 | - | ||
| 160 | -**New method** | ||
| 161 | - | ||
| 162 | -`BigDecimal::sqrt()` calculates the square root of a decimal number, to a given scale. | ||
| 163 | - | ||
| 164 | -## [0.8.3](https://github.com/brick/math/releases/tag/0.8.3) - 2018-12-06 | ||
| 165 | - | ||
| 166 | -**New method** | ||
| 167 | - | ||
| 168 | -`BigInteger::sqrt()` calculates the square root of a number (thanks @peter279k). | ||
| 169 | - | ||
| 170 | -**New exception** | ||
| 171 | - | ||
| 172 | -`NegativeNumberException` is thrown when calling `sqrt()` on a negative number. | ||
| 173 | - | ||
| 174 | -## [0.8.2](https://github.com/brick/math/releases/tag/0.8.2) - 2018-11-08 | ||
| 175 | - | ||
| 176 | -**Performance update** | ||
| 177 | - | ||
| 178 | -- Further improvement of `toInt()` performance | ||
| 179 | -- `NativeCalculator` can now perform some multiplications more efficiently | ||
| 180 | - | ||
| 181 | -## [0.8.1](https://github.com/brick/math/releases/tag/0.8.1) - 2018-11-07 | ||
| 182 | - | ||
| 183 | -Performance optimization of `toInt()` methods. | ||
| 184 | - | ||
| 185 | -## [0.8.0](https://github.com/brick/math/releases/tag/0.8.0) - 2018-10-13 | ||
| 186 | - | ||
| 187 | -**Breaking changes** | ||
| 188 | - | ||
| 189 | -The following deprecated methods have been removed. Use the new method name instead: | ||
| 190 | - | ||
| 191 | -| Method removed | Replacement method | | ||
| 192 | -| --- | --- | | ||
| 193 | -| `BigDecimal::getIntegral()` | `BigDecimal::getIntegralPart()` | | ||
| 194 | -| `BigDecimal::getFraction()` | `BigDecimal::getFractionalPart()` | | ||
| 195 | - | ||
| 196 | ---- | ||
| 197 | - | ||
| 198 | -**New features** | ||
| 199 | - | ||
| 200 | -`BigInteger` has been augmented with 5 new methods for bitwise operations: | ||
| 201 | - | ||
| 202 | -| New method | Description | | ||
| 203 | -| --- | --- | | ||
| 204 | -| `and()` | performs a bitwise `AND` operation on two numbers | | ||
| 205 | -| `or()` | performs a bitwise `OR` operation on two numbers | | ||
| 206 | -| `xor()` | performs a bitwise `XOR` operation on two numbers | | ||
| 207 | -| `shiftedLeft()` | returns the number shifted left by a number of bits | | ||
| 208 | -| `shiftedRight()` | returns the number shifted right by a number of bits | | ||
| 209 | - | ||
| 210 | -Thanks to @DASPRiD 👍 | ||
| 211 | - | ||
| 212 | -## [0.7.3](https://github.com/brick/math/releases/tag/0.7.3) - 2018-08-20 | ||
| 213 | - | ||
| 214 | -**New method:** `BigDecimal::hasNonZeroFractionalPart()` | ||
| 215 | - | ||
| 216 | -**Renamed/deprecated methods:** | ||
| 217 | - | ||
| 218 | -- `BigDecimal::getIntegral()` has been renamed to `getIntegralPart()` and is now deprecated | ||
| 219 | -- `BigDecimal::getFraction()` has been renamed to `getFractionalPart()` and is now deprecated | ||
| 220 | - | ||
| 221 | -## [0.7.2](https://github.com/brick/math/releases/tag/0.7.2) - 2018-07-21 | ||
| 222 | - | ||
| 223 | -**Performance update** | ||
| 224 | - | ||
| 225 | -`BigInteger::parse()` and `toBase()` now use GMP's built-in base conversion features when available. | ||
| 226 | - | ||
| 227 | -## [0.7.1](https://github.com/brick/math/releases/tag/0.7.1) - 2018-03-01 | ||
| 228 | - | ||
| 229 | -This is a maintenance release, no code has been changed. | ||
| 230 | - | ||
| 231 | -- When installed with `--no-dev`, the autoloader does not autoload tests anymore | ||
| 232 | -- Tests and other files unnecessary for production are excluded from the dist package | ||
| 233 | - | ||
| 234 | -This will help make installations more compact. | ||
| 235 | - | ||
| 236 | -## [0.7.0](https://github.com/brick/math/releases/tag/0.7.0) - 2017-10-02 | ||
| 237 | - | ||
| 238 | -Methods renamed: | ||
| 239 | - | ||
| 240 | -- `BigNumber:sign()` has been renamed to `getSign()` | ||
| 241 | -- `BigDecimal::unscaledValue()` has been renamed to `getUnscaledValue()` | ||
| 242 | -- `BigDecimal::scale()` has been renamed to `getScale()` | ||
| 243 | -- `BigDecimal::integral()` has been renamed to `getIntegral()` | ||
| 244 | -- `BigDecimal::fraction()` has been renamed to `getFraction()` | ||
| 245 | -- `BigRational::numerator()` has been renamed to `getNumerator()` | ||
| 246 | -- `BigRational::denominator()` has been renamed to `getDenominator()` | ||
| 247 | - | ||
| 248 | -Classes renamed: | ||
| 249 | - | ||
| 250 | -- `ArithmeticException` has been renamed to `MathException` | ||
| 251 | - | ||
| 252 | -## [0.6.2](https://github.com/brick/math/releases/tag/0.6.2) - 2017-10-02 | ||
| 253 | - | ||
| 254 | -The base class for all exceptions is now `MathException`. | ||
| 255 | -`ArithmeticException` has been deprecated, and will be removed in 0.7.0. | ||
| 256 | - | ||
| 257 | -## [0.6.1](https://github.com/brick/math/releases/tag/0.6.1) - 2017-10-02 | ||
| 258 | - | ||
| 259 | -A number of methods have been renamed: | ||
| 260 | - | ||
| 261 | -- `BigNumber:sign()` is deprecated; use `getSign()` instead | ||
| 262 | -- `BigDecimal::unscaledValue()` is deprecated; use `getUnscaledValue()` instead | ||
| 263 | -- `BigDecimal::scale()` is deprecated; use `getScale()` instead | ||
| 264 | -- `BigDecimal::integral()` is deprecated; use `getIntegral()` instead | ||
| 265 | -- `BigDecimal::fraction()` is deprecated; use `getFraction()` instead | ||
| 266 | -- `BigRational::numerator()` is deprecated; use `getNumerator()` instead | ||
| 267 | -- `BigRational::denominator()` is deprecated; use `getDenominator()` instead | ||
| 268 | - | ||
| 269 | -The old methods will be removed in version 0.7.0. | ||
| 270 | - | ||
| 271 | -## [0.6.0](https://github.com/brick/math/releases/tag/0.6.0) - 2017-08-25 | ||
| 272 | - | ||
| 273 | -- Minimum PHP version is now [7.1](https://gophp71.org/); for PHP 5.6 and PHP 7.0 support, use version `0.5` | ||
| 274 | -- Deprecated method `BigDecimal::withScale()` has been removed; use `toScale()` instead | ||
| 275 | -- Method `BigNumber::toInteger()` has been renamed to `toInt()` | ||
| 276 | - | ||
| 277 | -## [0.5.4](https://github.com/brick/math/releases/tag/0.5.4) - 2016-10-17 | ||
| 278 | - | ||
| 279 | -`BigNumber` classes now implement [JsonSerializable](http://php.net/manual/en/class.jsonserializable.php). | ||
| 280 | -The JSON output is always a string. | ||
| 281 | - | ||
| 282 | -## [0.5.3](https://github.com/brick/math/releases/tag/0.5.3) - 2016-03-31 | ||
| 283 | - | ||
| 284 | -This is a bugfix release. Dividing by a negative power of 1 with the same scale as the dividend could trigger an incorrect optimization which resulted in a wrong result. See #6. | ||
| 285 | - | ||
| 286 | -## [0.5.2](https://github.com/brick/math/releases/tag/0.5.2) - 2015-08-06 | ||
| 287 | - | ||
| 288 | -The `$scale` parameter of `BigDecimal::dividedBy()` is now optional again. | ||
| 289 | - | ||
| 290 | -## [0.5.1](https://github.com/brick/math/releases/tag/0.5.1) - 2015-07-05 | ||
| 291 | - | ||
| 292 | -**New method: `BigNumber::toScale()`** | ||
| 293 | - | ||
| 294 | -This allows to convert any `BigNumber` to a `BigDecimal` with a given scale, using rounding if necessary. | ||
| 295 | - | ||
| 296 | -## [0.5.0](https://github.com/brick/math/releases/tag/0.5.0) - 2015-07-04 | ||
| 297 | - | ||
| 298 | -**New features** | ||
| 299 | -- Common `BigNumber` interface for all classes, with the following methods: | ||
| 300 | - - `sign()` and derived methods (`isZero()`, `isPositive()`, ...) | ||
| 301 | - - `compareTo()` and derived methods (`isEqualTo()`, `isGreaterThan()`, ...) that work across different `BigNumber` types | ||
| 302 | - - `toBigInteger()`, `toBigDecimal()`, `toBigRational`() conversion methods | ||
| 303 | - - `toInteger()` and `toFloat()` conversion methods to native types | ||
| 304 | -- Unified `of()` behaviour: every class now accepts any type of number, provided that it can be safely converted to the current type | ||
| 305 | -- New method: `BigDecimal::exactlyDividedBy()`; this method automatically computes the scale of the result, provided that the division yields a finite number of digits | ||
| 306 | -- New methods: `BigRational::quotient()` and `remainder()` | ||
| 307 | -- Fine-grained exceptions: `DivisionByZeroException`, `RoundingNecessaryException`, `NumberFormatException` | ||
| 308 | -- Factory methods `zero()`, `one()` and `ten()` available in all classes | ||
| 309 | -- Rounding mode reintroduced in `BigInteger::dividedBy()` | ||
| 310 | - | ||
| 311 | -This release also comes with many performance improvements. | ||
| 312 | - | ||
| 313 | ---- | ||
| 314 | - | ||
| 315 | -**Breaking changes** | ||
| 316 | -- `BigInteger`: | ||
| 317 | - - `getSign()` is renamed to `sign()` | ||
| 318 | - - `toString()` is renamed to `toBase()` | ||
| 319 | - - `BigInteger::dividedBy()` now throws an exception by default if the remainder is not zero; use `quotient()` to get the previous behaviour | ||
| 320 | -- `BigDecimal`: | ||
| 321 | - - `getSign()` is renamed to `sign()` | ||
| 322 | - - `getUnscaledValue()` is renamed to `unscaledValue()` | ||
| 323 | - - `getScale()` is renamed to `scale()` | ||
| 324 | - - `getIntegral()` is renamed to `integral()` | ||
| 325 | - - `getFraction()` is renamed to `fraction()` | ||
| 326 | - - `divideAndRemainder()` is renamed to `quotientAndRemainder()` | ||
| 327 | - - `dividedBy()` now takes a **mandatory** `$scale` parameter **before** the rounding mode | ||
| 328 | - - `toBigInteger()` does not accept a `$roundingMode` parameter any more | ||
| 329 | - - `toBigRational()` does not simplify the fraction any more; explicitly add `->simplified()` to get the previous behaviour | ||
| 330 | -- `BigRational`: | ||
| 331 | - - `getSign()` is renamed to `sign()` | ||
| 332 | - - `getNumerator()` is renamed to `numerator()` | ||
| 333 | - - `getDenominator()` is renamed to `denominator()` | ||
| 334 | - - `of()` is renamed to `nd()`, while `parse()` is renamed to `of()` | ||
| 335 | -- Miscellaneous: | ||
| 336 | - - `ArithmeticException` is moved to an `Exception\` sub-namespace | ||
| 337 | - - `of()` factory methods now throw `NumberFormatException` instead of `InvalidArgumentException` | ||
| 338 | - | ||
| 339 | -## [0.4.3](https://github.com/brick/math/releases/tag/0.4.3) - 2016-03-31 | ||
| 340 | - | ||
| 341 | -Backport of two bug fixes from the 0.5 branch: | ||
| 342 | -- `BigInteger::parse()` did not always throw `InvalidArgumentException` as expected | ||
| 343 | -- Dividing by a negative power of 1 with the same scale as the dividend could trigger an incorrect optimization which resulted in a wrong result. See #6. | ||
| 344 | - | ||
| 345 | -## [0.4.2](https://github.com/brick/math/releases/tag/0.4.2) - 2015-06-16 | ||
| 346 | - | ||
| 347 | -New method: `BigDecimal::stripTrailingZeros()` | ||
| 348 | - | ||
| 349 | -## [0.4.1](https://github.com/brick/math/releases/tag/0.4.1) - 2015-06-12 | ||
| 350 | - | ||
| 351 | -Introducing a `BigRational` class, to perform calculations on fractions of any size. | ||
| 352 | - | ||
| 353 | -## [0.4.0](https://github.com/brick/math/releases/tag/0.4.0) - 2015-06-12 | ||
| 354 | - | ||
| 355 | -Rounding modes have been removed from `BigInteger`, and are now a concept specific to `BigDecimal`. | ||
| 356 | - | ||
| 357 | -`BigInteger::dividedBy()` now always returns the quotient of the division. | ||
| 358 | - | ||
| 359 | -## [0.3.5](https://github.com/brick/math/releases/tag/0.3.5) - 2016-03-31 | ||
| 360 | - | ||
| 361 | -Backport of two bug fixes from the 0.5 branch: | ||
| 362 | - | ||
| 363 | -- `BigInteger::parse()` did not always throw `InvalidArgumentException` as expected | ||
| 364 | -- Dividing by a negative power of 1 with the same scale as the dividend could trigger an incorrect optimization which resulted in a wrong result. See #6. | ||
| 365 | - | ||
| 366 | -## [0.3.4](https://github.com/brick/math/releases/tag/0.3.4) - 2015-06-11 | ||
| 367 | - | ||
| 368 | -New methods: | ||
| 369 | -- `BigInteger::remainder()` returns the remainder of a division only | ||
| 370 | -- `BigInteger::gcd()` returns the greatest common divisor of two numbers | ||
| 371 | - | ||
| 372 | -## [0.3.3](https://github.com/brick/math/releases/tag/0.3.3) - 2015-06-07 | ||
| 373 | - | ||
| 374 | -Fix `toString()` not handling negative numbers. | ||
| 375 | - | ||
| 376 | -## [0.3.2](https://github.com/brick/math/releases/tag/0.3.2) - 2015-06-07 | ||
| 377 | - | ||
| 378 | -`BigInteger` and `BigDecimal` now have a `getSign()` method that returns: | ||
| 379 | -- `-1` if the number is negative | ||
| 380 | -- `0` if the number is zero | ||
| 381 | -- `1` if the number is positive | ||
| 382 | - | ||
| 383 | -## [0.3.1](https://github.com/brick/math/releases/tag/0.3.1) - 2015-06-05 | ||
| 384 | - | ||
| 385 | -Minor performance improvements | ||
| 386 | - | ||
| 387 | -## [0.3.0](https://github.com/brick/math/releases/tag/0.3.0) - 2015-06-04 | ||
| 388 | - | ||
| 389 | -The `$roundingMode` and `$scale` parameters have been swapped in `BigDecimal::dividedBy()`. | ||
| 390 | - | ||
| 391 | -## [0.2.2](https://github.com/brick/math/releases/tag/0.2.2) - 2015-06-04 | ||
| 392 | - | ||
| 393 | -Stronger immutability guarantee for `BigInteger` and `BigDecimal`. | ||
| 394 | - | ||
| 395 | -So far, it would have been possible to break immutability of these classes by calling the `unserialize()` internal function. This release fixes that. | ||
| 396 | - | ||
| 397 | -## [0.2.1](https://github.com/brick/math/releases/tag/0.2.1) - 2015-06-02 | ||
| 398 | - | ||
| 399 | -Added `BigDecimal::divideAndRemainder()` | ||
| 400 | - | ||
| 401 | -## [0.2.0](https://github.com/brick/math/releases/tag/0.2.0) - 2015-05-22 | ||
| 402 | - | ||
| 403 | -- `min()` and `max()` do not accept an `array` any more, but a variable number of parameters | ||
| 404 | -- **minimum PHP version is now 5.6** | ||
| 405 | -- continuous integration with PHP 7 | ||
| 406 | - | ||
| 407 | -## [0.1.1](https://github.com/brick/math/releases/tag/0.1.1) - 2014-09-01 | ||
| 408 | - | ||
| 409 | -- Added `BigInteger::power()` | ||
| 410 | -- Added HHVM support | ||
| 411 | - | ||
| 412 | -## [0.1.0](https://github.com/brick/math/releases/tag/0.1.0) - 2014-08-31 | ||
| 413 | - | ||
| 414 | -First beta release. | ||
| 415 | - |
vendor/brick/math/LICENSE
已删除
100755 → 0
| 1 | -The MIT License (MIT) | ||
| 2 | - | ||
| 3 | -Copyright (c) 2013-present Benjamin Morel | ||
| 4 | - | ||
| 5 | -Permission is hereby granted, free of charge, to any person obtaining a copy of | ||
| 6 | -this software and associated documentation files (the "Software"), to deal in | ||
| 7 | -the Software without restriction, including without limitation the rights to | ||
| 8 | -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of | ||
| 9 | -the Software, and to permit persons to whom the Software is furnished to do so, | ||
| 10 | -subject to the following conditions: | ||
| 11 | - | ||
| 12 | -The above copyright notice and this permission notice shall be included in all | ||
| 13 | -copies or substantial portions of the Software. | ||
| 14 | - | ||
| 15 | -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 16 | -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS | ||
| 17 | -FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR | ||
| 18 | -COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER | ||
| 19 | -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | ||
| 20 | -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
vendor/brick/math/SECURITY.md
已删除
100755 → 0
| 1 | -# Security Policy | ||
| 2 | - | ||
| 3 | -## Supported Versions | ||
| 4 | - | ||
| 5 | -Only the last two release streams are supported. | ||
| 6 | - | ||
| 7 | -| Version | Supported | | ||
| 8 | -| ------- | ------------------ | | ||
| 9 | -| 0.9.x | :white_check_mark: | | ||
| 10 | -| 0.8.x | :white_check_mark: | | ||
| 11 | -| < 0.8 | :x: | | ||
| 12 | - | ||
| 13 | -## Reporting a Vulnerability | ||
| 14 | - | ||
| 15 | -To report a security vulnerability, please use the | ||
| 16 | -[Tidelift security contact](https://tidelift.com/security). | ||
| 17 | -Tidelift will coordinate the fix and disclosure. |
vendor/brick/math/composer.json
已删除
100755 → 0
| 1 | -{ | ||
| 2 | - "name": "brick/math", | ||
| 3 | - "description": "Arbitrary-precision arithmetic library", | ||
| 4 | - "type": "library", | ||
| 5 | - "keywords": [ | ||
| 6 | - "Brick", | ||
| 7 | - "Math", | ||
| 8 | - "Arbitrary-precision", | ||
| 9 | - "Arithmetic", | ||
| 10 | - "BigInteger", | ||
| 11 | - "BigDecimal", | ||
| 12 | - "BigRational", | ||
| 13 | - "Bignum" | ||
| 14 | - ], | ||
| 15 | - "license": "MIT", | ||
| 16 | - "require": { | ||
| 17 | - "php": "^7.1 || ^8.0", | ||
| 18 | - "ext-json": "*" | ||
| 19 | - }, | ||
| 20 | - "require-dev": { | ||
| 21 | - "phpunit/phpunit": "^7.5.15 || ^8.5 || ^9.0", | ||
| 22 | - "php-coveralls/php-coveralls": "^2.2", | ||
| 23 | - "vimeo/psalm": "4.9.2" | ||
| 24 | - }, | ||
| 25 | - "autoload": { | ||
| 26 | - "psr-4": { | ||
| 27 | - "Brick\\Math\\": "src/" | ||
| 28 | - } | ||
| 29 | - }, | ||
| 30 | - "autoload-dev": { | ||
| 31 | - "psr-4": { | ||
| 32 | - "Brick\\Math\\Tests\\": "tests/" | ||
| 33 | - } | ||
| 34 | - } | ||
| 35 | -} |
vendor/brick/math/src/BigDecimal.php
已删除
100755 → 0
| 1 | -<?php | ||
| 2 | - | ||
| 3 | -declare(strict_types=1); | ||
| 4 | - | ||
| 5 | -namespace Brick\Math; | ||
| 6 | - | ||
| 7 | -use Brick\Math\Exception\DivisionByZeroException; | ||
| 8 | -use Brick\Math\Exception\MathException; | ||
| 9 | -use Brick\Math\Exception\NegativeNumberException; | ||
| 10 | -use Brick\Math\Internal\Calculator; | ||
| 11 | - | ||
| 12 | -/** | ||
| 13 | - * Immutable, arbitrary-precision signed decimal numbers. | ||
| 14 | - * | ||
| 15 | - * @psalm-immutable | ||
| 16 | - */ | ||
| 17 | -final class BigDecimal extends BigNumber | ||
| 18 | -{ | ||
| 19 | - /** | ||
| 20 | - * The unscaled value of this decimal number. | ||
| 21 | - * | ||
| 22 | - * This is a string of digits with an optional leading minus sign. | ||
| 23 | - * No leading zero must be present. | ||
| 24 | - * No leading minus sign must be present if the value is 0. | ||
| 25 | - * | ||
| 26 | - * @var string | ||
| 27 | - */ | ||
| 28 | - private $value; | ||
| 29 | - | ||
| 30 | - /** | ||
| 31 | - * The scale (number of digits after the decimal point) of this decimal number. | ||
| 32 | - * | ||
| 33 | - * This must be zero or more. | ||
| 34 | - * | ||
| 35 | - * @var int | ||
| 36 | - */ | ||
| 37 | - private $scale; | ||
| 38 | - | ||
| 39 | - /** | ||
| 40 | - * Protected constructor. Use a factory method to obtain an instance. | ||
| 41 | - * | ||
| 42 | - * @param string $value The unscaled value, validated. | ||
| 43 | - * @param int $scale The scale, validated. | ||
| 44 | - */ | ||
| 45 | - protected function __construct(string $value, int $scale = 0) | ||
| 46 | - { | ||
| 47 | - $this->value = $value; | ||
| 48 | - $this->scale = $scale; | ||
| 49 | - } | ||
| 50 | - | ||
| 51 | - /** | ||
| 52 | - * Creates a BigDecimal of the given value. | ||
| 53 | - * | ||
| 54 | - * @param BigNumber|int|float|string $value | ||
| 55 | - * | ||
| 56 | - * @return BigDecimal | ||
| 57 | - * | ||
| 58 | - * @throws MathException If the value cannot be converted to a BigDecimal. | ||
| 59 | - * | ||
| 60 | - * @psalm-pure | ||
| 61 | - */ | ||
| 62 | - public static function of($value) : BigNumber | ||
| 63 | - { | ||
| 64 | - return parent::of($value)->toBigDecimal(); | ||
| 65 | - } | ||
| 66 | - | ||
| 67 | - /** | ||
| 68 | - * Creates a BigDecimal from an unscaled value and a scale. | ||
| 69 | - * | ||
| 70 | - * Example: `(12345, 3)` will result in the BigDecimal `12.345`. | ||
| 71 | - * | ||
| 72 | - * @param BigNumber|int|float|string $value The unscaled value. Must be convertible to a BigInteger. | ||
| 73 | - * @param int $scale The scale of the number, positive or zero. | ||
| 74 | - * | ||
| 75 | - * @return BigDecimal | ||
| 76 | - * | ||
| 77 | - * @throws \InvalidArgumentException If the scale is negative. | ||
| 78 | - * | ||
| 79 | - * @psalm-pure | ||
| 80 | - */ | ||
| 81 | - public static function ofUnscaledValue($value, int $scale = 0) : BigDecimal | ||
| 82 | - { | ||
| 83 | - if ($scale < 0) { | ||
| 84 | - throw new \InvalidArgumentException('The scale cannot be negative.'); | ||
| 85 | - } | ||
| 86 | - | ||
| 87 | - return new BigDecimal((string) BigInteger::of($value), $scale); | ||
| 88 | - } | ||
| 89 | - | ||
| 90 | - /** | ||
| 91 | - * Returns a BigDecimal representing zero, with a scale of zero. | ||
| 92 | - * | ||
| 93 | - * @return BigDecimal | ||
| 94 | - * | ||
| 95 | - * @psalm-pure | ||
| 96 | - */ | ||
| 97 | - public static function zero() : BigDecimal | ||
| 98 | - { | ||
| 99 | - /** | ||
| 100 | - * @psalm-suppress ImpureStaticVariable | ||
| 101 | - * @var BigDecimal|null $zero | ||
| 102 | - */ | ||
| 103 | - static $zero; | ||
| 104 | - | ||
| 105 | - if ($zero === null) { | ||
| 106 | - $zero = new BigDecimal('0'); | ||
| 107 | - } | ||
| 108 | - | ||
| 109 | - return $zero; | ||
| 110 | - } | ||
| 111 | - | ||
| 112 | - /** | ||
| 113 | - * Returns a BigDecimal representing one, with a scale of zero. | ||
| 114 | - * | ||
| 115 | - * @return BigDecimal | ||
| 116 | - * | ||
| 117 | - * @psalm-pure | ||
| 118 | - */ | ||
| 119 | - public static function one() : BigDecimal | ||
| 120 | - { | ||
| 121 | - /** | ||
| 122 | - * @psalm-suppress ImpureStaticVariable | ||
| 123 | - * @var BigDecimal|null $one | ||
| 124 | - */ | ||
| 125 | - static $one; | ||
| 126 | - | ||
| 127 | - if ($one === null) { | ||
| 128 | - $one = new BigDecimal('1'); | ||
| 129 | - } | ||
| 130 | - | ||
| 131 | - return $one; | ||
| 132 | - } | ||
| 133 | - | ||
| 134 | - /** | ||
| 135 | - * Returns a BigDecimal representing ten, with a scale of zero. | ||
| 136 | - * | ||
| 137 | - * @return BigDecimal | ||
| 138 | - * | ||
| 139 | - * @psalm-pure | ||
| 140 | - */ | ||
| 141 | - public static function ten() : BigDecimal | ||
| 142 | - { | ||
| 143 | - /** | ||
| 144 | - * @psalm-suppress ImpureStaticVariable | ||
| 145 | - * @var BigDecimal|null $ten | ||
| 146 | - */ | ||
| 147 | - static $ten; | ||
| 148 | - | ||
| 149 | - if ($ten === null) { | ||
| 150 | - $ten = new BigDecimal('10'); | ||
| 151 | - } | ||
| 152 | - | ||
| 153 | - return $ten; | ||
| 154 | - } | ||
| 155 | - | ||
| 156 | - /** | ||
| 157 | - * Returns the sum of this number and the given one. | ||
| 158 | - * | ||
| 159 | - * The result has a scale of `max($this->scale, $that->scale)`. | ||
| 160 | - * | ||
| 161 | - * @param BigNumber|int|float|string $that The number to add. Must be convertible to a BigDecimal. | ||
| 162 | - * | ||
| 163 | - * @return BigDecimal The result. | ||
| 164 | - * | ||
| 165 | - * @throws MathException If the number is not valid, or is not convertible to a BigDecimal. | ||
| 166 | - */ | ||
| 167 | - public function plus($that) : BigDecimal | ||
| 168 | - { | ||
| 169 | - $that = BigDecimal::of($that); | ||
| 170 | - | ||
| 171 | - if ($that->value === '0' && $that->scale <= $this->scale) { | ||
| 172 | - return $this; | ||
| 173 | - } | ||
| 174 | - | ||
| 175 | - if ($this->value === '0' && $this->scale <= $that->scale) { | ||
| 176 | - return $that; | ||
| 177 | - } | ||
| 178 | - | ||
| 179 | - [$a, $b] = $this->scaleValues($this, $that); | ||
| 180 | - | ||
| 181 | - $value = Calculator::get()->add($a, $b); | ||
| 182 | - $scale = $this->scale > $that->scale ? $this->scale : $that->scale; | ||
| 183 | - | ||
| 184 | - return new BigDecimal($value, $scale); | ||
| 185 | - } | ||
| 186 | - | ||
| 187 | - /** | ||
| 188 | - * Returns the difference of this number and the given one. | ||
| 189 | - * | ||
| 190 | - * The result has a scale of `max($this->scale, $that->scale)`. | ||
| 191 | - * | ||
| 192 | - * @param BigNumber|int|float|string $that The number to subtract. Must be convertible to a BigDecimal. | ||
| 193 | - * | ||
| 194 | - * @return BigDecimal The result. | ||
| 195 | - * | ||
| 196 | - * @throws MathException If the number is not valid, or is not convertible to a BigDecimal. | ||
| 197 | - */ | ||
| 198 | - public function minus($that) : BigDecimal | ||
| 199 | - { | ||
| 200 | - $that = BigDecimal::of($that); | ||
| 201 | - | ||
| 202 | - if ($that->value === '0' && $that->scale <= $this->scale) { | ||
| 203 | - return $this; | ||
| 204 | - } | ||
| 205 | - | ||
| 206 | - [$a, $b] = $this->scaleValues($this, $that); | ||
| 207 | - | ||
| 208 | - $value = Calculator::get()->sub($a, $b); | ||
| 209 | - $scale = $this->scale > $that->scale ? $this->scale : $that->scale; | ||
| 210 | - | ||
| 211 | - return new BigDecimal($value, $scale); | ||
| 212 | - } | ||
| 213 | - | ||
| 214 | - /** | ||
| 215 | - * Returns the product of this number and the given one. | ||
| 216 | - * | ||
| 217 | - * The result has a scale of `$this->scale + $that->scale`. | ||
| 218 | - * | ||
| 219 | - * @param BigNumber|int|float|string $that The multiplier. Must be convertible to a BigDecimal. | ||
| 220 | - * | ||
| 221 | - * @return BigDecimal The result. | ||
| 222 | - * | ||
| 223 | - * @throws MathException If the multiplier is not a valid number, or is not convertible to a BigDecimal. | ||
| 224 | - */ | ||
| 225 | - public function multipliedBy($that) : BigDecimal | ||
| 226 | - { | ||
| 227 | - $that = BigDecimal::of($that); | ||
| 228 | - | ||
| 229 | - if ($that->value === '1' && $that->scale === 0) { | ||
| 230 | - return $this; | ||
| 231 | - } | ||
| 232 | - | ||
| 233 | - if ($this->value === '1' && $this->scale === 0) { | ||
| 234 | - return $that; | ||
| 235 | - } | ||
| 236 | - | ||
| 237 | - $value = Calculator::get()->mul($this->value, $that->value); | ||
| 238 | - $scale = $this->scale + $that->scale; | ||
| 239 | - | ||
| 240 | - return new BigDecimal($value, $scale); | ||
| 241 | - } | ||
| 242 | - | ||
| 243 | - /** | ||
| 244 | - * Returns the result of the division of this number by the given one, at the given scale. | ||
| 245 | - * | ||
| 246 | - * @param BigNumber|int|float|string $that The divisor. | ||
| 247 | - * @param int|null $scale The desired scale, or null to use the scale of this number. | ||
| 248 | - * @param int $roundingMode An optional rounding mode. | ||
| 249 | - * | ||
| 250 | - * @return BigDecimal | ||
| 251 | - * | ||
| 252 | - * @throws \InvalidArgumentException If the scale or rounding mode is invalid. | ||
| 253 | - * @throws MathException If the number is invalid, is zero, or rounding was necessary. | ||
| 254 | - */ | ||
| 255 | - public function dividedBy($that, ?int $scale = null, int $roundingMode = RoundingMode::UNNECESSARY) : BigDecimal | ||
| 256 | - { | ||
| 257 | - $that = BigDecimal::of($that); | ||
| 258 | - | ||
| 259 | - if ($that->isZero()) { | ||
| 260 | - throw DivisionByZeroException::divisionByZero(); | ||
| 261 | - } | ||
| 262 | - | ||
| 263 | - if ($scale === null) { | ||
| 264 | - $scale = $this->scale; | ||
| 265 | - } elseif ($scale < 0) { | ||
| 266 | - throw new \InvalidArgumentException('Scale cannot be negative.'); | ||
| 267 | - } | ||
| 268 | - | ||
| 269 | - if ($that->value === '1' && $that->scale === 0 && $scale === $this->scale) { | ||
| 270 | - return $this; | ||
| 271 | - } | ||
| 272 | - | ||
| 273 | - $p = $this->valueWithMinScale($that->scale + $scale); | ||
| 274 | - $q = $that->valueWithMinScale($this->scale - $scale); | ||
| 275 | - | ||
| 276 | - $result = Calculator::get()->divRound($p, $q, $roundingMode); | ||
| 277 | - | ||
| 278 | - return new BigDecimal($result, $scale); | ||
| 279 | - } | ||
| 280 | - | ||
| 281 | - /** | ||
| 282 | - * Returns the exact result of the division of this number by the given one. | ||
| 283 | - * | ||
| 284 | - * The scale of the result is automatically calculated to fit all the fraction digits. | ||
| 285 | - * | ||
| 286 | - * @param BigNumber|int|float|string $that The divisor. Must be convertible to a BigDecimal. | ||
| 287 | - * | ||
| 288 | - * @return BigDecimal The result. | ||
| 289 | - * | ||
| 290 | - * @throws MathException If the divisor is not a valid number, is not convertible to a BigDecimal, is zero, | ||
| 291 | - * or the result yields an infinite number of digits. | ||
| 292 | - */ | ||
| 293 | - public function exactlyDividedBy($that) : BigDecimal | ||
| 294 | - { | ||
| 295 | - $that = BigDecimal::of($that); | ||
| 296 | - | ||
| 297 | - if ($that->value === '0') { | ||
| 298 | - throw DivisionByZeroException::divisionByZero(); | ||
| 299 | - } | ||
| 300 | - | ||
| 301 | - [, $b] = $this->scaleValues($this, $that); | ||
| 302 | - | ||
| 303 | - $d = \rtrim($b, '0'); | ||
| 304 | - $scale = \strlen($b) - \strlen($d); | ||
| 305 | - | ||
| 306 | - $calculator = Calculator::get(); | ||
| 307 | - | ||
| 308 | - foreach ([5, 2] as $prime) { | ||
| 309 | - for (;;) { | ||
| 310 | - $lastDigit = (int) $d[-1]; | ||
| 311 | - | ||
| 312 | - if ($lastDigit % $prime !== 0) { | ||
| 313 | - break; | ||
| 314 | - } | ||
| 315 | - | ||
| 316 | - $d = $calculator->divQ($d, (string) $prime); | ||
| 317 | - $scale++; | ||
| 318 | - } | ||
| 319 | - } | ||
| 320 | - | ||
| 321 | - return $this->dividedBy($that, $scale)->stripTrailingZeros(); | ||
| 322 | - } | ||
| 323 | - | ||
| 324 | - /** | ||
| 325 | - * Returns this number exponentiated to the given value. | ||
| 326 | - * | ||
| 327 | - * The result has a scale of `$this->scale * $exponent`. | ||
| 328 | - * | ||
| 329 | - * @param int $exponent The exponent. | ||
| 330 | - * | ||
| 331 | - * @return BigDecimal The result. | ||
| 332 | - * | ||
| 333 | - * @throws \InvalidArgumentException If the exponent is not in the range 0 to 1,000,000. | ||
| 334 | - */ | ||
| 335 | - public function power(int $exponent) : BigDecimal | ||
| 336 | - { | ||
| 337 | - if ($exponent === 0) { | ||
| 338 | - return BigDecimal::one(); | ||
| 339 | - } | ||
| 340 | - | ||
| 341 | - if ($exponent === 1) { | ||
| 342 | - return $this; | ||
| 343 | - } | ||
| 344 | - | ||
| 345 | - if ($exponent < 0 || $exponent > Calculator::MAX_POWER) { | ||
| 346 | - throw new \InvalidArgumentException(\sprintf( | ||
| 347 | - 'The exponent %d is not in the range 0 to %d.', | ||
| 348 | - $exponent, | ||
| 349 | - Calculator::MAX_POWER | ||
| 350 | - )); | ||
| 351 | - } | ||
| 352 | - | ||
| 353 | - return new BigDecimal(Calculator::get()->pow($this->value, $exponent), $this->scale * $exponent); | ||
| 354 | - } | ||
| 355 | - | ||
| 356 | - /** | ||
| 357 | - * Returns the quotient of the division of this number by this given one. | ||
| 358 | - * | ||
| 359 | - * The quotient has a scale of `0`. | ||
| 360 | - * | ||
| 361 | - * @param BigNumber|int|float|string $that The divisor. Must be convertible to a BigDecimal. | ||
| 362 | - * | ||
| 363 | - * @return BigDecimal The quotient. | ||
| 364 | - * | ||
| 365 | - * @throws MathException If the divisor is not a valid decimal number, or is zero. | ||
| 366 | - */ | ||
| 367 | - public function quotient($that) : BigDecimal | ||
| 368 | - { | ||
| 369 | - $that = BigDecimal::of($that); | ||
| 370 | - | ||
| 371 | - if ($that->isZero()) { | ||
| 372 | - throw DivisionByZeroException::divisionByZero(); | ||
| 373 | - } | ||
| 374 | - | ||
| 375 | - $p = $this->valueWithMinScale($that->scale); | ||
| 376 | - $q = $that->valueWithMinScale($this->scale); | ||
| 377 | - | ||
| 378 | - $quotient = Calculator::get()->divQ($p, $q); | ||
| 379 | - | ||
| 380 | - return new BigDecimal($quotient, 0); | ||
| 381 | - } | ||
| 382 | - | ||
| 383 | - /** | ||
| 384 | - * Returns the remainder of the division of this number by this given one. | ||
| 385 | - * | ||
| 386 | - * The remainder has a scale of `max($this->scale, $that->scale)`. | ||
| 387 | - * | ||
| 388 | - * @param BigNumber|int|float|string $that The divisor. Must be convertible to a BigDecimal. | ||
| 389 | - * | ||
| 390 | - * @return BigDecimal The remainder. | ||
| 391 | - * | ||
| 392 | - * @throws MathException If the divisor is not a valid decimal number, or is zero. | ||
| 393 | - */ | ||
| 394 | - public function remainder($that) : BigDecimal | ||
| 395 | - { | ||
| 396 | - $that = BigDecimal::of($that); | ||
| 397 | - | ||
| 398 | - if ($that->isZero()) { | ||
| 399 | - throw DivisionByZeroException::divisionByZero(); | ||
| 400 | - } | ||
| 401 | - | ||
| 402 | - $p = $this->valueWithMinScale($that->scale); | ||
| 403 | - $q = $that->valueWithMinScale($this->scale); | ||
| 404 | - | ||
| 405 | - $remainder = Calculator::get()->divR($p, $q); | ||
| 406 | - | ||
| 407 | - $scale = $this->scale > $that->scale ? $this->scale : $that->scale; | ||
| 408 | - | ||
| 409 | - return new BigDecimal($remainder, $scale); | ||
| 410 | - } | ||
| 411 | - | ||
| 412 | - /** | ||
| 413 | - * Returns the quotient and remainder of the division of this number by the given one. | ||
| 414 | - * | ||
| 415 | - * The quotient has a scale of `0`, and the remainder has a scale of `max($this->scale, $that->scale)`. | ||
| 416 | - * | ||
| 417 | - * @param BigNumber|int|float|string $that The divisor. Must be convertible to a BigDecimal. | ||
| 418 | - * | ||
| 419 | - * @return BigDecimal[] An array containing the quotient and the remainder. | ||
| 420 | - * | ||
| 421 | - * @throws MathException If the divisor is not a valid decimal number, or is zero. | ||
| 422 | - */ | ||
| 423 | - public function quotientAndRemainder($that) : array | ||
| 424 | - { | ||
| 425 | - $that = BigDecimal::of($that); | ||
| 426 | - | ||
| 427 | - if ($that->isZero()) { | ||
| 428 | - throw DivisionByZeroException::divisionByZero(); | ||
| 429 | - } | ||
| 430 | - | ||
| 431 | - $p = $this->valueWithMinScale($that->scale); | ||
| 432 | - $q = $that->valueWithMinScale($this->scale); | ||
| 433 | - | ||
| 434 | - [$quotient, $remainder] = Calculator::get()->divQR($p, $q); | ||
| 435 | - | ||
| 436 | - $scale = $this->scale > $that->scale ? $this->scale : $that->scale; | ||
| 437 | - | ||
| 438 | - $quotient = new BigDecimal($quotient, 0); | ||
| 439 | - $remainder = new BigDecimal($remainder, $scale); | ||
| 440 | - | ||
| 441 | - return [$quotient, $remainder]; | ||
| 442 | - } | ||
| 443 | - | ||
| 444 | - /** | ||
| 445 | - * Returns the square root of this number, rounded down to the given number of decimals. | ||
| 446 | - * | ||
| 447 | - * @param int $scale | ||
| 448 | - * | ||
| 449 | - * @return BigDecimal | ||
| 450 | - * | ||
| 451 | - * @throws \InvalidArgumentException If the scale is negative. | ||
| 452 | - * @throws NegativeNumberException If this number is negative. | ||
| 453 | - */ | ||
| 454 | - public function sqrt(int $scale) : BigDecimal | ||
| 455 | - { | ||
| 456 | - if ($scale < 0) { | ||
| 457 | - throw new \InvalidArgumentException('Scale cannot be negative.'); | ||
| 458 | - } | ||
| 459 | - | ||
| 460 | - if ($this->value === '0') { | ||
| 461 | - return new BigDecimal('0', $scale); | ||
| 462 | - } | ||
| 463 | - | ||
| 464 | - if ($this->value[0] === '-') { | ||
| 465 | - throw new NegativeNumberException('Cannot calculate the square root of a negative number.'); | ||
| 466 | - } | ||
| 467 | - | ||
| 468 | - $value = $this->value; | ||
| 469 | - $addDigits = 2 * $scale - $this->scale; | ||
| 470 | - | ||
| 471 | - if ($addDigits > 0) { | ||
| 472 | - // add zeros | ||
| 473 | - $value .= \str_repeat('0', $addDigits); | ||
| 474 | - } elseif ($addDigits < 0) { | ||
| 475 | - // trim digits | ||
| 476 | - if (-$addDigits >= \strlen($this->value)) { | ||
| 477 | - // requesting a scale too low, will always yield a zero result | ||
| 478 | - return new BigDecimal('0', $scale); | ||
| 479 | - } | ||
| 480 | - | ||
| 481 | - $value = \substr($value, 0, $addDigits); | ||
| 482 | - } | ||
| 483 | - | ||
| 484 | - $value = Calculator::get()->sqrt($value); | ||
| 485 | - | ||
| 486 | - return new BigDecimal($value, $scale); | ||
| 487 | - } | ||
| 488 | - | ||
| 489 | - /** | ||
| 490 | - * Returns a copy of this BigDecimal with the decimal point moved $n places to the left. | ||
| 491 | - * | ||
| 492 | - * @param int $n | ||
| 493 | - * | ||
| 494 | - * @return BigDecimal | ||
| 495 | - */ | ||
| 496 | - public function withPointMovedLeft(int $n) : BigDecimal | ||
| 497 | - { | ||
| 498 | - if ($n === 0) { | ||
| 499 | - return $this; | ||
| 500 | - } | ||
| 501 | - | ||
| 502 | - if ($n < 0) { | ||
| 503 | - return $this->withPointMovedRight(-$n); | ||
| 504 | - } | ||
| 505 | - | ||
| 506 | - return new BigDecimal($this->value, $this->scale + $n); | ||
| 507 | - } | ||
| 508 | - | ||
| 509 | - /** | ||
| 510 | - * Returns a copy of this BigDecimal with the decimal point moved $n places to the right. | ||
| 511 | - * | ||
| 512 | - * @param int $n | ||
| 513 | - * | ||
| 514 | - * @return BigDecimal | ||
| 515 | - */ | ||
| 516 | - public function withPointMovedRight(int $n) : BigDecimal | ||
| 517 | - { | ||
| 518 | - if ($n === 0) { | ||
| 519 | - return $this; | ||
| 520 | - } | ||
| 521 | - | ||
| 522 | - if ($n < 0) { | ||
| 523 | - return $this->withPointMovedLeft(-$n); | ||
| 524 | - } | ||
| 525 | - | ||
| 526 | - $value = $this->value; | ||
| 527 | - $scale = $this->scale - $n; | ||
| 528 | - | ||
| 529 | - if ($scale < 0) { | ||
| 530 | - if ($value !== '0') { | ||
| 531 | - $value .= \str_repeat('0', -$scale); | ||
| 532 | - } | ||
| 533 | - $scale = 0; | ||
| 534 | - } | ||
| 535 | - | ||
| 536 | - return new BigDecimal($value, $scale); | ||
| 537 | - } | ||
| 538 | - | ||
| 539 | - /** | ||
| 540 | - * Returns a copy of this BigDecimal with any trailing zeros removed from the fractional part. | ||
| 541 | - * | ||
| 542 | - * @return BigDecimal | ||
| 543 | - */ | ||
| 544 | - public function stripTrailingZeros() : BigDecimal | ||
| 545 | - { | ||
| 546 | - if ($this->scale === 0) { | ||
| 547 | - return $this; | ||
| 548 | - } | ||
| 549 | - | ||
| 550 | - $trimmedValue = \rtrim($this->value, '0'); | ||
| 551 | - | ||
| 552 | - if ($trimmedValue === '') { | ||
| 553 | - return BigDecimal::zero(); | ||
| 554 | - } | ||
| 555 | - | ||
| 556 | - $trimmableZeros = \strlen($this->value) - \strlen($trimmedValue); | ||
| 557 | - | ||
| 558 | - if ($trimmableZeros === 0) { | ||
| 559 | - return $this; | ||
| 560 | - } | ||
| 561 | - | ||
| 562 | - if ($trimmableZeros > $this->scale) { | ||
| 563 | - $trimmableZeros = $this->scale; | ||
| 564 | - } | ||
| 565 | - | ||
| 566 | - $value = \substr($this->value, 0, -$trimmableZeros); | ||
| 567 | - $scale = $this->scale - $trimmableZeros; | ||
| 568 | - | ||
| 569 | - return new BigDecimal($value, $scale); | ||
| 570 | - } | ||
| 571 | - | ||
| 572 | - /** | ||
| 573 | - * Returns the absolute value of this number. | ||
| 574 | - * | ||
| 575 | - * @return BigDecimal | ||
| 576 | - */ | ||
| 577 | - public function abs() : BigDecimal | ||
| 578 | - { | ||
| 579 | - return $this->isNegative() ? $this->negated() : $this; | ||
| 580 | - } | ||
| 581 | - | ||
| 582 | - /** | ||
| 583 | - * Returns the negated value of this number. | ||
| 584 | - * | ||
| 585 | - * @return BigDecimal | ||
| 586 | - */ | ||
| 587 | - public function negated() : BigDecimal | ||
| 588 | - { | ||
| 589 | - return new BigDecimal(Calculator::get()->neg($this->value), $this->scale); | ||
| 590 | - } | ||
| 591 | - | ||
| 592 | - /** | ||
| 593 | - * {@inheritdoc} | ||
| 594 | - */ | ||
| 595 | - public function compareTo($that) : int | ||
| 596 | - { | ||
| 597 | - $that = BigNumber::of($that); | ||
| 598 | - | ||
| 599 | - if ($that instanceof BigInteger) { | ||
| 600 | - $that = $that->toBigDecimal(); | ||
| 601 | - } | ||
| 602 | - | ||
| 603 | - if ($that instanceof BigDecimal) { | ||
| 604 | - [$a, $b] = $this->scaleValues($this, $that); | ||
| 605 | - | ||
| 606 | - return Calculator::get()->cmp($a, $b); | ||
| 607 | - } | ||
| 608 | - | ||
| 609 | - return - $that->compareTo($this); | ||
| 610 | - } | ||
| 611 | - | ||
| 612 | - /** | ||
| 613 | - * {@inheritdoc} | ||
| 614 | - */ | ||
| 615 | - public function getSign() : int | ||
| 616 | - { | ||
| 617 | - return ($this->value === '0') ? 0 : (($this->value[0] === '-') ? -1 : 1); | ||
| 618 | - } | ||
| 619 | - | ||
| 620 | - /** | ||
| 621 | - * @return BigInteger | ||
| 622 | - */ | ||
| 623 | - public function getUnscaledValue() : BigInteger | ||
| 624 | - { | ||
| 625 | - return BigInteger::create($this->value); | ||
| 626 | - } | ||
| 627 | - | ||
| 628 | - /** | ||
| 629 | - * @return int | ||
| 630 | - */ | ||
| 631 | - public function getScale() : int | ||
| 632 | - { | ||
| 633 | - return $this->scale; | ||
| 634 | - } | ||
| 635 | - | ||
| 636 | - /** | ||
| 637 | - * Returns a string representing the integral part of this decimal number. | ||
| 638 | - * | ||
| 639 | - * Example: `-123.456` => `-123`. | ||
| 640 | - * | ||
| 641 | - * @return string | ||
| 642 | - */ | ||
| 643 | - public function getIntegralPart() : string | ||
| 644 | - { | ||
| 645 | - if ($this->scale === 0) { | ||
| 646 | - return $this->value; | ||
| 647 | - } | ||
| 648 | - | ||
| 649 | - $value = $this->getUnscaledValueWithLeadingZeros(); | ||
| 650 | - | ||
| 651 | - return \substr($value, 0, -$this->scale); | ||
| 652 | - } | ||
| 653 | - | ||
| 654 | - /** | ||
| 655 | - * Returns a string representing the fractional part of this decimal number. | ||
| 656 | - * | ||
| 657 | - * If the scale is zero, an empty string is returned. | ||
| 658 | - * | ||
| 659 | - * Examples: `-123.456` => '456', `123` => ''. | ||
| 660 | - * | ||
| 661 | - * @return string | ||
| 662 | - */ | ||
| 663 | - public function getFractionalPart() : string | ||
| 664 | - { | ||
| 665 | - if ($this->scale === 0) { | ||
| 666 | - return ''; | ||
| 667 | - } | ||
| 668 | - | ||
| 669 | - $value = $this->getUnscaledValueWithLeadingZeros(); | ||
| 670 | - | ||
| 671 | - return \substr($value, -$this->scale); | ||
| 672 | - } | ||
| 673 | - | ||
| 674 | - /** | ||
| 675 | - * Returns whether this decimal number has a non-zero fractional part. | ||
| 676 | - * | ||
| 677 | - * @return bool | ||
| 678 | - */ | ||
| 679 | - public function hasNonZeroFractionalPart() : bool | ||
| 680 | - { | ||
| 681 | - return $this->getFractionalPart() !== \str_repeat('0', $this->scale); | ||
| 682 | - } | ||
| 683 | - | ||
| 684 | - /** | ||
| 685 | - * {@inheritdoc} | ||
| 686 | - */ | ||
| 687 | - public function toBigInteger() : BigInteger | ||
| 688 | - { | ||
| 689 | - $zeroScaleDecimal = $this->scale === 0 ? $this : $this->dividedBy(1, 0); | ||
| 690 | - | ||
| 691 | - return BigInteger::create($zeroScaleDecimal->value); | ||
| 692 | - } | ||
| 693 | - | ||
| 694 | - /** | ||
| 695 | - * {@inheritdoc} | ||
| 696 | - */ | ||
| 697 | - public function toBigDecimal() : BigDecimal | ||
| 698 | - { | ||
| 699 | - return $this; | ||
| 700 | - } | ||
| 701 | - | ||
| 702 | - /** | ||
| 703 | - * {@inheritdoc} | ||
| 704 | - */ | ||
| 705 | - public function toBigRational() : BigRational | ||
| 706 | - { | ||
| 707 | - $numerator = BigInteger::create($this->value); | ||
| 708 | - $denominator = BigInteger::create('1' . \str_repeat('0', $this->scale)); | ||
| 709 | - | ||
| 710 | - return BigRational::create($numerator, $denominator, false); | ||
| 711 | - } | ||
| 712 | - | ||
| 713 | - /** | ||
| 714 | - * {@inheritdoc} | ||
| 715 | - */ | ||
| 716 | - public function toScale(int $scale, int $roundingMode = RoundingMode::UNNECESSARY) : BigDecimal | ||
| 717 | - { | ||
| 718 | - if ($scale === $this->scale) { | ||
| 719 | - return $this; | ||
| 720 | - } | ||
| 721 | - | ||
| 722 | - return $this->dividedBy(BigDecimal::one(), $scale, $roundingMode); | ||
| 723 | - } | ||
| 724 | - | ||
| 725 | - /** | ||
| 726 | - * {@inheritdoc} | ||
| 727 | - */ | ||
| 728 | - public function toInt() : int | ||
| 729 | - { | ||
| 730 | - return $this->toBigInteger()->toInt(); | ||
| 731 | - } | ||
| 732 | - | ||
| 733 | - /** | ||
| 734 | - * {@inheritdoc} | ||
| 735 | - */ | ||
| 736 | - public function toFloat() : float | ||
| 737 | - { | ||
| 738 | - return (float) (string) $this; | ||
| 739 | - } | ||
| 740 | - | ||
| 741 | - /** | ||
| 742 | - * {@inheritdoc} | ||
| 743 | - */ | ||
| 744 | - public function __toString() : string | ||
| 745 | - { | ||
| 746 | - if ($this->scale === 0) { | ||
| 747 | - return $this->value; | ||
| 748 | - } | ||
| 749 | - | ||
| 750 | - $value = $this->getUnscaledValueWithLeadingZeros(); | ||
| 751 | - | ||
| 752 | - return \substr($value, 0, -$this->scale) . '.' . \substr($value, -$this->scale); | ||
| 753 | - } | ||
| 754 | - | ||
| 755 | - /** | ||
| 756 | - * This method is required for serializing the object and SHOULD NOT be accessed directly. | ||
| 757 | - * | ||
| 758 | - * @internal | ||
| 759 | - * | ||
| 760 | - * @return array{value: string, scale: int} | ||
| 761 | - */ | ||
| 762 | - public function __serialize(): array | ||
| 763 | - { | ||
| 764 | - return ['value' => $this->value, 'scale' => $this->scale]; | ||
| 765 | - } | ||
| 766 | - | ||
| 767 | - /** | ||
| 768 | - * This method is only here to allow unserializing the object and cannot be accessed directly. | ||
| 769 | - * | ||
| 770 | - * @internal | ||
| 771 | - * @psalm-suppress RedundantPropertyInitializationCheck | ||
| 772 | - * | ||
| 773 | - * @param array{value: string, scale: int} $data | ||
| 774 | - * | ||
| 775 | - * @return void | ||
| 776 | - * | ||
| 777 | - * @throws \LogicException | ||
| 778 | - */ | ||
| 779 | - public function __unserialize(array $data): void | ||
| 780 | - { | ||
| 781 | - if (isset($this->value)) { | ||
| 782 | - throw new \LogicException('__unserialize() is an internal function, it must not be called directly.'); | ||
| 783 | - } | ||
| 784 | - | ||
| 785 | - $this->value = $data['value']; | ||
| 786 | - $this->scale = $data['scale']; | ||
| 787 | - } | ||
| 788 | - | ||
| 789 | - /** | ||
| 790 | - * This method is required by interface Serializable and SHOULD NOT be accessed directly. | ||
| 791 | - * | ||
| 792 | - * @internal | ||
| 793 | - * | ||
| 794 | - * @return string | ||
| 795 | - */ | ||
| 796 | - public function serialize() : string | ||
| 797 | - { | ||
| 798 | - return $this->value . ':' . $this->scale; | ||
| 799 | - } | ||
| 800 | - | ||
| 801 | - /** | ||
| 802 | - * This method is only here to implement interface Serializable and cannot be accessed directly. | ||
| 803 | - * | ||
| 804 | - * @internal | ||
| 805 | - * @psalm-suppress RedundantPropertyInitializationCheck | ||
| 806 | - * | ||
| 807 | - * @param string $value | ||
| 808 | - * | ||
| 809 | - * @return void | ||
| 810 | - * | ||
| 811 | - * @throws \LogicException | ||
| 812 | - */ | ||
| 813 | - public function unserialize($value) : void | ||
| 814 | - { | ||
| 815 | - if (isset($this->value)) { | ||
| 816 | - throw new \LogicException('unserialize() is an internal function, it must not be called directly.'); | ||
| 817 | - } | ||
| 818 | - | ||
| 819 | - [$value, $scale] = \explode(':', $value); | ||
| 820 | - | ||
| 821 | - $this->value = $value; | ||
| 822 | - $this->scale = (int) $scale; | ||
| 823 | - } | ||
| 824 | - | ||
| 825 | - /** | ||
| 826 | - * Puts the internal values of the given decimal numbers on the same scale. | ||
| 827 | - * | ||
| 828 | - * @param BigDecimal $x The first decimal number. | ||
| 829 | - * @param BigDecimal $y The second decimal number. | ||
| 830 | - * | ||
| 831 | - * @return array{string, string} The scaled integer values of $x and $y. | ||
| 832 | - */ | ||
| 833 | - private function scaleValues(BigDecimal $x, BigDecimal $y) : array | ||
| 834 | - { | ||
| 835 | - $a = $x->value; | ||
| 836 | - $b = $y->value; | ||
| 837 | - | ||
| 838 | - if ($b !== '0' && $x->scale > $y->scale) { | ||
| 839 | - $b .= \str_repeat('0', $x->scale - $y->scale); | ||
| 840 | - } elseif ($a !== '0' && $x->scale < $y->scale) { | ||
| 841 | - $a .= \str_repeat('0', $y->scale - $x->scale); | ||
| 842 | - } | ||
| 843 | - | ||
| 844 | - return [$a, $b]; | ||
| 845 | - } | ||
| 846 | - | ||
| 847 | - /** | ||
| 848 | - * @param int $scale | ||
| 849 | - * | ||
| 850 | - * @return string | ||
| 851 | - */ | ||
| 852 | - private function valueWithMinScale(int $scale) : string | ||
| 853 | - { | ||
| 854 | - $value = $this->value; | ||
| 855 | - | ||
| 856 | - if ($this->value !== '0' && $scale > $this->scale) { | ||
| 857 | - $value .= \str_repeat('0', $scale - $this->scale); | ||
| 858 | - } | ||
| 859 | - | ||
| 860 | - return $value; | ||
| 861 | - } | ||
| 862 | - | ||
| 863 | - /** | ||
| 864 | - * Adds leading zeros if necessary to the unscaled value to represent the full decimal number. | ||
| 865 | - * | ||
| 866 | - * @return string | ||
| 867 | - */ | ||
| 868 | - private function getUnscaledValueWithLeadingZeros() : string | ||
| 869 | - { | ||
| 870 | - $value = $this->value; | ||
| 871 | - $targetLength = $this->scale + 1; | ||
| 872 | - $negative = ($value[0] === '-'); | ||
| 873 | - $length = \strlen($value); | ||
| 874 | - | ||
| 875 | - if ($negative) { | ||
| 876 | - $length--; | ||
| 877 | - } | ||
| 878 | - | ||
| 879 | - if ($length >= $targetLength) { | ||
| 880 | - return $this->value; | ||
| 881 | - } | ||
| 882 | - | ||
| 883 | - if ($negative) { | ||
| 884 | - $value = \substr($value, 1); | ||
| 885 | - } | ||
| 886 | - | ||
| 887 | - $value = \str_pad($value, $targetLength, '0', STR_PAD_LEFT); | ||
| 888 | - | ||
| 889 | - if ($negative) { | ||
| 890 | - $value = '-' . $value; | ||
| 891 | - } | ||
| 892 | - | ||
| 893 | - return $value; | ||
| 894 | - } | ||
| 895 | -} |
vendor/brick/math/src/BigInteger.php
已删除
100755 → 0
| 1 | -<?php | ||
| 2 | - | ||
| 3 | -declare(strict_types=1); | ||
| 4 | - | ||
| 5 | -namespace Brick\Math; | ||
| 6 | - | ||
| 7 | -use Brick\Math\Exception\DivisionByZeroException; | ||
| 8 | -use Brick\Math\Exception\IntegerOverflowException; | ||
| 9 | -use Brick\Math\Exception\MathException; | ||
| 10 | -use Brick\Math\Exception\NegativeNumberException; | ||
| 11 | -use Brick\Math\Exception\NumberFormatException; | ||
| 12 | -use Brick\Math\Internal\Calculator; | ||
| 13 | - | ||
| 14 | -/** | ||
| 15 | - * An arbitrary-size integer. | ||
| 16 | - * | ||
| 17 | - * All methods accepting a number as a parameter accept either a BigInteger instance, | ||
| 18 | - * an integer, or a string representing an arbitrary size integer. | ||
| 19 | - * | ||
| 20 | - * @psalm-immutable | ||
| 21 | - */ | ||
| 22 | -final class BigInteger extends BigNumber | ||
| 23 | -{ | ||
| 24 | - /** | ||
| 25 | - * The value, as a string of digits with optional leading minus sign. | ||
| 26 | - * | ||
| 27 | - * No leading zeros must be present. | ||
| 28 | - * No leading minus sign must be present if the number is zero. | ||
| 29 | - * | ||
| 30 | - * @var string | ||
| 31 | - */ | ||
| 32 | - private $value; | ||
| 33 | - | ||
| 34 | - /** | ||
| 35 | - * Protected constructor. Use a factory method to obtain an instance. | ||
| 36 | - * | ||
| 37 | - * @param string $value A string of digits, with optional leading minus sign. | ||
| 38 | - */ | ||
| 39 | - protected function __construct(string $value) | ||
| 40 | - { | ||
| 41 | - $this->value = $value; | ||
| 42 | - } | ||
| 43 | - | ||
| 44 | - /** | ||
| 45 | - * Creates a BigInteger of the given value. | ||
| 46 | - * | ||
| 47 | - * @param BigNumber|int|float|string $value | ||
| 48 | - * | ||
| 49 | - * @return BigInteger | ||
| 50 | - * | ||
| 51 | - * @throws MathException If the value cannot be converted to a BigInteger. | ||
| 52 | - * | ||
| 53 | - * @psalm-pure | ||
| 54 | - */ | ||
| 55 | - public static function of($value) : BigNumber | ||
| 56 | - { | ||
| 57 | - return parent::of($value)->toBigInteger(); | ||
| 58 | - } | ||
| 59 | - | ||
| 60 | - /** | ||
| 61 | - * Creates a number from a string in a given base. | ||
| 62 | - * | ||
| 63 | - * The string can optionally be prefixed with the `+` or `-` sign. | ||
| 64 | - * | ||
| 65 | - * Bases greater than 36 are not supported by this method, as there is no clear consensus on which of the lowercase | ||
| 66 | - * or uppercase characters should come first. Instead, this method accepts any base up to 36, and does not | ||
| 67 | - * differentiate lowercase and uppercase characters, which are considered equal. | ||
| 68 | - * | ||
| 69 | - * For bases greater than 36, and/or custom alphabets, use the fromArbitraryBase() method. | ||
| 70 | - * | ||
| 71 | - * @param string $number The number to convert, in the given base. | ||
| 72 | - * @param int $base The base of the number, between 2 and 36. | ||
| 73 | - * | ||
| 74 | - * @return BigInteger | ||
| 75 | - * | ||
| 76 | - * @throws NumberFormatException If the number is empty, or contains invalid chars for the given base. | ||
| 77 | - * @throws \InvalidArgumentException If the base is out of range. | ||
| 78 | - * | ||
| 79 | - * @psalm-pure | ||
| 80 | - */ | ||
| 81 | - public static function fromBase(string $number, int $base) : BigInteger | ||
| 82 | - { | ||
| 83 | - if ($number === '') { | ||
| 84 | - throw new NumberFormatException('The number cannot be empty.'); | ||
| 85 | - } | ||
| 86 | - | ||
| 87 | - if ($base < 2 || $base > 36) { | ||
| 88 | - throw new \InvalidArgumentException(\sprintf('Base %d is not in range 2 to 36.', $base)); | ||
| 89 | - } | ||
| 90 | - | ||
| 91 | - if ($number[0] === '-') { | ||
| 92 | - $sign = '-'; | ||
| 93 | - $number = \substr($number, 1); | ||
| 94 | - } elseif ($number[0] === '+') { | ||
| 95 | - $sign = ''; | ||
| 96 | - $number = \substr($number, 1); | ||
| 97 | - } else { | ||
| 98 | - $sign = ''; | ||
| 99 | - } | ||
| 100 | - | ||
| 101 | - if ($number === '') { | ||
| 102 | - throw new NumberFormatException('The number cannot be empty.'); | ||
| 103 | - } | ||
| 104 | - | ||
| 105 | - $number = \ltrim($number, '0'); | ||
| 106 | - | ||
| 107 | - if ($number === '') { | ||
| 108 | - // The result will be the same in any base, avoid further calculation. | ||
| 109 | - return BigInteger::zero(); | ||
| 110 | - } | ||
| 111 | - | ||
| 112 | - if ($number === '1') { | ||
| 113 | - // The result will be the same in any base, avoid further calculation. | ||
| 114 | - return new BigInteger($sign . '1'); | ||
| 115 | - } | ||
| 116 | - | ||
| 117 | - $pattern = '/[^' . \substr(Calculator::ALPHABET, 0, $base) . ']/'; | ||
| 118 | - | ||
| 119 | - if (\preg_match($pattern, \strtolower($number), $matches) === 1) { | ||
| 120 | - throw new NumberFormatException(\sprintf('"%s" is not a valid character in base %d.', $matches[0], $base)); | ||
| 121 | - } | ||
| 122 | - | ||
| 123 | - if ($base === 10) { | ||
| 124 | - // The number is usable as is, avoid further calculation. | ||
| 125 | - return new BigInteger($sign . $number); | ||
| 126 | - } | ||
| 127 | - | ||
| 128 | - $result = Calculator::get()->fromBase($number, $base); | ||
| 129 | - | ||
| 130 | - return new BigInteger($sign . $result); | ||
| 131 | - } | ||
| 132 | - | ||
| 133 | - /** | ||
| 134 | - * Parses a string containing an integer in an arbitrary base, using a custom alphabet. | ||
| 135 | - * | ||
| 136 | - * Because this method accepts an alphabet with any character, including dash, it does not handle negative numbers. | ||
| 137 | - * | ||
| 138 | - * @param string $number The number to parse. | ||
| 139 | - * @param string $alphabet The alphabet, for example '01' for base 2, or '01234567' for base 8. | ||
| 140 | - * | ||
| 141 | - * @return BigInteger | ||
| 142 | - * | ||
| 143 | - * @throws NumberFormatException If the given number is empty or contains invalid chars for the given alphabet. | ||
| 144 | - * @throws \InvalidArgumentException If the alphabet does not contain at least 2 chars. | ||
| 145 | - * | ||
| 146 | - * @psalm-pure | ||
| 147 | - */ | ||
| 148 | - public static function fromArbitraryBase(string $number, string $alphabet) : BigInteger | ||
| 149 | - { | ||
| 150 | - if ($number === '') { | ||
| 151 | - throw new NumberFormatException('The number cannot be empty.'); | ||
| 152 | - } | ||
| 153 | - | ||
| 154 | - $base = \strlen($alphabet); | ||
| 155 | - | ||
| 156 | - if ($base < 2) { | ||
| 157 | - throw new \InvalidArgumentException('The alphabet must contain at least 2 chars.'); | ||
| 158 | - } | ||
| 159 | - | ||
| 160 | - $pattern = '/[^' . \preg_quote($alphabet, '/') . ']/'; | ||
| 161 | - | ||
| 162 | - if (\preg_match($pattern, $number, $matches) === 1) { | ||
| 163 | - throw NumberFormatException::charNotInAlphabet($matches[0]); | ||
| 164 | - } | ||
| 165 | - | ||
| 166 | - $number = Calculator::get()->fromArbitraryBase($number, $alphabet, $base); | ||
| 167 | - | ||
| 168 | - return new BigInteger($number); | ||
| 169 | - } | ||
| 170 | - | ||
| 171 | - /** | ||
| 172 | - * Translates a string of bytes containing the binary representation of a BigInteger into a BigInteger. | ||
| 173 | - * | ||
| 174 | - * The input string is assumed to be in big-endian byte-order: the most significant byte is in the zeroth element. | ||
| 175 | - * | ||
| 176 | - * If `$signed` is true, the input is assumed to be in two's-complement representation, and the leading bit is | ||
| 177 | - * interpreted as a sign bit. If `$signed` is false, the input is interpreted as an unsigned number, and the | ||
| 178 | - * resulting BigInteger will always be positive or zero. | ||
| 179 | - * | ||
| 180 | - * This method can be used to retrieve a number exported by `toBytes()`, as long as the `$signed` flags match. | ||
| 181 | - * | ||
| 182 | - * @param string $value The byte string. | ||
| 183 | - * @param bool $signed Whether to interpret as a signed number in two's-complement representation with a leading | ||
| 184 | - * sign bit. | ||
| 185 | - * | ||
| 186 | - * @return BigInteger | ||
| 187 | - * | ||
| 188 | - * @throws NumberFormatException If the string is empty. | ||
| 189 | - */ | ||
| 190 | - public static function fromBytes(string $value, bool $signed = true) : BigInteger | ||
| 191 | - { | ||
| 192 | - if ($value === '') { | ||
| 193 | - throw new NumberFormatException('The byte string must not be empty.'); | ||
| 194 | - } | ||
| 195 | - | ||
| 196 | - $twosComplement = false; | ||
| 197 | - | ||
| 198 | - if ($signed) { | ||
| 199 | - $x = \ord($value[0]); | ||
| 200 | - | ||
| 201 | - if (($twosComplement = ($x >= 0x80))) { | ||
| 202 | - $value = ~$value; | ||
| 203 | - } | ||
| 204 | - } | ||
| 205 | - | ||
| 206 | - $number = self::fromBase(\bin2hex($value), 16); | ||
| 207 | - | ||
| 208 | - if ($twosComplement) { | ||
| 209 | - return $number->plus(1)->negated(); | ||
| 210 | - } | ||
| 211 | - | ||
| 212 | - return $number; | ||
| 213 | - } | ||
| 214 | - | ||
| 215 | - /** | ||
| 216 | - * Generates a pseudo-random number in the range 0 to 2^numBits - 1. | ||
| 217 | - * | ||
| 218 | - * Using the default random bytes generator, this method is suitable for cryptographic use. | ||
| 219 | - * | ||
| 220 | - * @psalm-param callable(int): string $randomBytesGenerator | ||
| 221 | - * | ||
| 222 | - * @param int $numBits The number of bits. | ||
| 223 | - * @param callable|null $randomBytesGenerator A function that accepts a number of bytes as an integer, and returns a | ||
| 224 | - * string of random bytes of the given length. Defaults to the | ||
| 225 | - * `random_bytes()` function. | ||
| 226 | - * | ||
| 227 | - * @return BigInteger | ||
| 228 | - * | ||
| 229 | - * @throws \InvalidArgumentException If $numBits is negative. | ||
| 230 | - */ | ||
| 231 | - public static function randomBits(int $numBits, ?callable $randomBytesGenerator = null) : BigInteger | ||
| 232 | - { | ||
| 233 | - if ($numBits < 0) { | ||
| 234 | - throw new \InvalidArgumentException('The number of bits cannot be negative.'); | ||
| 235 | - } | ||
| 236 | - | ||
| 237 | - if ($numBits === 0) { | ||
| 238 | - return BigInteger::zero(); | ||
| 239 | - } | ||
| 240 | - | ||
| 241 | - if ($randomBytesGenerator === null) { | ||
| 242 | - $randomBytesGenerator = 'random_bytes'; | ||
| 243 | - } | ||
| 244 | - | ||
| 245 | - $byteLength = \intdiv($numBits - 1, 8) + 1; | ||
| 246 | - | ||
| 247 | - $extraBits = ($byteLength * 8 - $numBits); | ||
| 248 | - $bitmask = \chr(0xFF >> $extraBits); | ||
| 249 | - | ||
| 250 | - $randomBytes = $randomBytesGenerator($byteLength); | ||
| 251 | - $randomBytes[0] = $randomBytes[0] & $bitmask; | ||
| 252 | - | ||
| 253 | - return self::fromBytes($randomBytes, false); | ||
| 254 | - } | ||
| 255 | - | ||
| 256 | - /** | ||
| 257 | - * Generates a pseudo-random number between `$min` and `$max`. | ||
| 258 | - * | ||
| 259 | - * Using the default random bytes generator, this method is suitable for cryptographic use. | ||
| 260 | - * | ||
| 261 | - * @psalm-param (callable(int): string)|null $randomBytesGenerator | ||
| 262 | - * | ||
| 263 | - * @param BigNumber|int|float|string $min The lower bound. Must be convertible to a BigInteger. | ||
| 264 | - * @param BigNumber|int|float|string $max The upper bound. Must be convertible to a BigInteger. | ||
| 265 | - * @param callable|null $randomBytesGenerator A function that accepts a number of bytes as an integer, | ||
| 266 | - * and returns a string of random bytes of the given length. | ||
| 267 | - * Defaults to the `random_bytes()` function. | ||
| 268 | - * | ||
| 269 | - * @return BigInteger | ||
| 270 | - * | ||
| 271 | - * @throws MathException If one of the parameters cannot be converted to a BigInteger, | ||
| 272 | - * or `$min` is greater than `$max`. | ||
| 273 | - */ | ||
| 274 | - public static function randomRange($min, $max, ?callable $randomBytesGenerator = null) : BigInteger | ||
| 275 | - { | ||
| 276 | - $min = BigInteger::of($min); | ||
| 277 | - $max = BigInteger::of($max); | ||
| 278 | - | ||
| 279 | - if ($min->isGreaterThan($max)) { | ||
| 280 | - throw new MathException('$min cannot be greater than $max.'); | ||
| 281 | - } | ||
| 282 | - | ||
| 283 | - if ($min->isEqualTo($max)) { | ||
| 284 | - return $min; | ||
| 285 | - } | ||
| 286 | - | ||
| 287 | - $diff = $max->minus($min); | ||
| 288 | - $bitLength = $diff->getBitLength(); | ||
| 289 | - | ||
| 290 | - // try until the number is in range (50% to 100% chance of success) | ||
| 291 | - do { | ||
| 292 | - $randomNumber = self::randomBits($bitLength, $randomBytesGenerator); | ||
| 293 | - } while ($randomNumber->isGreaterThan($diff)); | ||
| 294 | - | ||
| 295 | - return $randomNumber->plus($min); | ||
| 296 | - } | ||
| 297 | - | ||
| 298 | - /** | ||
| 299 | - * Returns a BigInteger representing zero. | ||
| 300 | - * | ||
| 301 | - * @return BigInteger | ||
| 302 | - * | ||
| 303 | - * @psalm-pure | ||
| 304 | - */ | ||
| 305 | - public static function zero() : BigInteger | ||
| 306 | - { | ||
| 307 | - /** | ||
| 308 | - * @psalm-suppress ImpureStaticVariable | ||
| 309 | - * @var BigInteger|null $zero | ||
| 310 | - */ | ||
| 311 | - static $zero; | ||
| 312 | - | ||
| 313 | - if ($zero === null) { | ||
| 314 | - $zero = new BigInteger('0'); | ||
| 315 | - } | ||
| 316 | - | ||
| 317 | - return $zero; | ||
| 318 | - } | ||
| 319 | - | ||
| 320 | - /** | ||
| 321 | - * Returns a BigInteger representing one. | ||
| 322 | - * | ||
| 323 | - * @return BigInteger | ||
| 324 | - * | ||
| 325 | - * @psalm-pure | ||
| 326 | - */ | ||
| 327 | - public static function one() : BigInteger | ||
| 328 | - { | ||
| 329 | - /** | ||
| 330 | - * @psalm-suppress ImpureStaticVariable | ||
| 331 | - * @var BigInteger|null $one | ||
| 332 | - */ | ||
| 333 | - static $one; | ||
| 334 | - | ||
| 335 | - if ($one === null) { | ||
| 336 | - $one = new BigInteger('1'); | ||
| 337 | - } | ||
| 338 | - | ||
| 339 | - return $one; | ||
| 340 | - } | ||
| 341 | - | ||
| 342 | - /** | ||
| 343 | - * Returns a BigInteger representing ten. | ||
| 344 | - * | ||
| 345 | - * @return BigInteger | ||
| 346 | - * | ||
| 347 | - * @psalm-pure | ||
| 348 | - */ | ||
| 349 | - public static function ten() : BigInteger | ||
| 350 | - { | ||
| 351 | - /** | ||
| 352 | - * @psalm-suppress ImpureStaticVariable | ||
| 353 | - * @var BigInteger|null $ten | ||
| 354 | - */ | ||
| 355 | - static $ten; | ||
| 356 | - | ||
| 357 | - if ($ten === null) { | ||
| 358 | - $ten = new BigInteger('10'); | ||
| 359 | - } | ||
| 360 | - | ||
| 361 | - return $ten; | ||
| 362 | - } | ||
| 363 | - | ||
| 364 | - /** | ||
| 365 | - * Returns the sum of this number and the given one. | ||
| 366 | - * | ||
| 367 | - * @param BigNumber|int|float|string $that The number to add. Must be convertible to a BigInteger. | ||
| 368 | - * | ||
| 369 | - * @return BigInteger The result. | ||
| 370 | - * | ||
| 371 | - * @throws MathException If the number is not valid, or is not convertible to a BigInteger. | ||
| 372 | - */ | ||
| 373 | - public function plus($that) : BigInteger | ||
| 374 | - { | ||
| 375 | - $that = BigInteger::of($that); | ||
| 376 | - | ||
| 377 | - if ($that->value === '0') { | ||
| 378 | - return $this; | ||
| 379 | - } | ||
| 380 | - | ||
| 381 | - if ($this->value === '0') { | ||
| 382 | - return $that; | ||
| 383 | - } | ||
| 384 | - | ||
| 385 | - $value = Calculator::get()->add($this->value, $that->value); | ||
| 386 | - | ||
| 387 | - return new BigInteger($value); | ||
| 388 | - } | ||
| 389 | - | ||
| 390 | - /** | ||
| 391 | - * Returns the difference of this number and the given one. | ||
| 392 | - * | ||
| 393 | - * @param BigNumber|int|float|string $that The number to subtract. Must be convertible to a BigInteger. | ||
| 394 | - * | ||
| 395 | - * @return BigInteger The result. | ||
| 396 | - * | ||
| 397 | - * @throws MathException If the number is not valid, or is not convertible to a BigInteger. | ||
| 398 | - */ | ||
| 399 | - public function minus($that) : BigInteger | ||
| 400 | - { | ||
| 401 | - $that = BigInteger::of($that); | ||
| 402 | - | ||
| 403 | - if ($that->value === '0') { | ||
| 404 | - return $this; | ||
| 405 | - } | ||
| 406 | - | ||
| 407 | - $value = Calculator::get()->sub($this->value, $that->value); | ||
| 408 | - | ||
| 409 | - return new BigInteger($value); | ||
| 410 | - } | ||
| 411 | - | ||
| 412 | - /** | ||
| 413 | - * Returns the product of this number and the given one. | ||
| 414 | - * | ||
| 415 | - * @param BigNumber|int|float|string $that The multiplier. Must be convertible to a BigInteger. | ||
| 416 | - * | ||
| 417 | - * @return BigInteger The result. | ||
| 418 | - * | ||
| 419 | - * @throws MathException If the multiplier is not a valid number, or is not convertible to a BigInteger. | ||
| 420 | - */ | ||
| 421 | - public function multipliedBy($that) : BigInteger | ||
| 422 | - { | ||
| 423 | - $that = BigInteger::of($that); | ||
| 424 | - | ||
| 425 | - if ($that->value === '1') { | ||
| 426 | - return $this; | ||
| 427 | - } | ||
| 428 | - | ||
| 429 | - if ($this->value === '1') { | ||
| 430 | - return $that; | ||
| 431 | - } | ||
| 432 | - | ||
| 433 | - $value = Calculator::get()->mul($this->value, $that->value); | ||
| 434 | - | ||
| 435 | - return new BigInteger($value); | ||
| 436 | - } | ||
| 437 | - | ||
| 438 | - /** | ||
| 439 | - * Returns the result of the division of this number by the given one. | ||
| 440 | - * | ||
| 441 | - * @param BigNumber|int|float|string $that The divisor. Must be convertible to a BigInteger. | ||
| 442 | - * @param int $roundingMode An optional rounding mode. | ||
| 443 | - * | ||
| 444 | - * @return BigInteger The result. | ||
| 445 | - * | ||
| 446 | - * @throws MathException If the divisor is not a valid number, is not convertible to a BigInteger, is zero, | ||
| 447 | - * or RoundingMode::UNNECESSARY is used and the remainder is not zero. | ||
| 448 | - */ | ||
| 449 | - public function dividedBy($that, int $roundingMode = RoundingMode::UNNECESSARY) : BigInteger | ||
| 450 | - { | ||
| 451 | - $that = BigInteger::of($that); | ||
| 452 | - | ||
| 453 | - if ($that->value === '1') { | ||
| 454 | - return $this; | ||
| 455 | - } | ||
| 456 | - | ||
| 457 | - if ($that->value === '0') { | ||
| 458 | - throw DivisionByZeroException::divisionByZero(); | ||
| 459 | - } | ||
| 460 | - | ||
| 461 | - $result = Calculator::get()->divRound($this->value, $that->value, $roundingMode); | ||
| 462 | - | ||
| 463 | - return new BigInteger($result); | ||
| 464 | - } | ||
| 465 | - | ||
| 466 | - /** | ||
| 467 | - * Returns this number exponentiated to the given value. | ||
| 468 | - * | ||
| 469 | - * @param int $exponent The exponent. | ||
| 470 | - * | ||
| 471 | - * @return BigInteger The result. | ||
| 472 | - * | ||
| 473 | - * @throws \InvalidArgumentException If the exponent is not in the range 0 to 1,000,000. | ||
| 474 | - */ | ||
| 475 | - public function power(int $exponent) : BigInteger | ||
| 476 | - { | ||
| 477 | - if ($exponent === 0) { | ||
| 478 | - return BigInteger::one(); | ||
| 479 | - } | ||
| 480 | - | ||
| 481 | - if ($exponent === 1) { | ||
| 482 | - return $this; | ||
| 483 | - } | ||
| 484 | - | ||
| 485 | - if ($exponent < 0 || $exponent > Calculator::MAX_POWER) { | ||
| 486 | - throw new \InvalidArgumentException(\sprintf( | ||
| 487 | - 'The exponent %d is not in the range 0 to %d.', | ||
| 488 | - $exponent, | ||
| 489 | - Calculator::MAX_POWER | ||
| 490 | - )); | ||
| 491 | - } | ||
| 492 | - | ||
| 493 | - return new BigInteger(Calculator::get()->pow($this->value, $exponent)); | ||
| 494 | - } | ||
| 495 | - | ||
| 496 | - /** | ||
| 497 | - * Returns the quotient of the division of this number by the given one. | ||
| 498 | - * | ||
| 499 | - * @param BigNumber|int|float|string $that The divisor. Must be convertible to a BigInteger. | ||
| 500 | - * | ||
| 501 | - * @return BigInteger | ||
| 502 | - * | ||
| 503 | - * @throws DivisionByZeroException If the divisor is zero. | ||
| 504 | - */ | ||
| 505 | - public function quotient($that) : BigInteger | ||
| 506 | - { | ||
| 507 | - $that = BigInteger::of($that); | ||
| 508 | - | ||
| 509 | - if ($that->value === '1') { | ||
| 510 | - return $this; | ||
| 511 | - } | ||
| 512 | - | ||
| 513 | - if ($that->value === '0') { | ||
| 514 | - throw DivisionByZeroException::divisionByZero(); | ||
| 515 | - } | ||
| 516 | - | ||
| 517 | - $quotient = Calculator::get()->divQ($this->value, $that->value); | ||
| 518 | - | ||
| 519 | - return new BigInteger($quotient); | ||
| 520 | - } | ||
| 521 | - | ||
| 522 | - /** | ||
| 523 | - * Returns the remainder of the division of this number by the given one. | ||
| 524 | - * | ||
| 525 | - * The remainder, when non-zero, has the same sign as the dividend. | ||
| 526 | - * | ||
| 527 | - * @param BigNumber|int|float|string $that The divisor. Must be convertible to a BigInteger. | ||
| 528 | - * | ||
| 529 | - * @return BigInteger | ||
| 530 | - * | ||
| 531 | - * @throws DivisionByZeroException If the divisor is zero. | ||
| 532 | - */ | ||
| 533 | - public function remainder($that) : BigInteger | ||
| 534 | - { | ||
| 535 | - $that = BigInteger::of($that); | ||
| 536 | - | ||
| 537 | - if ($that->value === '1') { | ||
| 538 | - return BigInteger::zero(); | ||
| 539 | - } | ||
| 540 | - | ||
| 541 | - if ($that->value === '0') { | ||
| 542 | - throw DivisionByZeroException::divisionByZero(); | ||
| 543 | - } | ||
| 544 | - | ||
| 545 | - $remainder = Calculator::get()->divR($this->value, $that->value); | ||
| 546 | - | ||
| 547 | - return new BigInteger($remainder); | ||
| 548 | - } | ||
| 549 | - | ||
| 550 | - /** | ||
| 551 | - * Returns the quotient and remainder of the division of this number by the given one. | ||
| 552 | - * | ||
| 553 | - * @param BigNumber|int|float|string $that The divisor. Must be convertible to a BigInteger. | ||
| 554 | - * | ||
| 555 | - * @return BigInteger[] An array containing the quotient and the remainder. | ||
| 556 | - * | ||
| 557 | - * @throws DivisionByZeroException If the divisor is zero. | ||
| 558 | - */ | ||
| 559 | - public function quotientAndRemainder($that) : array | ||
| 560 | - { | ||
| 561 | - $that = BigInteger::of($that); | ||
| 562 | - | ||
| 563 | - if ($that->value === '0') { | ||
| 564 | - throw DivisionByZeroException::divisionByZero(); | ||
| 565 | - } | ||
| 566 | - | ||
| 567 | - [$quotient, $remainder] = Calculator::get()->divQR($this->value, $that->value); | ||
| 568 | - | ||
| 569 | - return [ | ||
| 570 | - new BigInteger($quotient), | ||
| 571 | - new BigInteger($remainder) | ||
| 572 | - ]; | ||
| 573 | - } | ||
| 574 | - | ||
| 575 | - /** | ||
| 576 | - * Returns the modulo of this number and the given one. | ||
| 577 | - * | ||
| 578 | - * The modulo operation yields the same result as the remainder operation when both operands are of the same sign, | ||
| 579 | - * and may differ when signs are different. | ||
| 580 | - * | ||
| 581 | - * The result of the modulo operation, when non-zero, has the same sign as the divisor. | ||
| 582 | - * | ||
| 583 | - * @param BigNumber|int|float|string $that The divisor. Must be convertible to a BigInteger. | ||
| 584 | - * | ||
| 585 | - * @return BigInteger | ||
| 586 | - * | ||
| 587 | - * @throws DivisionByZeroException If the divisor is zero. | ||
| 588 | - */ | ||
| 589 | - public function mod($that) : BigInteger | ||
| 590 | - { | ||
| 591 | - $that = BigInteger::of($that); | ||
| 592 | - | ||
| 593 | - if ($that->value === '0') { | ||
| 594 | - throw DivisionByZeroException::modulusMustNotBeZero(); | ||
| 595 | - } | ||
| 596 | - | ||
| 597 | - $value = Calculator::get()->mod($this->value, $that->value); | ||
| 598 | - | ||
| 599 | - return new BigInteger($value); | ||
| 600 | - } | ||
| 601 | - | ||
| 602 | - /** | ||
| 603 | - * Returns the modular multiplicative inverse of this BigInteger modulo $m. | ||
| 604 | - * | ||
| 605 | - * @param BigInteger $m | ||
| 606 | - * | ||
| 607 | - * @return BigInteger | ||
| 608 | - * | ||
| 609 | - * @throws DivisionByZeroException If $m is zero. | ||
| 610 | - * @throws NegativeNumberException If $m is negative. | ||
| 611 | - * @throws MathException If this BigInteger has no multiplicative inverse mod m (that is, this BigInteger | ||
| 612 | - * is not relatively prime to m). | ||
| 613 | - */ | ||
| 614 | - public function modInverse(BigInteger $m) : BigInteger | ||
| 615 | - { | ||
| 616 | - if ($m->value === '0') { | ||
| 617 | - throw DivisionByZeroException::modulusMustNotBeZero(); | ||
| 618 | - } | ||
| 619 | - | ||
| 620 | - if ($m->isNegative()) { | ||
| 621 | - throw new NegativeNumberException('Modulus must not be negative.'); | ||
| 622 | - } | ||
| 623 | - | ||
| 624 | - if ($m->value === '1') { | ||
| 625 | - return BigInteger::zero(); | ||
| 626 | - } | ||
| 627 | - | ||
| 628 | - $value = Calculator::get()->modInverse($this->value, $m->value); | ||
| 629 | - | ||
| 630 | - if ($value === null) { | ||
| 631 | - throw new MathException('Unable to compute the modInverse for the given modulus.'); | ||
| 632 | - } | ||
| 633 | - | ||
| 634 | - return new BigInteger($value); | ||
| 635 | - } | ||
| 636 | - | ||
| 637 | - /** | ||
| 638 | - * Returns this number raised into power with modulo. | ||
| 639 | - * | ||
| 640 | - * This operation only works on positive numbers. | ||
| 641 | - * | ||
| 642 | - * @param BigNumber|int|float|string $exp The exponent. Must be positive or zero. | ||
| 643 | - * @param BigNumber|int|float|string $mod The modulus. Must be strictly positive. | ||
| 644 | - * | ||
| 645 | - * @return BigInteger | ||
| 646 | - * | ||
| 647 | - * @throws NegativeNumberException If any of the operands is negative. | ||
| 648 | - * @throws DivisionByZeroException If the modulus is zero. | ||
| 649 | - */ | ||
| 650 | - public function modPow($exp, $mod) : BigInteger | ||
| 651 | - { | ||
| 652 | - $exp = BigInteger::of($exp); | ||
| 653 | - $mod = BigInteger::of($mod); | ||
| 654 | - | ||
| 655 | - if ($this->isNegative() || $exp->isNegative() || $mod->isNegative()) { | ||
| 656 | - throw new NegativeNumberException('The operands cannot be negative.'); | ||
| 657 | - } | ||
| 658 | - | ||
| 659 | - if ($mod->isZero()) { | ||
| 660 | - throw DivisionByZeroException::modulusMustNotBeZero(); | ||
| 661 | - } | ||
| 662 | - | ||
| 663 | - $result = Calculator::get()->modPow($this->value, $exp->value, $mod->value); | ||
| 664 | - | ||
| 665 | - return new BigInteger($result); | ||
| 666 | - } | ||
| 667 | - | ||
| 668 | - /** | ||
| 669 | - * Returns the greatest common divisor of this number and the given one. | ||
| 670 | - * | ||
| 671 | - * The GCD is always positive, unless both operands are zero, in which case it is zero. | ||
| 672 | - * | ||
| 673 | - * @param BigNumber|int|float|string $that The operand. Must be convertible to an integer number. | ||
| 674 | - * | ||
| 675 | - * @return BigInteger | ||
| 676 | - */ | ||
| 677 | - public function gcd($that) : BigInteger | ||
| 678 | - { | ||
| 679 | - $that = BigInteger::of($that); | ||
| 680 | - | ||
| 681 | - if ($that->value === '0' && $this->value[0] !== '-') { | ||
| 682 | - return $this; | ||
| 683 | - } | ||
| 684 | - | ||
| 685 | - if ($this->value === '0' && $that->value[0] !== '-') { | ||
| 686 | - return $that; | ||
| 687 | - } | ||
| 688 | - | ||
| 689 | - $value = Calculator::get()->gcd($this->value, $that->value); | ||
| 690 | - | ||
| 691 | - return new BigInteger($value); | ||
| 692 | - } | ||
| 693 | - | ||
| 694 | - /** | ||
| 695 | - * Returns the integer square root number of this number, rounded down. | ||
| 696 | - * | ||
| 697 | - * The result is the largest x such that x² ≤ n. | ||
| 698 | - * | ||
| 699 | - * @return BigInteger | ||
| 700 | - * | ||
| 701 | - * @throws NegativeNumberException If this number is negative. | ||
| 702 | - */ | ||
| 703 | - public function sqrt() : BigInteger | ||
| 704 | - { | ||
| 705 | - if ($this->value[0] === '-') { | ||
| 706 | - throw new NegativeNumberException('Cannot calculate the square root of a negative number.'); | ||
| 707 | - } | ||
| 708 | - | ||
| 709 | - $value = Calculator::get()->sqrt($this->value); | ||
| 710 | - | ||
| 711 | - return new BigInteger($value); | ||
| 712 | - } | ||
| 713 | - | ||
| 714 | - /** | ||
| 715 | - * Returns the absolute value of this number. | ||
| 716 | - * | ||
| 717 | - * @return BigInteger | ||
| 718 | - */ | ||
| 719 | - public function abs() : BigInteger | ||
| 720 | - { | ||
| 721 | - return $this->isNegative() ? $this->negated() : $this; | ||
| 722 | - } | ||
| 723 | - | ||
| 724 | - /** | ||
| 725 | - * Returns the inverse of this number. | ||
| 726 | - * | ||
| 727 | - * @return BigInteger | ||
| 728 | - */ | ||
| 729 | - public function negated() : BigInteger | ||
| 730 | - { | ||
| 731 | - return new BigInteger(Calculator::get()->neg($this->value)); | ||
| 732 | - } | ||
| 733 | - | ||
| 734 | - /** | ||
| 735 | - * Returns the integer bitwise-and combined with another integer. | ||
| 736 | - * | ||
| 737 | - * This method returns a negative BigInteger if and only if both operands are negative. | ||
| 738 | - * | ||
| 739 | - * @param BigNumber|int|float|string $that The operand. Must be convertible to an integer number. | ||
| 740 | - * | ||
| 741 | - * @return BigInteger | ||
| 742 | - */ | ||
| 743 | - public function and($that) : BigInteger | ||
| 744 | - { | ||
| 745 | - $that = BigInteger::of($that); | ||
| 746 | - | ||
| 747 | - return new BigInteger(Calculator::get()->and($this->value, $that->value)); | ||
| 748 | - } | ||
| 749 | - | ||
| 750 | - /** | ||
| 751 | - * Returns the integer bitwise-or combined with another integer. | ||
| 752 | - * | ||
| 753 | - * This method returns a negative BigInteger if and only if either of the operands is negative. | ||
| 754 | - * | ||
| 755 | - * @param BigNumber|int|float|string $that The operand. Must be convertible to an integer number. | ||
| 756 | - * | ||
| 757 | - * @return BigInteger | ||
| 758 | - */ | ||
| 759 | - public function or($that) : BigInteger | ||
| 760 | - { | ||
| 761 | - $that = BigInteger::of($that); | ||
| 762 | - | ||
| 763 | - return new BigInteger(Calculator::get()->or($this->value, $that->value)); | ||
| 764 | - } | ||
| 765 | - | ||
| 766 | - /** | ||
| 767 | - * Returns the integer bitwise-xor combined with another integer. | ||
| 768 | - * | ||
| 769 | - * This method returns a negative BigInteger if and only if exactly one of the operands is negative. | ||
| 770 | - * | ||
| 771 | - * @param BigNumber|int|float|string $that The operand. Must be convertible to an integer number. | ||
| 772 | - * | ||
| 773 | - * @return BigInteger | ||
| 774 | - */ | ||
| 775 | - public function xor($that) : BigInteger | ||
| 776 | - { | ||
| 777 | - $that = BigInteger::of($that); | ||
| 778 | - | ||
| 779 | - return new BigInteger(Calculator::get()->xor($this->value, $that->value)); | ||
| 780 | - } | ||
| 781 | - | ||
| 782 | - /** | ||
| 783 | - * Returns the bitwise-not of this BigInteger. | ||
| 784 | - * | ||
| 785 | - * @return BigInteger | ||
| 786 | - */ | ||
| 787 | - public function not() : BigInteger | ||
| 788 | - { | ||
| 789 | - return $this->negated()->minus(1); | ||
| 790 | - } | ||
| 791 | - | ||
| 792 | - /** | ||
| 793 | - * Returns the integer left shifted by a given number of bits. | ||
| 794 | - * | ||
| 795 | - * @param int $distance The distance to shift. | ||
| 796 | - * | ||
| 797 | - * @return BigInteger | ||
| 798 | - */ | ||
| 799 | - public function shiftedLeft(int $distance) : BigInteger | ||
| 800 | - { | ||
| 801 | - if ($distance === 0) { | ||
| 802 | - return $this; | ||
| 803 | - } | ||
| 804 | - | ||
| 805 | - if ($distance < 0) { | ||
| 806 | - return $this->shiftedRight(- $distance); | ||
| 807 | - } | ||
| 808 | - | ||
| 809 | - return $this->multipliedBy(BigInteger::of(2)->power($distance)); | ||
| 810 | - } | ||
| 811 | - | ||
| 812 | - /** | ||
| 813 | - * Returns the integer right shifted by a given number of bits. | ||
| 814 | - * | ||
| 815 | - * @param int $distance The distance to shift. | ||
| 816 | - * | ||
| 817 | - * @return BigInteger | ||
| 818 | - */ | ||
| 819 | - public function shiftedRight(int $distance) : BigInteger | ||
| 820 | - { | ||
| 821 | - if ($distance === 0) { | ||
| 822 | - return $this; | ||
| 823 | - } | ||
| 824 | - | ||
| 825 | - if ($distance < 0) { | ||
| 826 | - return $this->shiftedLeft(- $distance); | ||
| 827 | - } | ||
| 828 | - | ||
| 829 | - $operand = BigInteger::of(2)->power($distance); | ||
| 830 | - | ||
| 831 | - if ($this->isPositiveOrZero()) { | ||
| 832 | - return $this->quotient($operand); | ||
| 833 | - } | ||
| 834 | - | ||
| 835 | - return $this->dividedBy($operand, RoundingMode::UP); | ||
| 836 | - } | ||
| 837 | - | ||
| 838 | - /** | ||
| 839 | - * Returns the number of bits in the minimal two's-complement representation of this BigInteger, excluding a sign bit. | ||
| 840 | - * | ||
| 841 | - * For positive BigIntegers, this is equivalent to the number of bits in the ordinary binary representation. | ||
| 842 | - * Computes (ceil(log2(this < 0 ? -this : this+1))). | ||
| 843 | - * | ||
| 844 | - * @return int | ||
| 845 | - */ | ||
| 846 | - public function getBitLength() : int | ||
| 847 | - { | ||
| 848 | - if ($this->value === '0') { | ||
| 849 | - return 0; | ||
| 850 | - } | ||
| 851 | - | ||
| 852 | - if ($this->isNegative()) { | ||
| 853 | - return $this->abs()->minus(1)->getBitLength(); | ||
| 854 | - } | ||
| 855 | - | ||
| 856 | - return \strlen($this->toBase(2)); | ||
| 857 | - } | ||
| 858 | - | ||
| 859 | - /** | ||
| 860 | - * Returns the index of the rightmost (lowest-order) one bit in this BigInteger. | ||
| 861 | - * | ||
| 862 | - * Returns -1 if this BigInteger contains no one bits. | ||
| 863 | - * | ||
| 864 | - * @return int | ||
| 865 | - */ | ||
| 866 | - public function getLowestSetBit() : int | ||
| 867 | - { | ||
| 868 | - $n = $this; | ||
| 869 | - $bitLength = $this->getBitLength(); | ||
| 870 | - | ||
| 871 | - for ($i = 0; $i <= $bitLength; $i++) { | ||
| 872 | - if ($n->isOdd()) { | ||
| 873 | - return $i; | ||
| 874 | - } | ||
| 875 | - | ||
| 876 | - $n = $n->shiftedRight(1); | ||
| 877 | - } | ||
| 878 | - | ||
| 879 | - return -1; | ||
| 880 | - } | ||
| 881 | - | ||
| 882 | - /** | ||
| 883 | - * Returns whether this number is even. | ||
| 884 | - * | ||
| 885 | - * @return bool | ||
| 886 | - */ | ||
| 887 | - public function isEven() : bool | ||
| 888 | - { | ||
| 889 | - return \in_array($this->value[-1], ['0', '2', '4', '6', '8'], true); | ||
| 890 | - } | ||
| 891 | - | ||
| 892 | - /** | ||
| 893 | - * Returns whether this number is odd. | ||
| 894 | - * | ||
| 895 | - * @return bool | ||
| 896 | - */ | ||
| 897 | - public function isOdd() : bool | ||
| 898 | - { | ||
| 899 | - return \in_array($this->value[-1], ['1', '3', '5', '7', '9'], true); | ||
| 900 | - } | ||
| 901 | - | ||
| 902 | - /** | ||
| 903 | - * Returns true if and only if the designated bit is set. | ||
| 904 | - * | ||
| 905 | - * Computes ((this & (1<<n)) != 0). | ||
| 906 | - * | ||
| 907 | - * @param int $n The bit to test, 0-based. | ||
| 908 | - * | ||
| 909 | - * @return bool | ||
| 910 | - * | ||
| 911 | - * @throws \InvalidArgumentException If the bit to test is negative. | ||
| 912 | - */ | ||
| 913 | - public function testBit(int $n) : bool | ||
| 914 | - { | ||
| 915 | - if ($n < 0) { | ||
| 916 | - throw new \InvalidArgumentException('The bit to test cannot be negative.'); | ||
| 917 | - } | ||
| 918 | - | ||
| 919 | - return $this->shiftedRight($n)->isOdd(); | ||
| 920 | - } | ||
| 921 | - | ||
| 922 | - /** | ||
| 923 | - * {@inheritdoc} | ||
| 924 | - */ | ||
| 925 | - public function compareTo($that) : int | ||
| 926 | - { | ||
| 927 | - $that = BigNumber::of($that); | ||
| 928 | - | ||
| 929 | - if ($that instanceof BigInteger) { | ||
| 930 | - return Calculator::get()->cmp($this->value, $that->value); | ||
| 931 | - } | ||
| 932 | - | ||
| 933 | - return - $that->compareTo($this); | ||
| 934 | - } | ||
| 935 | - | ||
| 936 | - /** | ||
| 937 | - * {@inheritdoc} | ||
| 938 | - */ | ||
| 939 | - public function getSign() : int | ||
| 940 | - { | ||
| 941 | - return ($this->value === '0') ? 0 : (($this->value[0] === '-') ? -1 : 1); | ||
| 942 | - } | ||
| 943 | - | ||
| 944 | - /** | ||
| 945 | - * {@inheritdoc} | ||
| 946 | - */ | ||
| 947 | - public function toBigInteger() : BigInteger | ||
| 948 | - { | ||
| 949 | - return $this; | ||
| 950 | - } | ||
| 951 | - | ||
| 952 | - /** | ||
| 953 | - * {@inheritdoc} | ||
| 954 | - */ | ||
| 955 | - public function toBigDecimal() : BigDecimal | ||
| 956 | - { | ||
| 957 | - return BigDecimal::create($this->value); | ||
| 958 | - } | ||
| 959 | - | ||
| 960 | - /** | ||
| 961 | - * {@inheritdoc} | ||
| 962 | - */ | ||
| 963 | - public function toBigRational() : BigRational | ||
| 964 | - { | ||
| 965 | - return BigRational::create($this, BigInteger::one(), false); | ||
| 966 | - } | ||
| 967 | - | ||
| 968 | - /** | ||
| 969 | - * {@inheritdoc} | ||
| 970 | - */ | ||
| 971 | - public function toScale(int $scale, int $roundingMode = RoundingMode::UNNECESSARY) : BigDecimal | ||
| 972 | - { | ||
| 973 | - return $this->toBigDecimal()->toScale($scale, $roundingMode); | ||
| 974 | - } | ||
| 975 | - | ||
| 976 | - /** | ||
| 977 | - * {@inheritdoc} | ||
| 978 | - */ | ||
| 979 | - public function toInt() : int | ||
| 980 | - { | ||
| 981 | - $intValue = (int) $this->value; | ||
| 982 | - | ||
| 983 | - if ($this->value !== (string) $intValue) { | ||
| 984 | - throw IntegerOverflowException::toIntOverflow($this); | ||
| 985 | - } | ||
| 986 | - | ||
| 987 | - return $intValue; | ||
| 988 | - } | ||
| 989 | - | ||
| 990 | - /** | ||
| 991 | - * {@inheritdoc} | ||
| 992 | - */ | ||
| 993 | - public function toFloat() : float | ||
| 994 | - { | ||
| 995 | - return (float) $this->value; | ||
| 996 | - } | ||
| 997 | - | ||
| 998 | - /** | ||
| 999 | - * Returns a string representation of this number in the given base. | ||
| 1000 | - * | ||
| 1001 | - * The output will always be lowercase for bases greater than 10. | ||
| 1002 | - * | ||
| 1003 | - * @param int $base | ||
| 1004 | - * | ||
| 1005 | - * @return string | ||
| 1006 | - * | ||
| 1007 | - * @throws \InvalidArgumentException If the base is out of range. | ||
| 1008 | - */ | ||
| 1009 | - public function toBase(int $base) : string | ||
| 1010 | - { | ||
| 1011 | - if ($base === 10) { | ||
| 1012 | - return $this->value; | ||
| 1013 | - } | ||
| 1014 | - | ||
| 1015 | - if ($base < 2 || $base > 36) { | ||
| 1016 | - throw new \InvalidArgumentException(\sprintf('Base %d is out of range [2, 36]', $base)); | ||
| 1017 | - } | ||
| 1018 | - | ||
| 1019 | - return Calculator::get()->toBase($this->value, $base); | ||
| 1020 | - } | ||
| 1021 | - | ||
| 1022 | - /** | ||
| 1023 | - * Returns a string representation of this number in an arbitrary base with a custom alphabet. | ||
| 1024 | - * | ||
| 1025 | - * Because this method accepts an alphabet with any character, including dash, it does not handle negative numbers; | ||
| 1026 | - * a NegativeNumberException will be thrown when attempting to call this method on a negative number. | ||
| 1027 | - * | ||
| 1028 | - * @param string $alphabet The alphabet, for example '01' for base 2, or '01234567' for base 8. | ||
| 1029 | - * | ||
| 1030 | - * @return string | ||
| 1031 | - * | ||
| 1032 | - * @throws NegativeNumberException If this number is negative. | ||
| 1033 | - * @throws \InvalidArgumentException If the given alphabet does not contain at least 2 chars. | ||
| 1034 | - */ | ||
| 1035 | - public function toArbitraryBase(string $alphabet) : string | ||
| 1036 | - { | ||
| 1037 | - $base = \strlen($alphabet); | ||
| 1038 | - | ||
| 1039 | - if ($base < 2) { | ||
| 1040 | - throw new \InvalidArgumentException('The alphabet must contain at least 2 chars.'); | ||
| 1041 | - } | ||
| 1042 | - | ||
| 1043 | - if ($this->value[0] === '-') { | ||
| 1044 | - throw new NegativeNumberException(__FUNCTION__ . '() does not support negative numbers.'); | ||
| 1045 | - } | ||
| 1046 | - | ||
| 1047 | - return Calculator::get()->toArbitraryBase($this->value, $alphabet, $base); | ||
| 1048 | - } | ||
| 1049 | - | ||
| 1050 | - /** | ||
| 1051 | - * Returns a string of bytes containing the binary representation of this BigInteger. | ||
| 1052 | - * | ||
| 1053 | - * The string is in big-endian byte-order: the most significant byte is in the zeroth element. | ||
| 1054 | - * | ||
| 1055 | - * If `$signed` is true, the output will be in two's-complement representation, and a sign bit will be prepended to | ||
| 1056 | - * the output. If `$signed` is false, no sign bit will be prepended, and this method will throw an exception if the | ||
| 1057 | - * number is negative. | ||
| 1058 | - * | ||
| 1059 | - * The string will contain the minimum number of bytes required to represent this BigInteger, including a sign bit | ||
| 1060 | - * if `$signed` is true. | ||
| 1061 | - * | ||
| 1062 | - * This representation is compatible with the `fromBytes()` factory method, as long as the `$signed` flags match. | ||
| 1063 | - * | ||
| 1064 | - * @param bool $signed Whether to output a signed number in two's-complement representation with a leading sign bit. | ||
| 1065 | - * | ||
| 1066 | - * @return string | ||
| 1067 | - * | ||
| 1068 | - * @throws NegativeNumberException If $signed is false, and the number is negative. | ||
| 1069 | - */ | ||
| 1070 | - public function toBytes(bool $signed = true) : string | ||
| 1071 | - { | ||
| 1072 | - if (! $signed && $this->isNegative()) { | ||
| 1073 | - throw new NegativeNumberException('Cannot convert a negative number to a byte string when $signed is false.'); | ||
| 1074 | - } | ||
| 1075 | - | ||
| 1076 | - $hex = $this->abs()->toBase(16); | ||
| 1077 | - | ||
| 1078 | - if (\strlen($hex) % 2 !== 0) { | ||
| 1079 | - $hex = '0' . $hex; | ||
| 1080 | - } | ||
| 1081 | - | ||
| 1082 | - $baseHexLength = \strlen($hex); | ||
| 1083 | - | ||
| 1084 | - if ($signed) { | ||
| 1085 | - if ($this->isNegative()) { | ||
| 1086 | - $bin = \hex2bin($hex); | ||
| 1087 | - assert($bin !== false); | ||
| 1088 | - | ||
| 1089 | - $hex = \bin2hex(~$bin); | ||
| 1090 | - $hex = self::fromBase($hex, 16)->plus(1)->toBase(16); | ||
| 1091 | - | ||
| 1092 | - $hexLength = \strlen($hex); | ||
| 1093 | - | ||
| 1094 | - if ($hexLength < $baseHexLength) { | ||
| 1095 | - $hex = \str_repeat('0', $baseHexLength - $hexLength) . $hex; | ||
| 1096 | - } | ||
| 1097 | - | ||
| 1098 | - if ($hex[0] < '8') { | ||
| 1099 | - $hex = 'FF' . $hex; | ||
| 1100 | - } | ||
| 1101 | - } else { | ||
| 1102 | - if ($hex[0] >= '8') { | ||
| 1103 | - $hex = '00' . $hex; | ||
| 1104 | - } | ||
| 1105 | - } | ||
| 1106 | - } | ||
| 1107 | - | ||
| 1108 | - return \hex2bin($hex); | ||
| 1109 | - } | ||
| 1110 | - | ||
| 1111 | - /** | ||
| 1112 | - * {@inheritdoc} | ||
| 1113 | - */ | ||
| 1114 | - public function __toString() : string | ||
| 1115 | - { | ||
| 1116 | - return $this->value; | ||
| 1117 | - } | ||
| 1118 | - | ||
| 1119 | - /** | ||
| 1120 | - * This method is required for serializing the object and SHOULD NOT be accessed directly. | ||
| 1121 | - * | ||
| 1122 | - * @internal | ||
| 1123 | - * | ||
| 1124 | - * @return array{value: string} | ||
| 1125 | - */ | ||
| 1126 | - public function __serialize(): array | ||
| 1127 | - { | ||
| 1128 | - return ['value' => $this->value]; | ||
| 1129 | - } | ||
| 1130 | - | ||
| 1131 | - /** | ||
| 1132 | - * This method is only here to allow unserializing the object and cannot be accessed directly. | ||
| 1133 | - * | ||
| 1134 | - * @internal | ||
| 1135 | - * @psalm-suppress RedundantPropertyInitializationCheck | ||
| 1136 | - * | ||
| 1137 | - * @param array{value: string} $data | ||
| 1138 | - * | ||
| 1139 | - * @return void | ||
| 1140 | - * | ||
| 1141 | - * @throws \LogicException | ||
| 1142 | - */ | ||
| 1143 | - public function __unserialize(array $data): void | ||
| 1144 | - { | ||
| 1145 | - if (isset($this->value)) { | ||
| 1146 | - throw new \LogicException('__unserialize() is an internal function, it must not be called directly.'); | ||
| 1147 | - } | ||
| 1148 | - | ||
| 1149 | - $this->value = $data['value']; | ||
| 1150 | - } | ||
| 1151 | - | ||
| 1152 | - /** | ||
| 1153 | - * This method is required by interface Serializable and SHOULD NOT be accessed directly. | ||
| 1154 | - * | ||
| 1155 | - * @internal | ||
| 1156 | - * | ||
| 1157 | - * @return string | ||
| 1158 | - */ | ||
| 1159 | - public function serialize() : string | ||
| 1160 | - { | ||
| 1161 | - return $this->value; | ||
| 1162 | - } | ||
| 1163 | - | ||
| 1164 | - /** | ||
| 1165 | - * This method is only here to implement interface Serializable and cannot be accessed directly. | ||
| 1166 | - * | ||
| 1167 | - * @internal | ||
| 1168 | - * @psalm-suppress RedundantPropertyInitializationCheck | ||
| 1169 | - * | ||
| 1170 | - * @param string $value | ||
| 1171 | - * | ||
| 1172 | - * @return void | ||
| 1173 | - * | ||
| 1174 | - * @throws \LogicException | ||
| 1175 | - */ | ||
| 1176 | - public function unserialize($value) : void | ||
| 1177 | - { | ||
| 1178 | - if (isset($this->value)) { | ||
| 1179 | - throw new \LogicException('unserialize() is an internal function, it must not be called directly.'); | ||
| 1180 | - } | ||
| 1181 | - | ||
| 1182 | - $this->value = $value; | ||
| 1183 | - } | ||
| 1184 | -} |
vendor/brick/math/src/BigNumber.php
已删除
100755 → 0
| 1 | -<?php | ||
| 2 | - | ||
| 3 | -declare(strict_types=1); | ||
| 4 | - | ||
| 5 | -namespace Brick\Math; | ||
| 6 | - | ||
| 7 | -use Brick\Math\Exception\DivisionByZeroException; | ||
| 8 | -use Brick\Math\Exception\MathException; | ||
| 9 | -use Brick\Math\Exception\NumberFormatException; | ||
| 10 | -use Brick\Math\Exception\RoundingNecessaryException; | ||
| 11 | - | ||
| 12 | -/** | ||
| 13 | - * Common interface for arbitrary-precision rational numbers. | ||
| 14 | - * | ||
| 15 | - * @psalm-immutable | ||
| 16 | - */ | ||
| 17 | -abstract class BigNumber implements \Serializable, \JsonSerializable | ||
| 18 | -{ | ||
| 19 | - /** | ||
| 20 | - * The regular expression used to parse integer, decimal and rational numbers. | ||
| 21 | - */ | ||
| 22 | - private const PARSE_REGEXP = | ||
| 23 | - '/^' . | ||
| 24 | - '(?<sign>[\-\+])?' . | ||
| 25 | - '(?:' . | ||
| 26 | - '(?:' . | ||
| 27 | - '(?<integral>[0-9]+)?' . | ||
| 28 | - '(?<point>\.)?' . | ||
| 29 | - '(?<fractional>[0-9]+)?' . | ||
| 30 | - '(?:[eE](?<exponent>[\-\+]?[0-9]+))?' . | ||
| 31 | - ')|(?:' . | ||
| 32 | - '(?<numerator>[0-9]+)' . | ||
| 33 | - '\/?' . | ||
| 34 | - '(?<denominator>[0-9]+)' . | ||
| 35 | - ')' . | ||
| 36 | - ')' . | ||
| 37 | - '$/'; | ||
| 38 | - | ||
| 39 | - /** | ||
| 40 | - * Creates a BigNumber of the given value. | ||
| 41 | - * | ||
| 42 | - * The concrete return type is dependent on the given value, with the following rules: | ||
| 43 | - * | ||
| 44 | - * - BigNumber instances are returned as is | ||
| 45 | - * - integer numbers are returned as BigInteger | ||
| 46 | - * - floating point numbers are converted to a string then parsed as such | ||
| 47 | - * - strings containing a `/` character are returned as BigRational | ||
| 48 | - * - strings containing a `.` character or using an exponential notation are returned as BigDecimal | ||
| 49 | - * - strings containing only digits with an optional leading `+` or `-` sign are returned as BigInteger | ||
| 50 | - * | ||
| 51 | - * @param BigNumber|int|float|string $value | ||
| 52 | - * | ||
| 53 | - * @return BigNumber | ||
| 54 | - * | ||
| 55 | - * @throws NumberFormatException If the format of the number is not valid. | ||
| 56 | - * @throws DivisionByZeroException If the value represents a rational number with a denominator of zero. | ||
| 57 | - * | ||
| 58 | - * @psalm-pure | ||
| 59 | - */ | ||
| 60 | - public static function of($value) : BigNumber | ||
| 61 | - { | ||
| 62 | - if ($value instanceof BigNumber) { | ||
| 63 | - return $value; | ||
| 64 | - } | ||
| 65 | - | ||
| 66 | - if (\is_int($value)) { | ||
| 67 | - return new BigInteger((string) $value); | ||
| 68 | - } | ||
| 69 | - | ||
| 70 | - /** @psalm-suppress RedundantCastGivenDocblockType We cannot trust the untyped $value here! */ | ||
| 71 | - $value = \is_float($value) ? self::floatToString($value) : (string) $value; | ||
| 72 | - | ||
| 73 | - $throw = static function() use ($value) : void { | ||
| 74 | - throw new NumberFormatException(\sprintf( | ||
| 75 | - 'The given value "%s" does not represent a valid number.', | ||
| 76 | - $value | ||
| 77 | - )); | ||
| 78 | - }; | ||
| 79 | - | ||
| 80 | - if (\preg_match(self::PARSE_REGEXP, $value, $matches) !== 1) { | ||
| 81 | - $throw(); | ||
| 82 | - } | ||
| 83 | - | ||
| 84 | - $getMatch = static function(string $value) use ($matches) : ?string { | ||
| 85 | - return isset($matches[$value]) && $matches[$value] !== '' ? $matches[$value] : null; | ||
| 86 | - }; | ||
| 87 | - | ||
| 88 | - $sign = $getMatch('sign'); | ||
| 89 | - $numerator = $getMatch('numerator'); | ||
| 90 | - $denominator = $getMatch('denominator'); | ||
| 91 | - | ||
| 92 | - if ($numerator !== null) { | ||
| 93 | - assert($denominator !== null); | ||
| 94 | - | ||
| 95 | - if ($sign !== null) { | ||
| 96 | - $numerator = $sign . $numerator; | ||
| 97 | - } | ||
| 98 | - | ||
| 99 | - $numerator = self::cleanUp($numerator); | ||
| 100 | - $denominator = self::cleanUp($denominator); | ||
| 101 | - | ||
| 102 | - if ($denominator === '0') { | ||
| 103 | - throw DivisionByZeroException::denominatorMustNotBeZero(); | ||
| 104 | - } | ||
| 105 | - | ||
| 106 | - return new BigRational( | ||
| 107 | - new BigInteger($numerator), | ||
| 108 | - new BigInteger($denominator), | ||
| 109 | - false | ||
| 110 | - ); | ||
| 111 | - } | ||
| 112 | - | ||
| 113 | - $point = $getMatch('point'); | ||
| 114 | - $integral = $getMatch('integral'); | ||
| 115 | - $fractional = $getMatch('fractional'); | ||
| 116 | - $exponent = $getMatch('exponent'); | ||
| 117 | - | ||
| 118 | - if ($integral === null && $fractional === null) { | ||
| 119 | - $throw(); | ||
| 120 | - } | ||
| 121 | - | ||
| 122 | - if ($integral === null) { | ||
| 123 | - $integral = '0'; | ||
| 124 | - } | ||
| 125 | - | ||
| 126 | - if ($point !== null || $exponent !== null) { | ||
| 127 | - $fractional = ($fractional ?? ''); | ||
| 128 | - $exponent = ($exponent !== null) ? (int) $exponent : 0; | ||
| 129 | - | ||
| 130 | - if ($exponent === PHP_INT_MIN || $exponent === PHP_INT_MAX) { | ||
| 131 | - throw new NumberFormatException('Exponent too large.'); | ||
| 132 | - } | ||
| 133 | - | ||
| 134 | - $unscaledValue = self::cleanUp(($sign ?? ''). $integral . $fractional); | ||
| 135 | - | ||
| 136 | - $scale = \strlen($fractional) - $exponent; | ||
| 137 | - | ||
| 138 | - if ($scale < 0) { | ||
| 139 | - if ($unscaledValue !== '0') { | ||
| 140 | - $unscaledValue .= \str_repeat('0', - $scale); | ||
| 141 | - } | ||
| 142 | - $scale = 0; | ||
| 143 | - } | ||
| 144 | - | ||
| 145 | - return new BigDecimal($unscaledValue, $scale); | ||
| 146 | - } | ||
| 147 | - | ||
| 148 | - $integral = self::cleanUp(($sign ?? '') . $integral); | ||
| 149 | - | ||
| 150 | - return new BigInteger($integral); | ||
| 151 | - } | ||
| 152 | - | ||
| 153 | - /** | ||
| 154 | - * Safely converts float to string, avoiding locale-dependent issues. | ||
| 155 | - * | ||
| 156 | - * @see https://github.com/brick/math/pull/20 | ||
| 157 | - * | ||
| 158 | - * @param float $float | ||
| 159 | - * | ||
| 160 | - * @return string | ||
| 161 | - * | ||
| 162 | - * @psalm-pure | ||
| 163 | - * @psalm-suppress ImpureFunctionCall | ||
| 164 | - */ | ||
| 165 | - private static function floatToString(float $float) : string | ||
| 166 | - { | ||
| 167 | - $currentLocale = \setlocale(LC_NUMERIC, '0'); | ||
| 168 | - \setlocale(LC_NUMERIC, 'C'); | ||
| 169 | - | ||
| 170 | - $result = (string) $float; | ||
| 171 | - | ||
| 172 | - \setlocale(LC_NUMERIC, $currentLocale); | ||
| 173 | - | ||
| 174 | - return $result; | ||
| 175 | - } | ||
| 176 | - | ||
| 177 | - /** | ||
| 178 | - * Proxy method to access protected constructors from sibling classes. | ||
| 179 | - * | ||
| 180 | - * @internal | ||
| 181 | - * | ||
| 182 | - * @param mixed ...$args The arguments to the constructor. | ||
| 183 | - * | ||
| 184 | - * @return static | ||
| 185 | - * | ||
| 186 | - * @psalm-pure | ||
| 187 | - * @psalm-suppress TooManyArguments | ||
| 188 | - * @psalm-suppress UnsafeInstantiation | ||
| 189 | - */ | ||
| 190 | - protected static function create(... $args) : BigNumber | ||
| 191 | - { | ||
| 192 | - return new static(... $args); | ||
| 193 | - } | ||
| 194 | - | ||
| 195 | - /** | ||
| 196 | - * Returns the minimum of the given values. | ||
| 197 | - * | ||
| 198 | - * @param BigNumber|int|float|string ...$values The numbers to compare. All the numbers need to be convertible | ||
| 199 | - * to an instance of the class this method is called on. | ||
| 200 | - * | ||
| 201 | - * @return static The minimum value. | ||
| 202 | - * | ||
| 203 | - * @throws \InvalidArgumentException If no values are given. | ||
| 204 | - * @throws MathException If an argument is not valid. | ||
| 205 | - * | ||
| 206 | - * @psalm-suppress LessSpecificReturnStatement | ||
| 207 | - * @psalm-suppress MoreSpecificReturnType | ||
| 208 | - * @psalm-pure | ||
| 209 | - */ | ||
| 210 | - public static function min(...$values) : BigNumber | ||
| 211 | - { | ||
| 212 | - $min = null; | ||
| 213 | - | ||
| 214 | - foreach ($values as $value) { | ||
| 215 | - $value = static::of($value); | ||
| 216 | - | ||
| 217 | - if ($min === null || $value->isLessThan($min)) { | ||
| 218 | - $min = $value; | ||
| 219 | - } | ||
| 220 | - } | ||
| 221 | - | ||
| 222 | - if ($min === null) { | ||
| 223 | - throw new \InvalidArgumentException(__METHOD__ . '() expects at least one value.'); | ||
| 224 | - } | ||
| 225 | - | ||
| 226 | - return $min; | ||
| 227 | - } | ||
| 228 | - | ||
| 229 | - /** | ||
| 230 | - * Returns the maximum of the given values. | ||
| 231 | - * | ||
| 232 | - * @param BigNumber|int|float|string ...$values The numbers to compare. All the numbers need to be convertible | ||
| 233 | - * to an instance of the class this method is called on. | ||
| 234 | - * | ||
| 235 | - * @return static The maximum value. | ||
| 236 | - * | ||
| 237 | - * @throws \InvalidArgumentException If no values are given. | ||
| 238 | - * @throws MathException If an argument is not valid. | ||
| 239 | - * | ||
| 240 | - * @psalm-suppress LessSpecificReturnStatement | ||
| 241 | - * @psalm-suppress MoreSpecificReturnType | ||
| 242 | - * @psalm-pure | ||
| 243 | - */ | ||
| 244 | - public static function max(...$values) : BigNumber | ||
| 245 | - { | ||
| 246 | - $max = null; | ||
| 247 | - | ||
| 248 | - foreach ($values as $value) { | ||
| 249 | - $value = static::of($value); | ||
| 250 | - | ||
| 251 | - if ($max === null || $value->isGreaterThan($max)) { | ||
| 252 | - $max = $value; | ||
| 253 | - } | ||
| 254 | - } | ||
| 255 | - | ||
| 256 | - if ($max === null) { | ||
| 257 | - throw new \InvalidArgumentException(__METHOD__ . '() expects at least one value.'); | ||
| 258 | - } | ||
| 259 | - | ||
| 260 | - return $max; | ||
| 261 | - } | ||
| 262 | - | ||
| 263 | - /** | ||
| 264 | - * Returns the sum of the given values. | ||
| 265 | - * | ||
| 266 | - * @param BigNumber|int|float|string ...$values The numbers to add. All the numbers need to be convertible | ||
| 267 | - * to an instance of the class this method is called on. | ||
| 268 | - * | ||
| 269 | - * @return static The sum. | ||
| 270 | - * | ||
| 271 | - * @throws \InvalidArgumentException If no values are given. | ||
| 272 | - * @throws MathException If an argument is not valid. | ||
| 273 | - * | ||
| 274 | - * @psalm-suppress LessSpecificReturnStatement | ||
| 275 | - * @psalm-suppress MoreSpecificReturnType | ||
| 276 | - * @psalm-pure | ||
| 277 | - */ | ||
| 278 | - public static function sum(...$values) : BigNumber | ||
| 279 | - { | ||
| 280 | - /** @var BigNumber|null $sum */ | ||
| 281 | - $sum = null; | ||
| 282 | - | ||
| 283 | - foreach ($values as $value) { | ||
| 284 | - $value = static::of($value); | ||
| 285 | - | ||
| 286 | - $sum = $sum === null ? $value : self::add($sum, $value); | ||
| 287 | - } | ||
| 288 | - | ||
| 289 | - if ($sum === null) { | ||
| 290 | - throw new \InvalidArgumentException(__METHOD__ . '() expects at least one value.'); | ||
| 291 | - } | ||
| 292 | - | ||
| 293 | - return $sum; | ||
| 294 | - } | ||
| 295 | - | ||
| 296 | - /** | ||
| 297 | - * Adds two BigNumber instances in the correct order to avoid a RoundingNecessaryException. | ||
| 298 | - * | ||
| 299 | - * @todo This could be better resolved by creating an abstract protected method in BigNumber, and leaving to | ||
| 300 | - * concrete classes the responsibility to perform the addition themselves or delegate it to the given number, | ||
| 301 | - * depending on their ability to perform the operation. This will also require a version bump because we're | ||
| 302 | - * potentially breaking custom BigNumber implementations (if any...) | ||
| 303 | - * | ||
| 304 | - * @param BigNumber $a | ||
| 305 | - * @param BigNumber $b | ||
| 306 | - * | ||
| 307 | - * @return BigNumber | ||
| 308 | - * | ||
| 309 | - * @psalm-pure | ||
| 310 | - */ | ||
| 311 | - private static function add(BigNumber $a, BigNumber $b) : BigNumber | ||
| 312 | - { | ||
| 313 | - if ($a instanceof BigRational) { | ||
| 314 | - return $a->plus($b); | ||
| 315 | - } | ||
| 316 | - | ||
| 317 | - if ($b instanceof BigRational) { | ||
| 318 | - return $b->plus($a); | ||
| 319 | - } | ||
| 320 | - | ||
| 321 | - if ($a instanceof BigDecimal) { | ||
| 322 | - return $a->plus($b); | ||
| 323 | - } | ||
| 324 | - | ||
| 325 | - if ($b instanceof BigDecimal) { | ||
| 326 | - return $b->plus($a); | ||
| 327 | - } | ||
| 328 | - | ||
| 329 | - /** @var BigInteger $a */ | ||
| 330 | - | ||
| 331 | - return $a->plus($b); | ||
| 332 | - } | ||
| 333 | - | ||
| 334 | - /** | ||
| 335 | - * Removes optional leading zeros and + sign from the given number. | ||
| 336 | - * | ||
| 337 | - * @param string $number The number, validated as a non-empty string of digits with optional leading sign. | ||
| 338 | - * | ||
| 339 | - * @return string | ||
| 340 | - * | ||
| 341 | - * @psalm-pure | ||
| 342 | - */ | ||
| 343 | - private static function cleanUp(string $number) : string | ||
| 344 | - { | ||
| 345 | - $firstChar = $number[0]; | ||
| 346 | - | ||
| 347 | - if ($firstChar === '+' || $firstChar === '-') { | ||
| 348 | - $number = \substr($number, 1); | ||
| 349 | - } | ||
| 350 | - | ||
| 351 | - $number = \ltrim($number, '0'); | ||
| 352 | - | ||
| 353 | - if ($number === '') { | ||
| 354 | - return '0'; | ||
| 355 | - } | ||
| 356 | - | ||
| 357 | - if ($firstChar === '-') { | ||
| 358 | - return '-' . $number; | ||
| 359 | - } | ||
| 360 | - | ||
| 361 | - return $number; | ||
| 362 | - } | ||
| 363 | - | ||
| 364 | - /** | ||
| 365 | - * Checks if this number is equal to the given one. | ||
| 366 | - * | ||
| 367 | - * @param BigNumber|int|float|string $that | ||
| 368 | - * | ||
| 369 | - * @return bool | ||
| 370 | - */ | ||
| 371 | - public function isEqualTo($that) : bool | ||
| 372 | - { | ||
| 373 | - return $this->compareTo($that) === 0; | ||
| 374 | - } | ||
| 375 | - | ||
| 376 | - /** | ||
| 377 | - * Checks if this number is strictly lower than the given one. | ||
| 378 | - * | ||
| 379 | - * @param BigNumber|int|float|string $that | ||
| 380 | - * | ||
| 381 | - * @return bool | ||
| 382 | - */ | ||
| 383 | - public function isLessThan($that) : bool | ||
| 384 | - { | ||
| 385 | - return $this->compareTo($that) < 0; | ||
| 386 | - } | ||
| 387 | - | ||
| 388 | - /** | ||
| 389 | - * Checks if this number is lower than or equal to the given one. | ||
| 390 | - * | ||
| 391 | - * @param BigNumber|int|float|string $that | ||
| 392 | - * | ||
| 393 | - * @return bool | ||
| 394 | - */ | ||
| 395 | - public function isLessThanOrEqualTo($that) : bool | ||
| 396 | - { | ||
| 397 | - return $this->compareTo($that) <= 0; | ||
| 398 | - } | ||
| 399 | - | ||
| 400 | - /** | ||
| 401 | - * Checks if this number is strictly greater than the given one. | ||
| 402 | - * | ||
| 403 | - * @param BigNumber|int|float|string $that | ||
| 404 | - * | ||
| 405 | - * @return bool | ||
| 406 | - */ | ||
| 407 | - public function isGreaterThan($that) : bool | ||
| 408 | - { | ||
| 409 | - return $this->compareTo($that) > 0; | ||
| 410 | - } | ||
| 411 | - | ||
| 412 | - /** | ||
| 413 | - * Checks if this number is greater than or equal to the given one. | ||
| 414 | - * | ||
| 415 | - * @param BigNumber|int|float|string $that | ||
| 416 | - * | ||
| 417 | - * @return bool | ||
| 418 | - */ | ||
| 419 | - public function isGreaterThanOrEqualTo($that) : bool | ||
| 420 | - { | ||
| 421 | - return $this->compareTo($that) >= 0; | ||
| 422 | - } | ||
| 423 | - | ||
| 424 | - /** | ||
| 425 | - * Checks if this number equals zero. | ||
| 426 | - * | ||
| 427 | - * @return bool | ||
| 428 | - */ | ||
| 429 | - public function isZero() : bool | ||
| 430 | - { | ||
| 431 | - return $this->getSign() === 0; | ||
| 432 | - } | ||
| 433 | - | ||
| 434 | - /** | ||
| 435 | - * Checks if this number is strictly negative. | ||
| 436 | - * | ||
| 437 | - * @return bool | ||
| 438 | - */ | ||
| 439 | - public function isNegative() : bool | ||
| 440 | - { | ||
| 441 | - return $this->getSign() < 0; | ||
| 442 | - } | ||
| 443 | - | ||
| 444 | - /** | ||
| 445 | - * Checks if this number is negative or zero. | ||
| 446 | - * | ||
| 447 | - * @return bool | ||
| 448 | - */ | ||
| 449 | - public function isNegativeOrZero() : bool | ||
| 450 | - { | ||
| 451 | - return $this->getSign() <= 0; | ||
| 452 | - } | ||
| 453 | - | ||
| 454 | - /** | ||
| 455 | - * Checks if this number is strictly positive. | ||
| 456 | - * | ||
| 457 | - * @return bool | ||
| 458 | - */ | ||
| 459 | - public function isPositive() : bool | ||
| 460 | - { | ||
| 461 | - return $this->getSign() > 0; | ||
| 462 | - } | ||
| 463 | - | ||
| 464 | - /** | ||
| 465 | - * Checks if this number is positive or zero. | ||
| 466 | - * | ||
| 467 | - * @return bool | ||
| 468 | - */ | ||
| 469 | - public function isPositiveOrZero() : bool | ||
| 470 | - { | ||
| 471 | - return $this->getSign() >= 0; | ||
| 472 | - } | ||
| 473 | - | ||
| 474 | - /** | ||
| 475 | - * Returns the sign of this number. | ||
| 476 | - * | ||
| 477 | - * @return int -1 if the number is negative, 0 if zero, 1 if positive. | ||
| 478 | - */ | ||
| 479 | - abstract public function getSign() : int; | ||
| 480 | - | ||
| 481 | - /** | ||
| 482 | - * Compares this number to the given one. | ||
| 483 | - * | ||
| 484 | - * @param BigNumber|int|float|string $that | ||
| 485 | - * | ||
| 486 | - * @return int [-1,0,1] If `$this` is lower than, equal to, or greater than `$that`. | ||
| 487 | - * | ||
| 488 | - * @throws MathException If the number is not valid. | ||
| 489 | - */ | ||
| 490 | - abstract public function compareTo($that) : int; | ||
| 491 | - | ||
| 492 | - /** | ||
| 493 | - * Converts this number to a BigInteger. | ||
| 494 | - * | ||
| 495 | - * @return BigInteger The converted number. | ||
| 496 | - * | ||
| 497 | - * @throws RoundingNecessaryException If this number cannot be converted to a BigInteger without rounding. | ||
| 498 | - */ | ||
| 499 | - abstract public function toBigInteger() : BigInteger; | ||
| 500 | - | ||
| 501 | - /** | ||
| 502 | - * Converts this number to a BigDecimal. | ||
| 503 | - * | ||
| 504 | - * @return BigDecimal The converted number. | ||
| 505 | - * | ||
| 506 | - * @throws RoundingNecessaryException If this number cannot be converted to a BigDecimal without rounding. | ||
| 507 | - */ | ||
| 508 | - abstract public function toBigDecimal() : BigDecimal; | ||
| 509 | - | ||
| 510 | - /** | ||
| 511 | - * Converts this number to a BigRational. | ||
| 512 | - * | ||
| 513 | - * @return BigRational The converted number. | ||
| 514 | - */ | ||
| 515 | - abstract public function toBigRational() : BigRational; | ||
| 516 | - | ||
| 517 | - /** | ||
| 518 | - * Converts this number to a BigDecimal with the given scale, using rounding if necessary. | ||
| 519 | - * | ||
| 520 | - * @param int $scale The scale of the resulting `BigDecimal`. | ||
| 521 | - * @param int $roundingMode A `RoundingMode` constant. | ||
| 522 | - * | ||
| 523 | - * @return BigDecimal | ||
| 524 | - * | ||
| 525 | - * @throws RoundingNecessaryException If this number cannot be converted to the given scale without rounding. | ||
| 526 | - * This only applies when RoundingMode::UNNECESSARY is used. | ||
| 527 | - */ | ||
| 528 | - abstract public function toScale(int $scale, int $roundingMode = RoundingMode::UNNECESSARY) : BigDecimal; | ||
| 529 | - | ||
| 530 | - /** | ||
| 531 | - * Returns the exact value of this number as a native integer. | ||
| 532 | - * | ||
| 533 | - * If this number cannot be converted to a native integer without losing precision, an exception is thrown. | ||
| 534 | - * Note that the acceptable range for an integer depends on the platform and differs for 32-bit and 64-bit. | ||
| 535 | - * | ||
| 536 | - * @return int The converted value. | ||
| 537 | - * | ||
| 538 | - * @throws MathException If this number cannot be exactly converted to a native integer. | ||
| 539 | - */ | ||
| 540 | - abstract public function toInt() : int; | ||
| 541 | - | ||
| 542 | - /** | ||
| 543 | - * Returns an approximation of this number as a floating-point value. | ||
| 544 | - * | ||
| 545 | - * Note that this method can discard information as the precision of a floating-point value | ||
| 546 | - * is inherently limited. | ||
| 547 | - * | ||
| 548 | - * If the number is greater than the largest representable floating point number, positive infinity is returned. | ||
| 549 | - * If the number is less than the smallest representable floating point number, negative infinity is returned. | ||
| 550 | - * | ||
| 551 | - * @return float The converted value. | ||
| 552 | - */ | ||
| 553 | - abstract public function toFloat() : float; | ||
| 554 | - | ||
| 555 | - /** | ||
| 556 | - * Returns a string representation of this number. | ||
| 557 | - * | ||
| 558 | - * The output of this method can be parsed by the `of()` factory method; | ||
| 559 | - * this will yield an object equal to this one, without any information loss. | ||
| 560 | - * | ||
| 561 | - * @return string | ||
| 562 | - */ | ||
| 563 | - abstract public function __toString() : string; | ||
| 564 | - | ||
| 565 | - /** | ||
| 566 | - * {@inheritdoc} | ||
| 567 | - */ | ||
| 568 | - public function jsonSerialize() : string | ||
| 569 | - { | ||
| 570 | - return $this->__toString(); | ||
| 571 | - } | ||
| 572 | -} |
vendor/brick/math/src/BigRational.php
已删除
100755 → 0
| 1 | -<?php | ||
| 2 | - | ||
| 3 | -declare(strict_types=1); | ||
| 4 | - | ||
| 5 | -namespace Brick\Math; | ||
| 6 | - | ||
| 7 | -use Brick\Math\Exception\DivisionByZeroException; | ||
| 8 | -use Brick\Math\Exception\MathException; | ||
| 9 | -use Brick\Math\Exception\NumberFormatException; | ||
| 10 | -use Brick\Math\Exception\RoundingNecessaryException; | ||
| 11 | - | ||
| 12 | -/** | ||
| 13 | - * An arbitrarily large rational number. | ||
| 14 | - * | ||
| 15 | - * This class is immutable. | ||
| 16 | - * | ||
| 17 | - * @psalm-immutable | ||
| 18 | - */ | ||
| 19 | -final class BigRational extends BigNumber | ||
| 20 | -{ | ||
| 21 | - /** | ||
| 22 | - * The numerator. | ||
| 23 | - * | ||
| 24 | - * @var BigInteger | ||
| 25 | - */ | ||
| 26 | - private $numerator; | ||
| 27 | - | ||
| 28 | - /** | ||
| 29 | - * The denominator. Always strictly positive. | ||
| 30 | - * | ||
| 31 | - * @var BigInteger | ||
| 32 | - */ | ||
| 33 | - private $denominator; | ||
| 34 | - | ||
| 35 | - /** | ||
| 36 | - * Protected constructor. Use a factory method to obtain an instance. | ||
| 37 | - * | ||
| 38 | - * @param BigInteger $numerator The numerator. | ||
| 39 | - * @param BigInteger $denominator The denominator. | ||
| 40 | - * @param bool $checkDenominator Whether to check the denominator for negative and zero. | ||
| 41 | - * | ||
| 42 | - * @throws DivisionByZeroException If the denominator is zero. | ||
| 43 | - */ | ||
| 44 | - protected function __construct(BigInteger $numerator, BigInteger $denominator, bool $checkDenominator) | ||
| 45 | - { | ||
| 46 | - if ($checkDenominator) { | ||
| 47 | - if ($denominator->isZero()) { | ||
| 48 | - throw DivisionByZeroException::denominatorMustNotBeZero(); | ||
| 49 | - } | ||
| 50 | - | ||
| 51 | - if ($denominator->isNegative()) { | ||
| 52 | - $numerator = $numerator->negated(); | ||
| 53 | - $denominator = $denominator->negated(); | ||
| 54 | - } | ||
| 55 | - } | ||
| 56 | - | ||
| 57 | - $this->numerator = $numerator; | ||
| 58 | - $this->denominator = $denominator; | ||
| 59 | - } | ||
| 60 | - | ||
| 61 | - /** | ||
| 62 | - * Creates a BigRational of the given value. | ||
| 63 | - * | ||
| 64 | - * @param BigNumber|int|float|string $value | ||
| 65 | - * | ||
| 66 | - * @return BigRational | ||
| 67 | - * | ||
| 68 | - * @throws MathException If the value cannot be converted to a BigRational. | ||
| 69 | - * | ||
| 70 | - * @psalm-pure | ||
| 71 | - */ | ||
| 72 | - public static function of($value) : BigNumber | ||
| 73 | - { | ||
| 74 | - return parent::of($value)->toBigRational(); | ||
| 75 | - } | ||
| 76 | - | ||
| 77 | - /** | ||
| 78 | - * Creates a BigRational out of a numerator and a denominator. | ||
| 79 | - * | ||
| 80 | - * If the denominator is negative, the signs of both the numerator and the denominator | ||
| 81 | - * will be inverted to ensure that the denominator is always positive. | ||
| 82 | - * | ||
| 83 | - * @param BigNumber|int|float|string $numerator The numerator. Must be convertible to a BigInteger. | ||
| 84 | - * @param BigNumber|int|float|string $denominator The denominator. Must be convertible to a BigInteger. | ||
| 85 | - * | ||
| 86 | - * @return BigRational | ||
| 87 | - * | ||
| 88 | - * @throws NumberFormatException If an argument does not represent a valid number. | ||
| 89 | - * @throws RoundingNecessaryException If an argument represents a non-integer number. | ||
| 90 | - * @throws DivisionByZeroException If the denominator is zero. | ||
| 91 | - * | ||
| 92 | - * @psalm-pure | ||
| 93 | - */ | ||
| 94 | - public static function nd($numerator, $denominator) : BigRational | ||
| 95 | - { | ||
| 96 | - $numerator = BigInteger::of($numerator); | ||
| 97 | - $denominator = BigInteger::of($denominator); | ||
| 98 | - | ||
| 99 | - return new BigRational($numerator, $denominator, true); | ||
| 100 | - } | ||
| 101 | - | ||
| 102 | - /** | ||
| 103 | - * Returns a BigRational representing zero. | ||
| 104 | - * | ||
| 105 | - * @return BigRational | ||
| 106 | - * | ||
| 107 | - * @psalm-pure | ||
| 108 | - */ | ||
| 109 | - public static function zero() : BigRational | ||
| 110 | - { | ||
| 111 | - /** | ||
| 112 | - * @psalm-suppress ImpureStaticVariable | ||
| 113 | - * @var BigRational|null $zero | ||
| 114 | - */ | ||
| 115 | - static $zero; | ||
| 116 | - | ||
| 117 | - if ($zero === null) { | ||
| 118 | - $zero = new BigRational(BigInteger::zero(), BigInteger::one(), false); | ||
| 119 | - } | ||
| 120 | - | ||
| 121 | - return $zero; | ||
| 122 | - } | ||
| 123 | - | ||
| 124 | - /** | ||
| 125 | - * Returns a BigRational representing one. | ||
| 126 | - * | ||
| 127 | - * @return BigRational | ||
| 128 | - * | ||
| 129 | - * @psalm-pure | ||
| 130 | - */ | ||
| 131 | - public static function one() : BigRational | ||
| 132 | - { | ||
| 133 | - /** | ||
| 134 | - * @psalm-suppress ImpureStaticVariable | ||
| 135 | - * @var BigRational|null $one | ||
| 136 | - */ | ||
| 137 | - static $one; | ||
| 138 | - | ||
| 139 | - if ($one === null) { | ||
| 140 | - $one = new BigRational(BigInteger::one(), BigInteger::one(), false); | ||
| 141 | - } | ||
| 142 | - | ||
| 143 | - return $one; | ||
| 144 | - } | ||
| 145 | - | ||
| 146 | - /** | ||
| 147 | - * Returns a BigRational representing ten. | ||
| 148 | - * | ||
| 149 | - * @return BigRational | ||
| 150 | - * | ||
| 151 | - * @psalm-pure | ||
| 152 | - */ | ||
| 153 | - public static function ten() : BigRational | ||
| 154 | - { | ||
| 155 | - /** | ||
| 156 | - * @psalm-suppress ImpureStaticVariable | ||
| 157 | - * @var BigRational|null $ten | ||
| 158 | - */ | ||
| 159 | - static $ten; | ||
| 160 | - | ||
| 161 | - if ($ten === null) { | ||
| 162 | - $ten = new BigRational(BigInteger::ten(), BigInteger::one(), false); | ||
| 163 | - } | ||
| 164 | - | ||
| 165 | - return $ten; | ||
| 166 | - } | ||
| 167 | - | ||
| 168 | - /** | ||
| 169 | - * @return BigInteger | ||
| 170 | - */ | ||
| 171 | - public function getNumerator() : BigInteger | ||
| 172 | - { | ||
| 173 | - return $this->numerator; | ||
| 174 | - } | ||
| 175 | - | ||
| 176 | - /** | ||
| 177 | - * @return BigInteger | ||
| 178 | - */ | ||
| 179 | - public function getDenominator() : BigInteger | ||
| 180 | - { | ||
| 181 | - return $this->denominator; | ||
| 182 | - } | ||
| 183 | - | ||
| 184 | - /** | ||
| 185 | - * Returns the quotient of the division of the numerator by the denominator. | ||
| 186 | - * | ||
| 187 | - * @return BigInteger | ||
| 188 | - */ | ||
| 189 | - public function quotient() : BigInteger | ||
| 190 | - { | ||
| 191 | - return $this->numerator->quotient($this->denominator); | ||
| 192 | - } | ||
| 193 | - | ||
| 194 | - /** | ||
| 195 | - * Returns the remainder of the division of the numerator by the denominator. | ||
| 196 | - * | ||
| 197 | - * @return BigInteger | ||
| 198 | - */ | ||
| 199 | - public function remainder() : BigInteger | ||
| 200 | - { | ||
| 201 | - return $this->numerator->remainder($this->denominator); | ||
| 202 | - } | ||
| 203 | - | ||
| 204 | - /** | ||
| 205 | - * Returns the quotient and remainder of the division of the numerator by the denominator. | ||
| 206 | - * | ||
| 207 | - * @return BigInteger[] | ||
| 208 | - */ | ||
| 209 | - public function quotientAndRemainder() : array | ||
| 210 | - { | ||
| 211 | - return $this->numerator->quotientAndRemainder($this->denominator); | ||
| 212 | - } | ||
| 213 | - | ||
| 214 | - /** | ||
| 215 | - * Returns the sum of this number and the given one. | ||
| 216 | - * | ||
| 217 | - * @param BigNumber|int|float|string $that The number to add. | ||
| 218 | - * | ||
| 219 | - * @return BigRational The result. | ||
| 220 | - * | ||
| 221 | - * @throws MathException If the number is not valid. | ||
| 222 | - */ | ||
| 223 | - public function plus($that) : BigRational | ||
| 224 | - { | ||
| 225 | - $that = BigRational::of($that); | ||
| 226 | - | ||
| 227 | - $numerator = $this->numerator->multipliedBy($that->denominator); | ||
| 228 | - $numerator = $numerator->plus($that->numerator->multipliedBy($this->denominator)); | ||
| 229 | - $denominator = $this->denominator->multipliedBy($that->denominator); | ||
| 230 | - | ||
| 231 | - return new BigRational($numerator, $denominator, false); | ||
| 232 | - } | ||
| 233 | - | ||
| 234 | - /** | ||
| 235 | - * Returns the difference of this number and the given one. | ||
| 236 | - * | ||
| 237 | - * @param BigNumber|int|float|string $that The number to subtract. | ||
| 238 | - * | ||
| 239 | - * @return BigRational The result. | ||
| 240 | - * | ||
| 241 | - * @throws MathException If the number is not valid. | ||
| 242 | - */ | ||
| 243 | - public function minus($that) : BigRational | ||
| 244 | - { | ||
| 245 | - $that = BigRational::of($that); | ||
| 246 | - | ||
| 247 | - $numerator = $this->numerator->multipliedBy($that->denominator); | ||
| 248 | - $numerator = $numerator->minus($that->numerator->multipliedBy($this->denominator)); | ||
| 249 | - $denominator = $this->denominator->multipliedBy($that->denominator); | ||
| 250 | - | ||
| 251 | - return new BigRational($numerator, $denominator, false); | ||
| 252 | - } | ||
| 253 | - | ||
| 254 | - /** | ||
| 255 | - * Returns the product of this number and the given one. | ||
| 256 | - * | ||
| 257 | - * @param BigNumber|int|float|string $that The multiplier. | ||
| 258 | - * | ||
| 259 | - * @return BigRational The result. | ||
| 260 | - * | ||
| 261 | - * @throws MathException If the multiplier is not a valid number. | ||
| 262 | - */ | ||
| 263 | - public function multipliedBy($that) : BigRational | ||
| 264 | - { | ||
| 265 | - $that = BigRational::of($that); | ||
| 266 | - | ||
| 267 | - $numerator = $this->numerator->multipliedBy($that->numerator); | ||
| 268 | - $denominator = $this->denominator->multipliedBy($that->denominator); | ||
| 269 | - | ||
| 270 | - return new BigRational($numerator, $denominator, false); | ||
| 271 | - } | ||
| 272 | - | ||
| 273 | - /** | ||
| 274 | - * Returns the result of the division of this number by the given one. | ||
| 275 | - * | ||
| 276 | - * @param BigNumber|int|float|string $that The divisor. | ||
| 277 | - * | ||
| 278 | - * @return BigRational The result. | ||
| 279 | - * | ||
| 280 | - * @throws MathException If the divisor is not a valid number, or is zero. | ||
| 281 | - */ | ||
| 282 | - public function dividedBy($that) : BigRational | ||
| 283 | - { | ||
| 284 | - $that = BigRational::of($that); | ||
| 285 | - | ||
| 286 | - $numerator = $this->numerator->multipliedBy($that->denominator); | ||
| 287 | - $denominator = $this->denominator->multipliedBy($that->numerator); | ||
| 288 | - | ||
| 289 | - return new BigRational($numerator, $denominator, true); | ||
| 290 | - } | ||
| 291 | - | ||
| 292 | - /** | ||
| 293 | - * Returns this number exponentiated to the given value. | ||
| 294 | - * | ||
| 295 | - * @param int $exponent The exponent. | ||
| 296 | - * | ||
| 297 | - * @return BigRational The result. | ||
| 298 | - * | ||
| 299 | - * @throws \InvalidArgumentException If the exponent is not in the range 0 to 1,000,000. | ||
| 300 | - */ | ||
| 301 | - public function power(int $exponent) : BigRational | ||
| 302 | - { | ||
| 303 | - if ($exponent === 0) { | ||
| 304 | - $one = BigInteger::one(); | ||
| 305 | - | ||
| 306 | - return new BigRational($one, $one, false); | ||
| 307 | - } | ||
| 308 | - | ||
| 309 | - if ($exponent === 1) { | ||
| 310 | - return $this; | ||
| 311 | - } | ||
| 312 | - | ||
| 313 | - return new BigRational( | ||
| 314 | - $this->numerator->power($exponent), | ||
| 315 | - $this->denominator->power($exponent), | ||
| 316 | - false | ||
| 317 | - ); | ||
| 318 | - } | ||
| 319 | - | ||
| 320 | - /** | ||
| 321 | - * Returns the reciprocal of this BigRational. | ||
| 322 | - * | ||
| 323 | - * The reciprocal has the numerator and denominator swapped. | ||
| 324 | - * | ||
| 325 | - * @return BigRational | ||
| 326 | - * | ||
| 327 | - * @throws DivisionByZeroException If the numerator is zero. | ||
| 328 | - */ | ||
| 329 | - public function reciprocal() : BigRational | ||
| 330 | - { | ||
| 331 | - return new BigRational($this->denominator, $this->numerator, true); | ||
| 332 | - } | ||
| 333 | - | ||
| 334 | - /** | ||
| 335 | - * Returns the absolute value of this BigRational. | ||
| 336 | - * | ||
| 337 | - * @return BigRational | ||
| 338 | - */ | ||
| 339 | - public function abs() : BigRational | ||
| 340 | - { | ||
| 341 | - return new BigRational($this->numerator->abs(), $this->denominator, false); | ||
| 342 | - } | ||
| 343 | - | ||
| 344 | - /** | ||
| 345 | - * Returns the negated value of this BigRational. | ||
| 346 | - * | ||
| 347 | - * @return BigRational | ||
| 348 | - */ | ||
| 349 | - public function negated() : BigRational | ||
| 350 | - { | ||
| 351 | - return new BigRational($this->numerator->negated(), $this->denominator, false); | ||
| 352 | - } | ||
| 353 | - | ||
| 354 | - /** | ||
| 355 | - * Returns the simplified value of this BigRational. | ||
| 356 | - * | ||
| 357 | - * @return BigRational | ||
| 358 | - */ | ||
| 359 | - public function simplified() : BigRational | ||
| 360 | - { | ||
| 361 | - $gcd = $this->numerator->gcd($this->denominator); | ||
| 362 | - | ||
| 363 | - $numerator = $this->numerator->quotient($gcd); | ||
| 364 | - $denominator = $this->denominator->quotient($gcd); | ||
| 365 | - | ||
| 366 | - return new BigRational($numerator, $denominator, false); | ||
| 367 | - } | ||
| 368 | - | ||
| 369 | - /** | ||
| 370 | - * {@inheritdoc} | ||
| 371 | - */ | ||
| 372 | - public function compareTo($that) : int | ||
| 373 | - { | ||
| 374 | - return $this->minus($that)->getSign(); | ||
| 375 | - } | ||
| 376 | - | ||
| 377 | - /** | ||
| 378 | - * {@inheritdoc} | ||
| 379 | - */ | ||
| 380 | - public function getSign() : int | ||
| 381 | - { | ||
| 382 | - return $this->numerator->getSign(); | ||
| 383 | - } | ||
| 384 | - | ||
| 385 | - /** | ||
| 386 | - * {@inheritdoc} | ||
| 387 | - */ | ||
| 388 | - public function toBigInteger() : BigInteger | ||
| 389 | - { | ||
| 390 | - $simplified = $this->simplified(); | ||
| 391 | - | ||
| 392 | - if (! $simplified->denominator->isEqualTo(1)) { | ||
| 393 | - throw new RoundingNecessaryException('This rational number cannot be represented as an integer value without rounding.'); | ||
| 394 | - } | ||
| 395 | - | ||
| 396 | - return $simplified->numerator; | ||
| 397 | - } | ||
| 398 | - | ||
| 399 | - /** | ||
| 400 | - * {@inheritdoc} | ||
| 401 | - */ | ||
| 402 | - public function toBigDecimal() : BigDecimal | ||
| 403 | - { | ||
| 404 | - return $this->numerator->toBigDecimal()->exactlyDividedBy($this->denominator); | ||
| 405 | - } | ||
| 406 | - | ||
| 407 | - /** | ||
| 408 | - * {@inheritdoc} | ||
| 409 | - */ | ||
| 410 | - public function toBigRational() : BigRational | ||
| 411 | - { | ||
| 412 | - return $this; | ||
| 413 | - } | ||
| 414 | - | ||
| 415 | - /** | ||
| 416 | - * {@inheritdoc} | ||
| 417 | - */ | ||
| 418 | - public function toScale(int $scale, int $roundingMode = RoundingMode::UNNECESSARY) : BigDecimal | ||
| 419 | - { | ||
| 420 | - return $this->numerator->toBigDecimal()->dividedBy($this->denominator, $scale, $roundingMode); | ||
| 421 | - } | ||
| 422 | - | ||
| 423 | - /** | ||
| 424 | - * {@inheritdoc} | ||
| 425 | - */ | ||
| 426 | - public function toInt() : int | ||
| 427 | - { | ||
| 428 | - return $this->toBigInteger()->toInt(); | ||
| 429 | - } | ||
| 430 | - | ||
| 431 | - /** | ||
| 432 | - * {@inheritdoc} | ||
| 433 | - */ | ||
| 434 | - public function toFloat() : float | ||
| 435 | - { | ||
| 436 | - return $this->numerator->toFloat() / $this->denominator->toFloat(); | ||
| 437 | - } | ||
| 438 | - | ||
| 439 | - /** | ||
| 440 | - * {@inheritdoc} | ||
| 441 | - */ | ||
| 442 | - public function __toString() : string | ||
| 443 | - { | ||
| 444 | - $numerator = (string) $this->numerator; | ||
| 445 | - $denominator = (string) $this->denominator; | ||
| 446 | - | ||
| 447 | - if ($denominator === '1') { | ||
| 448 | - return $numerator; | ||
| 449 | - } | ||
| 450 | - | ||
| 451 | - return $this->numerator . '/' . $this->denominator; | ||
| 452 | - } | ||
| 453 | - | ||
| 454 | - /** | ||
| 455 | - * This method is required for serializing the object and SHOULD NOT be accessed directly. | ||
| 456 | - * | ||
| 457 | - * @internal | ||
| 458 | - * | ||
| 459 | - * @return array{numerator: BigInteger, denominator: BigInteger} | ||
| 460 | - */ | ||
| 461 | - public function __serialize(): array | ||
| 462 | - { | ||
| 463 | - return ['numerator' => $this->numerator, 'denominator' => $this->denominator]; | ||
| 464 | - } | ||
| 465 | - | ||
| 466 | - /** | ||
| 467 | - * This method is only here to allow unserializing the object and cannot be accessed directly. | ||
| 468 | - * | ||
| 469 | - * @internal | ||
| 470 | - * @psalm-suppress RedundantPropertyInitializationCheck | ||
| 471 | - * | ||
| 472 | - * @param array{numerator: BigInteger, denominator: BigInteger} $data | ||
| 473 | - * | ||
| 474 | - * @return void | ||
| 475 | - * | ||
| 476 | - * @throws \LogicException | ||
| 477 | - */ | ||
| 478 | - public function __unserialize(array $data): void | ||
| 479 | - { | ||
| 480 | - if (isset($this->numerator)) { | ||
| 481 | - throw new \LogicException('__unserialize() is an internal function, it must not be called directly.'); | ||
| 482 | - } | ||
| 483 | - | ||
| 484 | - $this->numerator = $data['numerator']; | ||
| 485 | - $this->denominator = $data['denominator']; | ||
| 486 | - } | ||
| 487 | - | ||
| 488 | - /** | ||
| 489 | - * This method is required by interface Serializable and SHOULD NOT be accessed directly. | ||
| 490 | - * | ||
| 491 | - * @internal | ||
| 492 | - * | ||
| 493 | - * @return string | ||
| 494 | - */ | ||
| 495 | - public function serialize() : string | ||
| 496 | - { | ||
| 497 | - return $this->numerator . '/' . $this->denominator; | ||
| 498 | - } | ||
| 499 | - | ||
| 500 | - /** | ||
| 501 | - * This method is only here to implement interface Serializable and cannot be accessed directly. | ||
| 502 | - * | ||
| 503 | - * @internal | ||
| 504 | - * @psalm-suppress RedundantPropertyInitializationCheck | ||
| 505 | - * | ||
| 506 | - * @param string $value | ||
| 507 | - * | ||
| 508 | - * @return void | ||
| 509 | - * | ||
| 510 | - * @throws \LogicException | ||
| 511 | - */ | ||
| 512 | - public function unserialize($value) : void | ||
| 513 | - { | ||
| 514 | - if (isset($this->numerator)) { | ||
| 515 | - throw new \LogicException('unserialize() is an internal function, it must not be called directly.'); | ||
| 516 | - } | ||
| 517 | - | ||
| 518 | - [$numerator, $denominator] = \explode('/', $value); | ||
| 519 | - | ||
| 520 | - $this->numerator = BigInteger::of($numerator); | ||
| 521 | - $this->denominator = BigInteger::of($denominator); | ||
| 522 | - } | ||
| 523 | -} |
| 1 | -<?php | ||
| 2 | - | ||
| 3 | -declare(strict_types=1); | ||
| 4 | - | ||
| 5 | -namespace Brick\Math\Exception; | ||
| 6 | - | ||
| 7 | -/** | ||
| 8 | - * Exception thrown when a division by zero occurs. | ||
| 9 | - */ | ||
| 10 | -class DivisionByZeroException extends MathException | ||
| 11 | -{ | ||
| 12 | - /** | ||
| 13 | - * @return DivisionByZeroException | ||
| 14 | - * | ||
| 15 | - * @psalm-pure | ||
| 16 | - */ | ||
| 17 | - public static function divisionByZero() : DivisionByZeroException | ||
| 18 | - { | ||
| 19 | - return new self('Division by zero.'); | ||
| 20 | - } | ||
| 21 | - | ||
| 22 | - /** | ||
| 23 | - * @return DivisionByZeroException | ||
| 24 | - * | ||
| 25 | - * @psalm-pure | ||
| 26 | - */ | ||
| 27 | - public static function modulusMustNotBeZero() : DivisionByZeroException | ||
| 28 | - { | ||
| 29 | - return new self('The modulus must not be zero.'); | ||
| 30 | - } | ||
| 31 | - | ||
| 32 | - /** | ||
| 33 | - * @return DivisionByZeroException | ||
| 34 | - * | ||
| 35 | - * @psalm-pure | ||
| 36 | - */ | ||
| 37 | - public static function denominatorMustNotBeZero() : DivisionByZeroException | ||
| 38 | - { | ||
| 39 | - return new self('The denominator of a rational number cannot be zero.'); | ||
| 40 | - } | ||
| 41 | -} |
| 1 | -<?php | ||
| 2 | - | ||
| 3 | -declare(strict_types=1); | ||
| 4 | - | ||
| 5 | -namespace Brick\Math\Exception; | ||
| 6 | - | ||
| 7 | -use Brick\Math\BigInteger; | ||
| 8 | - | ||
| 9 | -/** | ||
| 10 | - * Exception thrown when an integer overflow occurs. | ||
| 11 | - */ | ||
| 12 | -class IntegerOverflowException extends MathException | ||
| 13 | -{ | ||
| 14 | - /** | ||
| 15 | - * @param BigInteger $value | ||
| 16 | - * | ||
| 17 | - * @return IntegerOverflowException | ||
| 18 | - * | ||
| 19 | - * @psalm-pure | ||
| 20 | - */ | ||
| 21 | - public static function toIntOverflow(BigInteger $value) : IntegerOverflowException | ||
| 22 | - { | ||
| 23 | - $message = '%s is out of range %d to %d and cannot be represented as an integer.'; | ||
| 24 | - | ||
| 25 | - return new self(\sprintf($message, (string) $value, PHP_INT_MIN, PHP_INT_MAX)); | ||
| 26 | - } | ||
| 27 | -} |
| 1 | -<?php | ||
| 2 | - | ||
| 3 | -declare(strict_types=1); | ||
| 4 | - | ||
| 5 | -namespace Brick\Math\Exception; | ||
| 6 | - | ||
| 7 | -/** | ||
| 8 | - * Base class for all math exceptions. | ||
| 9 | - * | ||
| 10 | - * This class is abstract to ensure that only fine-grained exceptions are thrown throughout the code. | ||
| 11 | - */ | ||
| 12 | -class MathException extends \RuntimeException | ||
| 13 | -{ | ||
| 14 | -} |
| 1 | -<?php | ||
| 2 | - | ||
| 3 | -declare(strict_types=1); | ||
| 4 | - | ||
| 5 | -namespace Brick\Math\Exception; | ||
| 6 | - | ||
| 7 | -/** | ||
| 8 | - * Exception thrown when attempting to create a number from a string with an invalid format. | ||
| 9 | - */ | ||
| 10 | -class NumberFormatException extends MathException | ||
| 11 | -{ | ||
| 12 | - /** | ||
| 13 | - * @param string $char The failing character. | ||
| 14 | - * | ||
| 15 | - * @return NumberFormatException | ||
| 16 | - * | ||
| 17 | - * @psalm-pure | ||
| 18 | - */ | ||
| 19 | - public static function charNotInAlphabet(string $char) : self | ||
| 20 | - { | ||
| 21 | - $ord = \ord($char); | ||
| 22 | - | ||
| 23 | - if ($ord < 32 || $ord > 126) { | ||
| 24 | - $char = \strtoupper(\dechex($ord)); | ||
| 25 | - | ||
| 26 | - if ($ord < 10) { | ||
| 27 | - $char = '0' . $char; | ||
| 28 | - } | ||
| 29 | - } else { | ||
| 30 | - $char = '"' . $char . '"'; | ||
| 31 | - } | ||
| 32 | - | ||
| 33 | - return new self(sprintf('Char %s is not a valid character in the given alphabet.', $char)); | ||
| 34 | - } | ||
| 35 | -} |
| 1 | -<?php | ||
| 2 | - | ||
| 3 | -declare(strict_types=1); | ||
| 4 | - | ||
| 5 | -namespace Brick\Math\Exception; | ||
| 6 | - | ||
| 7 | -/** | ||
| 8 | - * Exception thrown when a number cannot be represented at the requested scale without rounding. | ||
| 9 | - */ | ||
| 10 | -class RoundingNecessaryException extends MathException | ||
| 11 | -{ | ||
| 12 | - /** | ||
| 13 | - * @return RoundingNecessaryException | ||
| 14 | - * | ||
| 15 | - * @psalm-pure | ||
| 16 | - */ | ||
| 17 | - public static function roundingNecessary() : RoundingNecessaryException | ||
| 18 | - { | ||
| 19 | - return new self('Rounding is necessary to represent the result of the operation at this scale.'); | ||
| 20 | - } | ||
| 21 | -} |
-
请 注册 或 登录 后发表评论