PluginProbe
Media Cloud Sync / 1.3.11
Media Cloud Sync v1.3.11
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.3.11, at includes/sdk/google/brick/math/src/BigRational.php

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