PluginProbe
Media Cloud Sync / 1.0.2
Media Cloud Sync v1.0.2
1.4.0 1.3.12 1.3.11 1.3.10 trunk 1.0.0 1.0.1 1.0.2 1.0.3 1.1.0 1.1.1 1.2.0 1.2.10 1.2.11 1.2.12 1.2.13 1.2.2 1.2.3 1.2.4 1.2.5 1.2.6 1.2.7 1.2.8 1.2.9 1.3.0 All 34 releases
media-cloud-sync / includes / sdk / google / brick / math / src / BigRational.php

BigRational.php in Media Cloud Sync 1.0.2, at includes/sdk/google/brick/math/src/BigRational.php

455 lines 13.4 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 namespace Dudlewebs\WPMCS\Brick\Math;
5
6 use Dudlewebs\WPMCS\Brick\Math\Exception\DivisionByZeroException;
7 use Dudlewebs\WPMCS\Brick\Math\Exception\MathException;
8 use Dudlewebs\WPMCS\Brick\Math\Exception\NumberFormatException;
9 use Dudlewebs\WPMCS\Brick\Math\Exception\RoundingNecessaryException;
10 /**
11 * An arbitrarily large rational number.
12 *
13 * This class is immutable.
14 *
15 * @psalm-immutable
16 */
17 final class BigRational extends BigNumber
18 {
19 /**
20 * The numerator.
21 *
22 * @var BigInteger
23 */
24 private $numerator;
25 /**
26 * The denominator. Always strictly positive.
27 *
28 * @var BigInteger
29 */
30 private $denominator;
31 /**
32 * Protected constructor. Use a factory method to obtain an instance.
33 *
34 * @param BigInteger $numerator The numerator.
35 * @param BigInteger $denominator The denominator.
36 * @param bool $checkDenominator Whether to check the denominator for negative and zero.
37 *
38 * @throws DivisionByZeroException If the denominator is zero.
39 */
40 protected function __construct(BigInteger $numerator, BigInteger $denominator, bool $checkDenominator)
41 {
42 if ($checkDenominator) {
43 if ($denominator->isZero()) {
44 throw DivisionByZeroException::denominatorMustNotBeZero();
45 }
46 if ($denominator->isNegative()) {
47 $numerator = $numerator->negated();
48 $denominator = $denominator->negated();
49 }
50 }
51 $this->numerator = $numerator;
52 $this->denominator = $denominator;
53 }
54 /**
55 * Creates a BigRational of the given value.
56 *
57 * @param BigNumber|int|float|string $value
58 *
59 * @return BigRational
60 *
61 * @throws MathException If the value cannot be converted to a BigRational.
62 *
63 * @psalm-pure
64 */
65 public static function of($value): BigNumber
66 {
67 return parent::of($value)->toBigRational();
68 }
69 /**
70 * Creates a BigRational out of a numerator and a denominator.
71 *
72 * If the denominator is negative, the signs of both the numerator and the denominator
73 * will be inverted to ensure that the denominator is always positive.
74 *
75 * @param BigNumber|int|float|string $numerator The numerator. Must be convertible to a BigInteger.
76 * @param BigNumber|int|float|string $denominator The denominator. Must be convertible to a BigInteger.
77 *
78 * @return BigRational
79 *
80 * @throws NumberFormatException If an argument does not represent a valid number.
81 * @throws RoundingNecessaryException If an argument represents a non-integer number.
82 * @throws DivisionByZeroException If the denominator is zero.
83 *
84 * @psalm-pure
85 */
86 public static function nd($numerator, $denominator): BigRational
87 {
88 $numerator = BigInteger::of($numerator);
89 $denominator = BigInteger::of($denominator);
90 return new BigRational($numerator, $denominator, \true);
91 }
92 /**
93 * Returns a BigRational representing zero.
94 *
95 * @return BigRational
96 *
97 * @psalm-pure
98 */
99 public static function zero(): BigRational
100 {
101 /**
102 * @psalm-suppress ImpureStaticVariable
103 * @var BigRational|null $zero
104 */
105 static $zero;
106 if ($zero === null) {
107 $zero = new BigRational(BigInteger::zero(), BigInteger::one(), \false);
108 }
109 return $zero;
110 }
111 /**
112 * Returns a BigRational representing one.
113 *
114 * @return BigRational
115 *
116 * @psalm-pure
117 */
118 public static function one(): BigRational
119 {
120 /**
121 * @psalm-suppress ImpureStaticVariable
122 * @var BigRational|null $one
123 */
124 static $one;
125 if ($one === null) {
126 $one = new BigRational(BigInteger::one(), BigInteger::one(), \false);
127 }
128 return $one;
129 }
130 /**
131 * Returns a BigRational representing ten.
132 *
133 * @return BigRational
134 *
135 * @psalm-pure
136 */
137 public static function ten(): BigRational
138 {
139 /**
140 * @psalm-suppress ImpureStaticVariable
141 * @var BigRational|null $ten
142 */
143 static $ten;
144 if ($ten === null) {
145 $ten = new BigRational(BigInteger::ten(), BigInteger::one(), \false);
146 }
147 return $ten;
148 }
149 /**
150 * @return BigInteger
151 */
152 public function getNumerator(): BigInteger
153 {
154 return $this->numerator;
155 }
156 /**
157 * @return BigInteger
158 */
159 public function getDenominator(): BigInteger
160 {
161 return $this->denominator;
162 }
163 /**
164 * Returns the quotient of the division of the numerator by the denominator.
165 *
166 * @return BigInteger
167 */
168 public function quotient(): BigInteger
169 {
170 return $this->numerator->quotient($this->denominator);
171 }
172 /**
173 * Returns the remainder of the division of the numerator by the denominator.
174 *
175 * @return BigInteger
176 */
177 public function remainder(): BigInteger
178 {
179 return $this->numerator->remainder($this->denominator);
180 }
181 /**
182 * Returns the quotient and remainder of the division of the numerator by the denominator.
183 *
184 * @return BigInteger[]
185 */
186 public function quotientAndRemainder(): array
187 {
188 return $this->numerator->quotientAndRemainder($this->denominator);
189 }
190 /**
191 * Returns the sum of this number and the given one.
192 *
193 * @param BigNumber|int|float|string $that The number to add.
194 *
195 * @return BigRational The result.
196 *
197 * @throws MathException If the number is not valid.
198 */
199 public function plus($that): BigRational
200 {
201 $that = BigRational::of($that);
202 $numerator = $this->numerator->multipliedBy($that->denominator);
203 $numerator = $numerator->plus($that->numerator->multipliedBy($this->denominator));
204 $denominator = $this->denominator->multipliedBy($that->denominator);
205 return new BigRational($numerator, $denominator, \false);
206 }
207 /**
208 * Returns the difference of this number and the given one.
209 *
210 * @param BigNumber|int|float|string $that The number to subtract.
211 *
212 * @return BigRational The result.
213 *
214 * @throws MathException If the number is not valid.
215 */
216 public function minus($that): BigRational
217 {
218 $that = BigRational::of($that);
219 $numerator = $this->numerator->multipliedBy($that->denominator);
220 $numerator = $numerator->minus($that->numerator->multipliedBy($this->denominator));
221 $denominator = $this->denominator->multipliedBy($that->denominator);
222 return new BigRational($numerator, $denominator, \false);
223 }
224 /**
225 * Returns the product of this number and the given one.
226 *
227 * @param BigNumber|int|float|string $that The multiplier.
228 *
229 * @return BigRational The result.
230 *
231 * @throws MathException If the multiplier is not a valid number.
232 */
233 public function multipliedBy($that): BigRational
234 {
235 $that = BigRational::of($that);
236 $numerator = $this->numerator->multipliedBy($that->numerator);
237 $denominator = $this->denominator->multipliedBy($that->denominator);
238 return new BigRational($numerator, $denominator, \false);
239 }
240 /**
241 * Returns the result of the division of this number by the given one.
242 *
243 * @param BigNumber|int|float|string $that The divisor.
244 *
245 * @return BigRational The result.
246 *
247 * @throws MathException If the divisor is not a valid number, or is zero.
248 */
249 public function dividedBy($that): BigRational
250 {
251 $that = BigRational::of($that);
252 $numerator = $this->numerator->multipliedBy($that->denominator);
253 $denominator = $this->denominator->multipliedBy($that->numerator);
254 return new BigRational($numerator, $denominator, \true);
255 }
256 /**
257 * Returns this number exponentiated to the given value.
258 *
259 * @param int $exponent The exponent.
260 *
261 * @return BigRational The result.
262 *
263 * @throws \InvalidArgumentException If the exponent is not in the range 0 to 1,000,000.
264 */
265 public function power(int $exponent): BigRational
266 {
267 if ($exponent === 0) {
268 $one = BigInteger::one();
269 return new BigRational($one, $one, \false);
270 }
271 if ($exponent === 1) {
272 return $this;
273 }
274 return new BigRational($this->numerator->power($exponent), $this->denominator->power($exponent), \false);
275 }
276 /**
277 * Returns the reciprocal of this BigRational.
278 *
279 * The reciprocal has the numerator and denominator swapped.
280 *
281 * @return BigRational
282 *
283 * @throws DivisionByZeroException If the numerator is zero.
284 */
285 public function reciprocal(): BigRational
286 {
287 return new BigRational($this->denominator, $this->numerator, \true);
288 }
289 /**
290 * Returns the absolute value of this BigRational.
291 *
292 * @return BigRational
293 */
294 public function abs(): BigRational
295 {
296 return new BigRational($this->numerator->abs(), $this->denominator, \false);
297 }
298 /**
299 * Returns the negated value of this BigRational.
300 *
301 * @return BigRational
302 */
303 public function negated(): BigRational
304 {
305 return new BigRational($this->numerator->negated(), $this->denominator, \false);
306 }
307 /**
308 * Returns the simplified value of this BigRational.
309 *
310 * @return BigRational
311 */
312 public function simplified(): BigRational
313 {
314 $gcd = $this->numerator->gcd($this->denominator);
315 $numerator = $this->numerator->quotient($gcd);
316 $denominator = $this->denominator->quotient($gcd);
317 return new BigRational($numerator, $denominator, \false);
318 }
319 /**
320 * {@inheritdoc}
321 */
322 public function compareTo($that): int
323 {
324 return $this->minus($that)->getSign();
325 }
326 /**
327 * {@inheritdoc}
328 */
329 public function getSign(): int
330 {
331 return $this->numerator->getSign();
332 }
333 /**
334 * {@inheritdoc}
335 */
336 public function toBigInteger(): BigInteger
337 {
338 $simplified = $this->simplified();
339 if (!$simplified->denominator->isEqualTo(1)) {
340 throw new RoundingNecessaryException('This rational number cannot be represented as an integer value without rounding.');
341 }
342 return $simplified->numerator;
343 }
344 /**
345 * {@inheritdoc}
346 */
347 public function toBigDecimal(): BigDecimal
348 {
349 return $this->numerator->toBigDecimal()->exactlyDividedBy($this->denominator);
350 }
351 /**
352 * {@inheritdoc}
353 */
354 public function toBigRational(): BigRational
355 {
356 return $this;
357 }
358 /**
359 * {@inheritdoc}
360 */
361 public function toScale(int $scale, int $roundingMode = RoundingMode::UNNECESSARY): BigDecimal
362 {
363 return $this->numerator->toBigDecimal()->dividedBy($this->denominator, $scale, $roundingMode);
364 }
365 /**
366 * {@inheritdoc}
367 */
368 public function toInt(): int
369 {
370 return $this->toBigInteger()->toInt();
371 }
372 /**
373 * {@inheritdoc}
374 */
375 public function toFloat(): float
376 {
377 return $this->numerator->toFloat() / $this->denominator->toFloat();
378 }
379 /**
380 * {@inheritdoc}
381 */
382 public function __toString(): string
383 {
384 $numerator = (string) $this->numerator;
385 $denominator = (string) $this->denominator;
386 if ($denominator === '1') {
387 return $numerator;
388 }
389 return $this->numerator . '/' . $this->denominator;
390 }
391 /**
392 * This method is required for serializing the object and SHOULD NOT be accessed directly.
393 *
394 * @internal
395 *
396 * @return array{numerator: BigInteger, denominator: BigInteger}
397 */
398 public function __serialize(): array
399 {
400 return ['numerator' => $this->numerator, 'denominator' => $this->denominator];
401 }
402 /**
403 * This method is only here to allow unserializing the object and cannot be accessed directly.
404 *
405 * @internal
406 * @psalm-suppress RedundantPropertyInitializationCheck
407 *
408 * @param array{numerator: BigInteger, denominator: BigInteger} $data
409 *
410 * @return void
411 *
412 * @throws \LogicException
413 */
414 public function __unserialize(array $data): void
415 {
416 if (isset($this->numerator)) {
417 throw new \LogicException('__unserialize() is an internal function, it must not be called directly.');
418 }
419 $this->numerator = $data['numerator'];
420 $this->denominator = $data['denominator'];
421 }
422 /**
423 * This method is required by interface Serializable and SHOULD NOT be accessed directly.
424 *
425 * @internal
426 *
427 * @return string
428 */
429 public function serialize(): string
430 {
431 return $this->numerator . '/' . $this->denominator;
432 }
433 /**
434 * This method is only here to implement interface Serializable and cannot be accessed directly.
435 *
436 * @internal
437 * @psalm-suppress RedundantPropertyInitializationCheck
438 *
439 * @param string $value
440 *
441 * @return void
442 *
443 * @throws \LogicException
444 */
445 public function unserialize($value): void
446 {
447 if (isset($this->numerator)) {
448 throw new \LogicException('unserialize() is an internal function, it must not be called directly.');
449 }
450 [$numerator, $denominator] = \explode('/', $value);
451 $this->numerator = BigInteger::of($numerator);
452 $this->denominator = BigInteger::of($denominator);
453 }
454 }
455