PluginProbe ʕ •ᴥ•ʔ
JetBackup – Backup, Restore & Migrate / trunk
JetBackup – Backup, Restore & Migrate vtrunk
3.1.22.3 1.4.3 1.4.4 1.4.5 1.4.6 1.4.7 1.4.8 1.4.8.1 1.4.9 1.5.0 1.5.1 1.5.1.1 1.5.2 1.5.3 1.5.4 1.5.5 1.5.6 1.5.7 1.5.8 1.6.0 1.6.10 1.6.11 1.6.12 1.6.13 1.6.15 1.6.5.1 1.6.8.8 1.6.9 1.6.9.1 2.0.3 2.0.4 2.0.5 2.0.6 2.0.7.5 2.0.8.7 2.0.9.11 2.0.9.14 2.0.9.15 2.0.9.6 2.0.9.7 2.0.9.9 3.1.10.7 3.1.11.1 3.1.12.3 3.1.13.4 3.1.14.17 3.1.15.4 3.1.16.1 3.1.17.5 3.1.18.10 3.1.18.8 3.1.18.9 3.1.19.8 3.1.20.3 3.1.21.3 3.1.7.9 3.1.9.2 trunk 1.1.90 1.1.91 1.2.0 1.2.5 1.2.6 1.2.7 1.2.8 1.2.9 1.3.0 1.3.1 1.3.2 1.3.3 1.3.4 1.3.6 1.3.7 1.3.8 1.3.9 1.4.0 1.4.1 1.4.2
backup / src / JetBackup / 3rdparty / phpseclib3 / Math / BigInteger.php
backup / src / JetBackup / 3rdparty / phpseclib3 / Math Last commit date
BigInteger 1 year ago BinaryField 1 year ago Common 1 year ago PrimeField 1 year ago .htaccess 1 year ago BigInteger.php 1 year ago BinaryField.php 1 year ago PrimeField.php 1 year ago index.html 1 year ago web.config 1 year ago
BigInteger.php
774 lines
1 <?php
2
3 /**
4 * Pure-PHP arbitrary precision integer arithmetic library.
5 *
6 * Supports base-2, base-10, base-16, and base-256 numbers. Uses the GMP or BCMath extensions, if available,
7 * and an internal implementation, otherwise.
8 *
9 * PHP version 5 and 7
10 *
11 * Here's an example of how to use this library:
12 * <code>
13 * <?php
14 * $a = new \phpseclib3\Math\BigInteger(2);
15 * $b = new \phpseclib3\Math\BigInteger(3);
16 *
17 * $c = $a->add($b);
18 *
19 * echo $c->toString(); // outputs 5
20 * ?>
21 * </code>
22 *
23 * @author Jim Wigginton <terrafrost@php.net>
24 * @copyright 2017 Jim Wigginton
25 * @license http://www.opensource.org/licenses/mit-license.html MIT License
26 */
27
28 declare(strict_types=1);
29
30 namespace phpseclib3\Math;
31
32 use phpseclib3\Exception\BadConfigurationException;
33 use phpseclib3\Exception\InvalidArgumentException;
34 use phpseclib3\Exception\UnexpectedValueException;
35 use phpseclib3\Math\BigInteger\Engines\Engine;
36
37 /**
38 * Pure-PHP arbitrary precision integer arithmetic library. Supports base-2, base-10, base-16, and base-256
39 * numbers.
40 *
41 * @author Jim Wigginton <terrafrost@php.net>
42 */
43 class BigInteger implements \JsonSerializable
44 {
45 /**
46 * Main Engine
47 *
48 * @var class-string<Engine>
49 */
50 private static $mainEngine;
51
52 /**
53 * Selected Engines
54 *
55 * @var list<string>
56 */
57 private static $engines;
58
59 /**
60 * The actual BigInteger object
61 *
62 * @var object
63 */
64 private $value;
65
66 /**
67 * Mode independent value used for serialization.
68 *
69 * @see self::__sleep()
70 * @see self::__wakeup()
71 * @var string
72 */
73 private $hex;
74
75 /**
76 * Precision (used only for serialization)
77 *
78 * @see self::__sleep()
79 * @see self::__wakeup()
80 * @var int
81 */
82 private $precision;
83
84 /**
85 * Sets engine type.
86 *
87 * Throws an exception if the type is invalid
88 *
89 * @param list<string> $modexps optional
90 */
91 public static function setEngine(string $main, array $modexps = ['DefaultEngine']): void
92 {
93 self::$engines = [];
94
95 $fqmain = 'phpseclib3\\Math\\BigInteger\\Engines\\' . $main;
96 if (!class_exists($fqmain) || !method_exists($fqmain, 'isValidEngine')) {
97 throw new InvalidArgumentException("$main is not a valid engine");
98 }
99 if (!$fqmain::isValidEngine()) {
100 throw new BadConfigurationException("$main is not setup correctly on this system");
101 }
102 /** @var class-string<Engine> $fqmain */
103 self::$mainEngine = $fqmain;
104
105 $found = false;
106 foreach ($modexps as $modexp) {
107 try {
108 $fqmain::setModExpEngine($modexp);
109 $found = true;
110 break;
111 } catch (\Exception $e) {
112 }
113 }
114
115 if (!$found) {
116 throw new BadConfigurationException("No valid modular exponentiation engine found for $main");
117 }
118
119 self::$engines = [$main, $modexp];
120 }
121
122 /**
123 * Returns the engine type
124 *
125 * @return string[]
126 */
127 public static function getEngine(): array
128 {
129 self::initialize_static_variables();
130
131 return self::$engines;
132 }
133
134 /**
135 * Initialize static variables
136 */
137 private static function initialize_static_variables(): void
138 {
139 if (!isset(self::$mainEngine)) {
140 $engines = [
141 ['GMP', ['DefaultEngine']],
142 ['PHP64', ['OpenSSL']],
143 ['BCMath', ['OpenSSL']],
144 ['PHP32', ['OpenSSL']],
145 ['PHP64', ['DefaultEngine']],
146 ['PHP32', ['DefaultEngine']],
147 ];
148
149 foreach ($engines as $engine) {
150 try {
151 self::setEngine($engine[0], $engine[1]);
152 return;
153 } catch (\Exception $e) {
154 }
155 }
156
157 throw new UnexpectedValueException('No valid BigInteger found. This is only possible when JIT is enabled on Windows and neither the GMP or BCMath extensions are available so either disable JIT or install GMP / BCMath');
158 }
159 }
160
161 /**
162 * Converts base-2, base-10, base-16, and binary strings (base-256) to BigIntegers.
163 *
164 * If the second parameter - $base - is negative, then it will be assumed that the number's are encoded using
165 * two's compliment. The sole exception to this is -10, which is treated the same as 10 is.
166 *
167 * @param string|int|BigInteger\Engines\Engine $x Base-10 number or base-$base number if $base set.
168 */
169 public function __construct($x = 0, int $base = 10)
170 {
171 self::initialize_static_variables();
172
173 if ($x instanceof self::$mainEngine) {
174 $this->value = clone $x;
175 } elseif ($x instanceof BigInteger\Engines\Engine) {
176 $this->value = new static("$x");
177 $this->value->setPrecision($x->getPrecision());
178 } else {
179 $this->value = new self::$mainEngine($x, $base);
180 }
181 }
182
183 /**
184 * Converts a BigInteger to a base-10 number.
185 */
186 public function toString(): string
187 {
188 return $this->value->toString();
189 }
190
191 /**
192 * __toString() magic method
193 */
194 public function __toString()
195 {
196 return (string)$this->value;
197 }
198
199 /**
200 * __debugInfo() magic method
201 *
202 * Will be called, automatically, when print_r() or var_dump() are called
203 */
204 public function __debugInfo()
205 {
206 return $this->value->__debugInfo();
207 }
208
209 /**
210 * Converts a BigInteger to a byte string (eg. base-256).
211 */
212 public function toBytes(bool $twos_compliment = false): string
213 {
214 return $this->value->toBytes($twos_compliment);
215 }
216
217 /**
218 * Converts a BigInteger to a hex string (eg. base-16).
219 */
220 public function toHex(bool $twos_compliment = false): string
221 {
222 return $this->value->toHex($twos_compliment);
223 }
224
225 /**
226 * Converts a BigInteger to a bit string (eg. base-2).
227 *
228 * Negative numbers are saved as positive numbers, unless $twos_compliment is set to true, at which point, they're
229 * saved as two's compliment.
230 */
231 public function toBits(bool $twos_compliment = false): string
232 {
233 return $this->value->toBits($twos_compliment);
234 }
235
236 /**
237 * Adds two BigIntegers.
238 */
239 public function add(BigInteger $y): BigInteger
240 {
241 return new static($this->value->add($y->value));
242 }
243
244 /**
245 * Subtracts two BigIntegers.
246 */
247 public function subtract(BigInteger $y): BigInteger
248 {
249 return new static($this->value->subtract($y->value));
250 }
251
252 /**
253 * Multiplies two BigIntegers
254 */
255 public function multiply(BigInteger $x): BigInteger
256 {
257 return new static($this->value->multiply($x->value));
258 }
259
260 /**
261 * Divides two BigIntegers.
262 *
263 * Returns an array whose first element contains the quotient and whose second element contains the
264 * "common residue". If the remainder would be positive, the "common residue" and the remainder are the
265 * same. If the remainder would be negative, the "common residue" is equal to the sum of the remainder
266 * and the divisor (basically, the "common residue" is the first positive modulo).
267 *
268 * Here's an example:
269 * <code>
270 * <?php
271 * $a = new \phpseclib3\Math\BigInteger('10');
272 * $b = new \phpseclib3\Math\BigInteger('20');
273 *
274 * list($quotient, $remainder) = $a->divide($b);
275 *
276 * echo $quotient->toString(); // outputs 0
277 * echo "\r\n";
278 * echo $remainder->toString(); // outputs 10
279 * ?>
280 * </code>
281 *
282 * @return BigInteger[]
283 */
284 public function divide(BigInteger $y): array
285 {
286 [$q, $r] = $this->value->divide($y->value);
287 return [
288 new static($q),
289 new static($r),
290 ];
291 }
292
293 /**
294 * Calculates modular inverses.
295 *
296 * Say you have (30 mod 17 * x mod 17) mod 17 == 1. x can be found using modular inverses.
297 */
298 public function modInverse(BigInteger $n): BigInteger
299 {
300 return new static($this->value->modInverse($n->value));
301 }
302
303 /**
304 * Calculates modular inverses.
305 *
306 * Say you have (30 mod 17 * x mod 17) mod 17 == 1. x can be found using modular inverses.
307 *
308 * @return BigInteger[]
309 */
310 public function extendedGCD(BigInteger $n): array
311 {
312 extract($this->value->extendedGCD($n->value));
313 /**
314 * @var BigInteger $gcd
315 * @var BigInteger $x
316 * @var BigInteger $y
317 */
318 return [
319 'gcd' => new static($gcd),
320 'x' => new static($x),
321 'y' => new static($y),
322 ];
323 }
324
325 /**
326 * Calculates the greatest common divisor
327 *
328 * Say you have 693 and 609. The GCD is 21.
329 */
330 public function gcd(BigInteger $n): BigInteger
331 {
332 return new static($this->value->gcd($n->value));
333 }
334
335 /**
336 * Absolute value.
337 */
338 public function abs(): BigInteger
339 {
340 return new static($this->value->abs());
341 }
342
343 /**
344 * Set Precision
345 *
346 * Some bitwise operations give different results depending on the precision being used. Examples include left
347 * shift, not, and rotates.
348 */
349 public function setPrecision(int $bits): void
350 {
351 $this->value->setPrecision($bits);
352 }
353
354 /**
355 * Get Precision
356 *
357 * Returns the precision if it exists, false if it doesn't
358 *
359 * @return int|bool
360 */
361 public function getPrecision()
362 {
363 return $this->value->getPrecision();
364 }
365
366 /**
367 * Serialize
368 *
369 * Will be called, automatically, when serialize() is called on a BigInteger object.
370 *
371 * __sleep() / __wakeup() have been around since PHP 4.0
372 *
373 * \Serializable was introduced in PHP 5.1 and deprecated in PHP 8.1:
374 * https://wiki.php.net/rfc/phase_out_serializable
375 *
376 * __serialize() / __unserialize() were introduced in PHP 7.4:
377 * https://wiki.php.net/rfc/custom_object_serialization
378 *
379 * @return array
380 */
381 public function __sleep()
382 {
383 $this->hex = $this->toHex(true);
384 $vars = ['hex'];
385 if ($this->getPrecision() > 0) {
386 $vars[] = 'precision';
387 }
388 return $vars;
389 }
390
391 /**
392 * Serialize
393 *
394 * Will be called, automatically, when unserialize() is called on a BigInteger object.
395 */
396 public function __wakeup(): void
397 {
398 $temp = new static($this->hex, -16);
399 $this->value = $temp->value;
400 if ($this->precision > 0) {
401 // recalculate $this->bitmask
402 $this->setPrecision($this->precision);
403 }
404 }
405
406 /**
407 * JSON Serialize
408 *
409 * Will be called, automatically, when json_encode() is called on a BigInteger object.
410 *
411 * @return array{hex: string, precision?: int]
412 */
413 #[\ReturnTypeWillChange]
414 public function jsonSerialize(): array
415 {
416 $result = ['hex' => $this->toHex(true)];
417 if ($this->precision > 0) {
418 $result['precision'] = $this->getPrecision();
419 }
420 return $result;
421 }
422
423 /**
424 * Performs modular exponentiation.
425 */
426 public function powMod(BigInteger $e, BigInteger $n): BigInteger
427 {
428 return new static($this->value->powMod($e->value, $n->value));
429 }
430
431 /**
432 * Performs modular exponentiation.
433 */
434 public function modPow(BigInteger $e, BigInteger $n): BigInteger
435 {
436 return new static($this->value->modPow($e->value, $n->value));
437 }
438
439 /**
440 * Compares two numbers.
441 *
442 * Although one might think !$x->compare($y) means $x != $y, it, in fact, means the opposite. The reason for this
443 * is demonstrated thusly:
444 *
445 * $x > $y: $x->compare($y) > 0
446 * $x < $y: $x->compare($y) < 0
447 * $x == $y: $x->compare($y) == 0
448 *
449 * Note how the same comparison operator is used. If you want to test for equality, use $x->equals($y).
450 *
451 * {@internal Could return $this->subtract($x), but that's not as fast as what we do do.}
452 *
453 * @return int in case < 0 if $this is less than $y; > 0 if $this is greater than $y, and 0 if they are equal.
454 * @see self::equals()
455 */
456 public function compare(BigInteger $y): int
457 {
458 return $this->value->compare($y->value);
459 }
460
461 /**
462 * Tests the equality of two numbers.
463 *
464 * If you need to see if one number is greater than or less than another number, use BigInteger::compare()
465 */
466 public function equals(BigInteger $x): bool
467 {
468 return $this->value->equals($x->value);
469 }
470
471 /**
472 * Logical Not
473 */
474 public function bitwise_not(): BigInteger
475 {
476 return new static($this->value->bitwise_not());
477 }
478
479 /**
480 * Logical And
481 */
482 public function bitwise_and(BigInteger $x): BigInteger
483 {
484 return new static($this->value->bitwise_and($x->value));
485 }
486
487 /**
488 * Logical Or
489 */
490 public function bitwise_or(BigInteger $x): BigInteger
491 {
492 return new static($this->value->bitwise_or($x->value));
493 }
494
495 /**
496 * Logical Exclusive Or
497 */
498 public function bitwise_xor(BigInteger $x): BigInteger
499 {
500 return new static($this->value->bitwise_xor($x->value));
501 }
502
503 /**
504 * Logical Right Shift
505 *
506 * Shifts BigInteger's by $shift bits, effectively dividing by 2**$shift.
507 */
508 public function bitwise_rightShift(int $shift): BigInteger
509 {
510 return new static($this->value->bitwise_rightShift($shift));
511 }
512
513 /**
514 * Logical Left Shift
515 *
516 * Shifts BigInteger's by $shift bits, effectively multiplying by 2**$shift.
517 */
518 public function bitwise_leftShift(int $shift): BigInteger
519 {
520 return new static($this->value->bitwise_leftShift($shift));
521 }
522
523 /**
524 * Logical Left Rotate
525 *
526 * Instead of the top x bits being dropped they're appended to the shifted bit string.
527 */
528 public function bitwise_leftRotate(int $shift): BigInteger
529 {
530 return new static($this->value->bitwise_leftRotate($shift));
531 }
532
533 /**
534 * Logical Right Rotate
535 *
536 * Instead of the bottom x bits being dropped they're prepended to the shifted bit string.
537 */
538 public function bitwise_rightRotate(int $shift): BigInteger
539 {
540 return new static($this->value->bitwise_rightRotate($shift));
541 }
542
543 /**
544 * Returns the smallest and largest n-bit number
545 *
546 * @return BigInteger[]
547 */
548 public static function minMaxBits(int $bits): array
549 {
550 self::initialize_static_variables();
551
552 $class = self::$mainEngine;
553 extract($class::minMaxBits($bits));
554 /** @var BigInteger $min
555 * @var BigInteger $max
556 */
557 return [
558 'min' => new static($min),
559 'max' => new static($max),
560 ];
561 }
562
563 /**
564 * Return the size of a BigInteger in bits
565 */
566 public function getLength(): int
567 {
568 return $this->value->getLength();
569 }
570
571 /**
572 * Return the size of a BigInteger in bytes
573 */
574 public function getLengthInBytes(): int
575 {
576 return $this->value->getLengthInBytes();
577 }
578
579 /**
580 * Generates a random number of a certain size
581 *
582 * Bit length is equal to $size
583 */
584 public static function random(int $size): BigInteger
585 {
586 self::initialize_static_variables();
587
588 $class = self::$mainEngine;
589 return new static($class::random($size));
590 }
591
592 /**
593 * Generates a random prime number of a certain size
594 *
595 * Bit length is equal to $size
596 */
597 public static function randomPrime(int $size): BigInteger
598 {
599 self::initialize_static_variables();
600
601 $class = self::$mainEngine;
602 return new static($class::randomPrime($size));
603 }
604
605 /**
606 * Generate a random prime number between a range
607 *
608 * If there's not a prime within the given range, false will be returned.
609 *
610 * @return false|BigInteger
611 */
612 public static function randomRangePrime(BigInteger $min, BigInteger $max)
613 {
614 $class = self::$mainEngine;
615 return new static($class::randomRangePrime($min->value, $max->value));
616 }
617
618 /**
619 * Generate a random number between a range
620 *
621 * Returns a random number between $min and $max where $min and $max
622 * can be defined using one of the two methods:
623 *
624 * BigInteger::randomRange($min, $max)
625 * BigInteger::randomRange($max, $min)
626 */
627 public static function randomRange(BigInteger $min, BigInteger $max): BigInteger
628 {
629 $class = self::$mainEngine;
630 return new static($class::randomRange($min->value, $max->value));
631 }
632
633 /**
634 * Checks a numer to see if it's prime
635 *
636 * Assuming the $t parameter is not set, this function has an error rate of 2**-80. The main motivation for the
637 * $t parameter is distributability. BigInteger::randomPrime() can be distributed across multiple pageloads
638 * on a website instead of just one.
639 *
640 * @param int|bool $t
641 */
642 public function isPrime($t = false): bool
643 {
644 return $this->value->isPrime($t);
645 }
646
647 /**
648 * Calculates the nth root of a biginteger.
649 *
650 * Returns the nth root of a positive biginteger, where n defaults to 2
651 *
652 * @param int $n optional
653 */
654 public function root(int $n = 2): BigInteger
655 {
656 return new static($this->value->root($n));
657 }
658
659 /**
660 * Performs exponentiation.
661 */
662 public function pow(BigInteger $n): BigInteger
663 {
664 return new static($this->value->pow($n->value));
665 }
666
667 /**
668 * Return the minimum BigInteger between an arbitrary number of BigIntegers.
669 */
670 public static function min(BigInteger ...$nums): BigInteger
671 {
672 $class = self::$mainEngine;
673 $nums = array_map(fn ($num) => $num->value, $nums);
674 return new static($class::min(...$nums));
675 }
676
677 /**
678 * Return the maximum BigInteger between an arbitrary number of BigIntegers.
679 */
680 public static function max(BigInteger ...$nums): BigInteger
681 {
682 $class = self::$mainEngine;
683 $nums = array_map(fn ($num) => $num->value, $nums);
684 return new static($class::max(...$nums));
685 }
686
687 /**
688 * Tests BigInteger to see if it is between two integers, inclusive
689 */
690 public function between(BigInteger $min, BigInteger $max): bool
691 {
692 return $this->value->between($min->value, $max->value);
693 }
694
695 /**
696 * Clone
697 */
698 public function __clone()
699 {
700 $this->value = clone $this->value;
701 }
702
703 /**
704 * Is Odd?
705 */
706 public function isOdd(): bool
707 {
708 return $this->value->isOdd();
709 }
710
711 /**
712 * Tests if a bit is set
713 */
714 public function testBit(int $x): bool
715 {
716 return $this->value->testBit($x);
717 }
718
719 /**
720 * Is Negative?
721 */
722 public function isNegative(): bool
723 {
724 return $this->value->isNegative();
725 }
726
727 /**
728 * Negate
729 *
730 * Given $k, returns -$k
731 */
732 public function negate(): BigInteger
733 {
734 return new static($this->value->negate());
735 }
736
737 /**
738 * Scan for 1 and right shift by that amount
739 *
740 * ie. $s = gmp_scan1($n, 0) and $r = gmp_div_q($n, gmp_pow(gmp_init('2'), $s));
741 */
742 public static function scan1divide(BigInteger $r): int
743 {
744 $class = self::$mainEngine;
745 return $class::scan1divide($r->value);
746 }
747
748 /**
749 * Create Recurring Modulo Function
750 *
751 * Sometimes it may be desirable to do repeated modulos with the same number outside of
752 * modular exponentiation
753 *
754 * @return callable
755 */
756 public function createRecurringModuloFunction()
757 {
758 $func = $this->value->createRecurringModuloFunction();
759 return fn (BigInteger $x) => new static($func($x->value));
760 }
761
762 /**
763 * Bitwise Split
764 *
765 * Splits BigInteger's into chunks of $split bits
766 *
767 * @return BigInteger[]
768 */
769 public function bitwise_split(int $split): array
770 {
771 return array_map(fn ($val) => new static($val), $this->value->bitwise_split($split));
772 }
773 }
774