PluginProbe
WCPOS – Point of Sale (POS) plugin for WooCommerce / 1.10.3
WCPOS – Point of Sale (POS) plugin for WooCommerce v1.10.3
1.10.19 1.10.18 1.10.17 1.10.16 1.10.15 1.10.13 1.10.14 1.10.12 1.10.11 1.10.10 1.10.9 1.10.8 untagged-3d9b7ccddc54df87c672 1.10.7 1.10.6 1.10.5 1.10.3 1.10.4 1.10.2 1.10.1 1.10.0 1.9.17 1.9.15 1.9.16 1.9.14 All 163 releases
woocommerce-pos / vendor / brick / math / src / BigRational.php

BigRational.php in WCPOS – Point of Sale (POS) plugin for WooCommerce 1.10.3, at vendor/brick/math/src/BigRational.php

524 lines 13.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
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 }
524