正在显示
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: ![.github/workflows/run-tests.yml](https://github.com/asm89/stack-cors/workflows/.github/workflows/run-tests.yml/badge.svg) | ||
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 | -} |
-
请 注册 或 登录 后发表评论