Rev 1101 | Rev 1324 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
827 | daniel-mar | 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 | namespace phpseclib3\Math; |
||
29 | |||
30 | use phpseclib3\Exception\BadConfigurationException; |
||
31 | use phpseclib3\Math\BigInteger\Engines\Engine; |
||
32 | |||
33 | /** |
||
34 | * Pure-PHP arbitrary precision integer arithmetic library. Supports base-2, base-10, base-16, and base-256 |
||
35 | * numbers. |
||
36 | * |
||
37 | * @author Jim Wigginton <terrafrost@php.net> |
||
38 | */ |
||
39 | class BigInteger implements \JsonSerializable |
||
40 | { |
||
41 | /** |
||
42 | * Main Engine |
||
43 | * |
||
44 | * @var class-string<Engine> |
||
45 | */ |
||
46 | private static $mainEngine; |
||
47 | |||
48 | /** |
||
49 | * Selected Engines |
||
50 | * |
||
51 | * @var list<string> |
||
52 | */ |
||
53 | private static $engines; |
||
54 | |||
55 | /** |
||
56 | * The actual BigInteger object |
||
57 | * |
||
58 | * @var object |
||
59 | */ |
||
60 | private $value; |
||
61 | |||
62 | /** |
||
63 | * Mode independent value used for serialization. |
||
64 | * |
||
65 | * @see self::__sleep() |
||
66 | * @see self::__wakeup() |
||
67 | * @var string |
||
68 | */ |
||
69 | private $hex; |
||
70 | |||
71 | /** |
||
72 | * Precision (used only for serialization) |
||
73 | * |
||
74 | * @see self::__sleep() |
||
75 | * @see self::__wakeup() |
||
76 | * @var int |
||
77 | */ |
||
78 | private $precision; |
||
79 | |||
80 | /** |
||
81 | * Sets engine type. |
||
82 | * |
||
83 | * Throws an exception if the type is invalid |
||
84 | * |
||
85 | * @param string $main |
||
86 | * @param list<string> $modexps optional |
||
87 | * @return void |
||
88 | */ |
||
89 | public static function setEngine($main, array $modexps = ['DefaultEngine']) |
||
90 | { |
||
91 | self::$engines = []; |
||
92 | |||
93 | $fqmain = 'phpseclib3\\Math\\BigInteger\\Engines\\' . $main; |
||
94 | if (!class_exists($fqmain) || !method_exists($fqmain, 'isValidEngine')) { |
||
95 | throw new \InvalidArgumentException("$main is not a valid engine"); |
||
96 | } |
||
97 | if (!$fqmain::isValidEngine()) { |
||
98 | throw new BadConfigurationException("$main is not setup correctly on this system"); |
||
99 | } |
||
100 | /** @var class-string<Engine> $fqmain */ |
||
101 | self::$mainEngine = $fqmain; |
||
102 | |||
103 | if (!in_array('Default', $modexps)) { |
||
104 | $modexps[] = 'DefaultEngine'; |
||
105 | } |
||
106 | |||
107 | $found = false; |
||
108 | foreach ($modexps as $modexp) { |
||
109 | try { |
||
110 | $fqmain::setModExpEngine($modexp); |
||
111 | $found = true; |
||
112 | break; |
||
113 | } catch (\Exception $e) { |
||
114 | } |
||
115 | } |
||
116 | |||
117 | if (!$found) { |
||
118 | throw new BadConfigurationException("No valid modular exponentiation engine found for $main"); |
||
119 | } |
||
120 | |||
121 | self::$engines = [$main, $modexp]; |
||
122 | } |
||
123 | |||
124 | /** |
||
125 | * Returns the engine type |
||
126 | * |
||
127 | * @return string[] |
||
128 | */ |
||
129 | public static function getEngine() |
||
130 | { |
||
131 | self::initialize_static_variables(); |
||
132 | |||
133 | return self::$engines; |
||
134 | } |
||
135 | |||
136 | /** |
||
137 | * Initialize static variables |
||
138 | */ |
||
139 | private static function initialize_static_variables() |
||
140 | { |
||
141 | if (!isset(self::$mainEngine)) { |
||
142 | $engines = [ |
||
143 | ['GMP'], |
||
144 | ['PHP64', ['OpenSSL']], |
||
145 | ['BCMath', ['OpenSSL']], |
||
146 | ['PHP32', ['OpenSSL']] |
||
147 | ]; |
||
148 | foreach ($engines as $engine) { |
||
149 | try { |
||
150 | self::setEngine($engine[0], isset($engine[1]) ? $engine[1] : []); |
||
151 | break; |
||
152 | } catch (\Exception $e) { |
||
153 | } |
||
154 | } |
||
155 | } |
||
156 | } |
||
157 | |||
158 | /** |
||
159 | * Converts base-2, base-10, base-16, and binary strings (base-256) to BigIntegers. |
||
160 | * |
||
161 | * If the second parameter - $base - is negative, then it will be assumed that the number's are encoded using |
||
162 | * two's compliment. The sole exception to this is -10, which is treated the same as 10 is. |
||
163 | * |
||
164 | * @param string|int|BigInteger\Engines\Engine $x Base-10 number or base-$base number if $base set. |
||
165 | * @param int $base |
||
166 | */ |
||
167 | public function __construct($x = 0, $base = 10) |
||
168 | { |
||
169 | self::initialize_static_variables(); |
||
170 | |||
171 | if ($x instanceof self::$mainEngine) { |
||
172 | $this->value = clone $x; |
||
173 | } elseif ($x instanceof BigInteger\Engines\Engine) { |
||
174 | $this->value = new static("$x"); |
||
175 | $this->value->setPrecision($x->getPrecision()); |
||
176 | } else { |
||
177 | $this->value = new self::$mainEngine($x, $base); |
||
178 | } |
||
179 | } |
||
180 | |||
181 | /** |
||
182 | * Converts a BigInteger to a base-10 number. |
||
183 | * |
||
184 | * @return string |
||
185 | */ |
||
186 | public function toString() |
||
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 | * @param bool $twos_compliment |
||
213 | * @return string |
||
214 | */ |
||
215 | public function toBytes($twos_compliment = false) |
||
216 | { |
||
217 | return $this->value->toBytes($twos_compliment); |
||
218 | } |
||
219 | |||
220 | /** |
||
221 | * Converts a BigInteger to a hex string (eg. base-16). |
||
222 | * |
||
223 | * @param bool $twos_compliment |
||
224 | * @return string |
||
225 | */ |
||
226 | public function toHex($twos_compliment = false) |
||
227 | { |
||
228 | return $this->value->toHex($twos_compliment); |
||
229 | } |
||
230 | |||
231 | /** |
||
232 | * Converts a BigInteger to a bit string (eg. base-2). |
||
233 | * |
||
234 | * Negative numbers are saved as positive numbers, unless $twos_compliment is set to true, at which point, they're |
||
235 | * saved as two's compliment. |
||
236 | * |
||
237 | * @param bool $twos_compliment |
||
238 | * @return string |
||
239 | */ |
||
240 | public function toBits($twos_compliment = false) |
||
241 | { |
||
242 | return $this->value->toBits($twos_compliment); |
||
243 | } |
||
244 | |||
245 | /** |
||
246 | * Adds two BigIntegers. |
||
247 | * |
||
248 | * @param BigInteger $y |
||
249 | * @return BigInteger |
||
250 | */ |
||
251 | public function add(BigInteger $y) |
||
252 | { |
||
253 | return new static($this->value->add($y->value)); |
||
254 | } |
||
255 | |||
256 | /** |
||
257 | * Subtracts two BigIntegers. |
||
258 | * |
||
259 | * @param BigInteger $y |
||
260 | * @return BigInteger |
||
261 | */ |
||
262 | public function subtract(BigInteger $y) |
||
263 | { |
||
264 | return new static($this->value->subtract($y->value)); |
||
265 | } |
||
266 | |||
267 | /** |
||
268 | * Multiplies two BigIntegers |
||
269 | * |
||
270 | * @param BigInteger $x |
||
271 | * @return BigInteger |
||
272 | */ |
||
273 | public function multiply(BigInteger $x) |
||
274 | { |
||
275 | return new static($this->value->multiply($x->value)); |
||
276 | } |
||
277 | |||
278 | /** |
||
279 | * Divides two BigIntegers. |
||
280 | * |
||
281 | * Returns an array whose first element contains the quotient and whose second element contains the |
||
282 | * "common residue". If the remainder would be positive, the "common residue" and the remainder are the |
||
283 | * same. If the remainder would be negative, the "common residue" is equal to the sum of the remainder |
||
284 | * and the divisor (basically, the "common residue" is the first positive modulo). |
||
285 | * |
||
286 | * Here's an example: |
||
287 | * <code> |
||
288 | * <?php |
||
289 | * $a = new \phpseclib3\Math\BigInteger('10'); |
||
290 | * $b = new \phpseclib3\Math\BigInteger('20'); |
||
291 | * |
||
292 | * list($quotient, $remainder) = $a->divide($b); |
||
293 | * |
||
294 | * echo $quotient->toString(); // outputs 0 |
||
295 | * echo "\r\n"; |
||
296 | * echo $remainder->toString(); // outputs 10 |
||
297 | * ?> |
||
298 | * </code> |
||
299 | * |
||
300 | * @param BigInteger $y |
||
301 | * @return BigInteger[] |
||
302 | */ |
||
303 | public function divide(BigInteger $y) |
||
304 | { |
||
305 | list($q, $r) = $this->value->divide($y->value); |
||
306 | return [ |
||
307 | new static($q), |
||
308 | new static($r) |
||
309 | ]; |
||
310 | } |
||
311 | |||
312 | /** |
||
313 | * Calculates modular inverses. |
||
314 | * |
||
315 | * Say you have (30 mod 17 * x mod 17) mod 17 == 1. x can be found using modular inverses. |
||
316 | * |
||
317 | * @param BigInteger $n |
||
318 | * @return BigInteger |
||
319 | */ |
||
320 | public function modInverse(BigInteger $n) |
||
321 | { |
||
322 | return new static($this->value->modInverse($n->value)); |
||
323 | } |
||
324 | |||
325 | /** |
||
326 | * Calculates modular inverses. |
||
327 | * |
||
328 | * Say you have (30 mod 17 * x mod 17) mod 17 == 1. x can be found using modular inverses. |
||
329 | * |
||
330 | * @param BigInteger $n |
||
331 | * @return BigInteger[] |
||
332 | */ |
||
333 | public function extendedGCD(BigInteger $n) |
||
334 | { |
||
335 | extract($this->value->extendedGCD($n->value)); |
||
336 | /** |
||
337 | * @var BigInteger $gcd |
||
338 | * @var BigInteger $x |
||
339 | * @var BigInteger $y |
||
340 | */ |
||
341 | return [ |
||
342 | 'gcd' => new static($gcd), |
||
343 | 'x' => new static($x), |
||
344 | 'y' => new static($y) |
||
345 | ]; |
||
346 | } |
||
347 | |||
348 | /** |
||
349 | * Calculates the greatest common divisor |
||
350 | * |
||
351 | * Say you have 693 and 609. The GCD is 21. |
||
352 | * |
||
353 | * @param BigInteger $n |
||
354 | * @return BigInteger |
||
355 | */ |
||
356 | public function gcd(BigInteger $n) |
||
357 | { |
||
358 | return new static($this->value->gcd($n->value)); |
||
359 | } |
||
360 | |||
361 | /** |
||
362 | * Absolute value. |
||
363 | * |
||
364 | * @return BigInteger |
||
365 | */ |
||
366 | public function abs() |
||
367 | { |
||
368 | return new static($this->value->abs()); |
||
369 | } |
||
370 | |||
371 | /** |
||
372 | * Set Precision |
||
373 | * |
||
374 | * Some bitwise operations give different results depending on the precision being used. Examples include left |
||
375 | * shift, not, and rotates. |
||
376 | * |
||
377 | * @param int $bits |
||
378 | */ |
||
379 | public function setPrecision($bits) |
||
380 | { |
||
381 | $this->value->setPrecision($bits); |
||
382 | } |
||
383 | |||
384 | /** |
||
385 | * Get Precision |
||
386 | * |
||
387 | * Returns the precision if it exists, false if it doesn't |
||
388 | * |
||
389 | * @return int|bool |
||
390 | */ |
||
391 | public function getPrecision() |
||
392 | { |
||
393 | return $this->value->getPrecision(); |
||
394 | } |
||
395 | |||
396 | /** |
||
397 | * Serialize |
||
398 | * |
||
399 | * Will be called, automatically, when serialize() is called on a BigInteger object. |
||
400 | * |
||
401 | * __sleep() / __wakeup() have been around since PHP 4.0 |
||
402 | * |
||
403 | * \Serializable was introduced in PHP 5.1 and deprecated in PHP 8.1: |
||
404 | * https://wiki.php.net/rfc/phase_out_serializable |
||
405 | * |
||
406 | * __serialize() / __unserialize() were introduced in PHP 7.4: |
||
407 | * https://wiki.php.net/rfc/custom_object_serialization |
||
408 | * |
||
409 | * @return array |
||
410 | */ |
||
411 | public function __sleep() |
||
412 | { |
||
413 | $this->hex = $this->toHex(true); |
||
414 | $vars = ['hex']; |
||
415 | if ($this->getPrecision() > 0) { |
||
416 | $vars[] = 'precision'; |
||
417 | } |
||
418 | return $vars; |
||
419 | } |
||
420 | |||
421 | /** |
||
422 | * Serialize |
||
423 | * |
||
424 | * Will be called, automatically, when unserialize() is called on a BigInteger object. |
||
425 | */ |
||
426 | public function __wakeup() |
||
427 | { |
||
428 | $temp = new static($this->hex, -16); |
||
429 | $this->value = $temp->value; |
||
430 | if ($this->precision > 0) { |
||
431 | // recalculate $this->bitmask |
||
432 | $this->setPrecision($this->precision); |
||
433 | } |
||
434 | } |
||
435 | |||
436 | /** |
||
437 | * JSON Serialize |
||
438 | * |
||
439 | * Will be called, automatically, when json_encode() is called on a BigInteger object. |
||
1114 | daniel-mar | 440 | * |
441 | * @return array{hex: string, precision?: int] |
||
827 | daniel-mar | 442 | */ |
443 | #[\ReturnTypeWillChange] |
||
444 | public function jsonSerialize() |
||
445 | { |
||
446 | $result = ['hex' => $this->toHex(true)]; |
||
447 | if ($this->precision > 0) { |
||
448 | $result['precision'] = $this->getPrecision(); |
||
449 | } |
||
450 | return $result; |
||
451 | } |
||
452 | |||
453 | /** |
||
454 | * Performs modular exponentiation. |
||
455 | * |
||
456 | * @param BigInteger $e |
||
457 | * @param BigInteger $n |
||
458 | * @return BigInteger |
||
459 | */ |
||
460 | public function powMod(BigInteger $e, BigInteger $n) |
||
461 | { |
||
462 | return new static($this->value->powMod($e->value, $n->value)); |
||
463 | } |
||
464 | |||
465 | /** |
||
466 | * Performs modular exponentiation. |
||
467 | * |
||
468 | * @param BigInteger $e |
||
469 | * @param BigInteger $n |
||
470 | * @return BigInteger |
||
471 | */ |
||
472 | public function modPow(BigInteger $e, BigInteger $n) |
||
473 | { |
||
474 | return new static($this->value->modPow($e->value, $n->value)); |
||
475 | } |
||
476 | |||
477 | /** |
||
478 | * Compares two numbers. |
||
479 | * |
||
480 | * Although one might think !$x->compare($y) means $x != $y, it, in fact, means the opposite. The reason for this |
||
481 | * is demonstrated thusly: |
||
482 | * |
||
483 | * $x > $y: $x->compare($y) > 0 |
||
484 | * $x < $y: $x->compare($y) < 0 |
||
485 | * $x == $y: $x->compare($y) == 0 |
||
486 | * |
||
487 | * Note how the same comparison operator is used. If you want to test for equality, use $x->equals($y). |
||
488 | * |
||
489 | * {@internal Could return $this->subtract($x), but that's not as fast as what we do do.} |
||
490 | * |
||
491 | * @param BigInteger $y |
||
492 | * @return int in case < 0 if $this is less than $y; > 0 if $this is greater than $y, and 0 if they are equal. |
||
493 | * @see self::equals() |
||
494 | */ |
||
495 | public function compare(BigInteger $y) |
||
496 | { |
||
497 | return $this->value->compare($y->value); |
||
498 | } |
||
499 | |||
500 | /** |
||
501 | * Tests the equality of two numbers. |
||
502 | * |
||
503 | * If you need to see if one number is greater than or less than another number, use BigInteger::compare() |
||
504 | * |
||
505 | * @param BigInteger $x |
||
506 | * @return bool |
||
507 | */ |
||
508 | public function equals(BigInteger $x) |
||
509 | { |
||
510 | return $this->value->equals($x->value); |
||
511 | } |
||
512 | |||
513 | /** |
||
514 | * Logical Not |
||
515 | * |
||
516 | * @return BigInteger |
||
517 | */ |
||
518 | public function bitwise_not() |
||
519 | { |
||
520 | return new static($this->value->bitwise_not()); |
||
521 | } |
||
522 | |||
523 | /** |
||
524 | * Logical And |
||
525 | * |
||
526 | * @param BigInteger $x |
||
527 | * @return BigInteger |
||
528 | */ |
||
529 | public function bitwise_and(BigInteger $x) |
||
530 | { |
||
531 | return new static($this->value->bitwise_and($x->value)); |
||
532 | } |
||
533 | |||
534 | /** |
||
535 | * Logical Or |
||
536 | * |
||
537 | * @param BigInteger $x |
||
538 | * @return BigInteger |
||
539 | */ |
||
540 | public function bitwise_or(BigInteger $x) |
||
541 | { |
||
542 | return new static($this->value->bitwise_or($x->value)); |
||
543 | } |
||
544 | |||
545 | /** |
||
546 | * Logical Exclusive Or |
||
547 | * |
||
548 | * @param BigInteger $x |
||
549 | * @return BigInteger |
||
550 | */ |
||
551 | public function bitwise_xor(BigInteger $x) |
||
552 | { |
||
553 | return new static($this->value->bitwise_xor($x->value)); |
||
554 | } |
||
555 | |||
556 | /** |
||
557 | * Logical Right Shift |
||
558 | * |
||
559 | * Shifts BigInteger's by $shift bits, effectively dividing by 2**$shift. |
||
560 | * |
||
561 | * @param int $shift |
||
562 | * @return BigInteger |
||
563 | */ |
||
564 | public function bitwise_rightShift($shift) |
||
565 | { |
||
566 | return new static($this->value->bitwise_rightShift($shift)); |
||
567 | } |
||
568 | |||
569 | /** |
||
570 | * Logical Left Shift |
||
571 | * |
||
572 | * Shifts BigInteger's by $shift bits, effectively multiplying by 2**$shift. |
||
573 | * |
||
574 | * @param int $shift |
||
575 | * @return BigInteger |
||
576 | */ |
||
577 | public function bitwise_leftShift($shift) |
||
578 | { |
||
579 | return new static($this->value->bitwise_leftShift($shift)); |
||
580 | } |
||
581 | |||
582 | /** |
||
583 | * Logical Left Rotate |
||
584 | * |
||
585 | * Instead of the top x bits being dropped they're appended to the shifted bit string. |
||
586 | * |
||
587 | * @param int $shift |
||
588 | * @return BigInteger |
||
589 | */ |
||
590 | public function bitwise_leftRotate($shift) |
||
591 | { |
||
592 | return new static($this->value->bitwise_leftRotate($shift)); |
||
593 | } |
||
594 | |||
595 | /** |
||
596 | * Logical Right Rotate |
||
597 | * |
||
598 | * Instead of the bottom x bits being dropped they're prepended to the shifted bit string. |
||
599 | * |
||
600 | * @param int $shift |
||
601 | * @return BigInteger |
||
602 | */ |
||
603 | public function bitwise_rightRotate($shift) |
||
604 | { |
||
605 | return new static($this->value->bitwise_rightRotate($shift)); |
||
606 | } |
||
607 | |||
608 | /** |
||
609 | * Returns the smallest and largest n-bit number |
||
610 | * |
||
611 | * @param int $bits |
||
612 | * @return BigInteger[] |
||
613 | */ |
||
614 | public static function minMaxBits($bits) |
||
615 | { |
||
616 | self::initialize_static_variables(); |
||
617 | |||
618 | $class = self::$mainEngine; |
||
619 | extract($class::minMaxBits($bits)); |
||
620 | /** @var BigInteger $min |
||
621 | * @var BigInteger $max |
||
622 | */ |
||
623 | return [ |
||
624 | 'min' => new static($min), |
||
625 | 'max' => new static($max) |
||
626 | ]; |
||
627 | } |
||
628 | |||
629 | /** |
||
630 | * Return the size of a BigInteger in bits |
||
631 | * |
||
632 | * @return int |
||
633 | */ |
||
634 | public function getLength() |
||
635 | { |
||
636 | return $this->value->getLength(); |
||
637 | } |
||
638 | |||
639 | /** |
||
640 | * Return the size of a BigInteger in bytes |
||
641 | * |
||
642 | * @return int |
||
643 | */ |
||
644 | public function getLengthInBytes() |
||
645 | { |
||
646 | return $this->value->getLengthInBytes(); |
||
647 | } |
||
648 | |||
649 | /** |
||
650 | * Generates a random number of a certain size |
||
651 | * |
||
652 | * Bit length is equal to $size |
||
653 | * |
||
654 | * @param int $size |
||
655 | * @return BigInteger |
||
656 | */ |
||
657 | public static function random($size) |
||
658 | { |
||
659 | self::initialize_static_variables(); |
||
660 | |||
661 | $class = self::$mainEngine; |
||
662 | return new static($class::random($size)); |
||
663 | } |
||
664 | |||
665 | /** |
||
666 | * Generates a random prime number of a certain size |
||
667 | * |
||
668 | * Bit length is equal to $size |
||
669 | * |
||
670 | * @param int $size |
||
671 | * @return BigInteger |
||
672 | */ |
||
673 | public static function randomPrime($size) |
||
674 | { |
||
675 | self::initialize_static_variables(); |
||
676 | |||
677 | $class = self::$mainEngine; |
||
678 | return new static($class::randomPrime($size)); |
||
679 | } |
||
680 | |||
681 | /** |
||
682 | * Generate a random prime number between a range |
||
683 | * |
||
684 | * If there's not a prime within the given range, false will be returned. |
||
685 | * |
||
686 | * @param BigInteger $min |
||
687 | * @param BigInteger $max |
||
688 | * @return false|BigInteger |
||
689 | */ |
||
690 | public static function randomRangePrime(BigInteger $min, BigInteger $max) |
||
691 | { |
||
692 | $class = self::$mainEngine; |
||
693 | return new static($class::randomRangePrime($min->value, $max->value)); |
||
694 | } |
||
695 | |||
696 | /** |
||
697 | * Generate a random number between a range |
||
698 | * |
||
699 | * Returns a random number between $min and $max where $min and $max |
||
700 | * can be defined using one of the two methods: |
||
701 | * |
||
702 | * BigInteger::randomRange($min, $max) |
||
703 | * BigInteger::randomRange($max, $min) |
||
704 | * |
||
705 | * @param BigInteger $min |
||
706 | * @param BigInteger $max |
||
707 | * @return BigInteger |
||
708 | */ |
||
709 | public static function randomRange(BigInteger $min, BigInteger $max) |
||
710 | { |
||
711 | $class = self::$mainEngine; |
||
712 | return new static($class::randomRange($min->value, $max->value)); |
||
713 | } |
||
714 | |||
715 | /** |
||
716 | * Checks a numer to see if it's prime |
||
717 | * |
||
718 | * Assuming the $t parameter is not set, this function has an error rate of 2**-80. The main motivation for the |
||
719 | * $t parameter is distributability. BigInteger::randomPrime() can be distributed across multiple pageloads |
||
720 | * on a website instead of just one. |
||
721 | * |
||
722 | * @param int|bool $t |
||
723 | * @return bool |
||
724 | */ |
||
725 | public function isPrime($t = false) |
||
726 | { |
||
727 | return $this->value->isPrime($t); |
||
728 | } |
||
729 | |||
730 | /** |
||
731 | * Calculates the nth root of a biginteger. |
||
732 | * |
||
733 | * Returns the nth root of a positive biginteger, where n defaults to 2 |
||
734 | * |
||
735 | * @param int $n optional |
||
736 | * @return BigInteger |
||
737 | */ |
||
738 | public function root($n = 2) |
||
739 | { |
||
740 | return new static($this->value->root($n)); |
||
741 | } |
||
742 | |||
743 | /** |
||
744 | * Performs exponentiation. |
||
745 | * |
||
746 | * @param BigInteger $n |
||
747 | * @return BigInteger |
||
748 | */ |
||
749 | public function pow(BigInteger $n) |
||
750 | { |
||
751 | return new static($this->value->pow($n->value)); |
||
752 | } |
||
753 | |||
754 | /** |
||
755 | * Return the minimum BigInteger between an arbitrary number of BigIntegers. |
||
756 | * |
||
757 | * @param BigInteger ...$nums |
||
758 | * @return BigInteger |
||
759 | */ |
||
760 | public static function min(BigInteger ...$nums) |
||
761 | { |
||
762 | $class = self::$mainEngine; |
||
763 | $nums = array_map(function ($num) { |
||
764 | return $num->value; |
||
765 | }, $nums); |
||
766 | return new static($class::min(...$nums)); |
||
767 | } |
||
768 | |||
769 | /** |
||
770 | * Return the maximum BigInteger between an arbitrary number of BigIntegers. |
||
771 | * |
||
772 | * @param BigInteger ...$nums |
||
773 | * @return BigInteger |
||
774 | */ |
||
775 | public static function max(BigInteger ...$nums) |
||
776 | { |
||
777 | $class = self::$mainEngine; |
||
778 | $nums = array_map(function ($num) { |
||
779 | return $num->value; |
||
780 | }, $nums); |
||
781 | return new static($class::max(...$nums)); |
||
782 | } |
||
783 | |||
784 | /** |
||
785 | * Tests BigInteger to see if it is between two integers, inclusive |
||
786 | * |
||
787 | * @param BigInteger $min |
||
788 | * @param BigInteger $max |
||
789 | * @return bool |
||
790 | */ |
||
791 | public function between(BigInteger $min, BigInteger $max) |
||
792 | { |
||
793 | return $this->value->between($min->value, $max->value); |
||
794 | } |
||
795 | |||
796 | /** |
||
797 | * Clone |
||
798 | */ |
||
799 | public function __clone() |
||
800 | { |
||
801 | $this->value = clone $this->value; |
||
802 | } |
||
803 | |||
804 | /** |
||
805 | * Is Odd? |
||
806 | * |
||
807 | * @return bool |
||
808 | */ |
||
809 | public function isOdd() |
||
810 | { |
||
811 | return $this->value->isOdd(); |
||
812 | } |
||
813 | |||
814 | /** |
||
815 | * Tests if a bit is set |
||
816 | * |
||
817 | * @param int $x |
||
818 | * @return bool |
||
819 | */ |
||
820 | public function testBit($x) |
||
821 | { |
||
822 | return $this->value->testBit($x); |
||
823 | } |
||
824 | |||
825 | /** |
||
826 | * Is Negative? |
||
827 | * |
||
828 | * @return bool |
||
829 | */ |
||
830 | public function isNegative() |
||
831 | { |
||
832 | return $this->value->isNegative(); |
||
833 | } |
||
834 | |||
835 | /** |
||
836 | * Negate |
||
837 | * |
||
838 | * Given $k, returns -$k |
||
839 | * |
||
840 | * @return BigInteger |
||
841 | */ |
||
842 | public function negate() |
||
843 | { |
||
844 | return new static($this->value->negate()); |
||
845 | } |
||
846 | |||
847 | /** |
||
848 | * Scan for 1 and right shift by that amount |
||
849 | * |
||
850 | * ie. $s = gmp_scan1($n, 0) and $r = gmp_div_q($n, gmp_pow(gmp_init('2'), $s)); |
||
851 | * |
||
852 | * @param BigInteger $r |
||
853 | * @return int |
||
854 | */ |
||
855 | public static function scan1divide(BigInteger $r) |
||
856 | { |
||
857 | $class = self::$mainEngine; |
||
858 | return $class::scan1divide($r->value); |
||
859 | } |
||
860 | |||
861 | /** |
||
862 | * Create Recurring Modulo Function |
||
863 | * |
||
864 | * Sometimes it may be desirable to do repeated modulos with the same number outside of |
||
865 | * modular exponentiation |
||
866 | * |
||
867 | * @return callable |
||
868 | */ |
||
869 | public function createRecurringModuloFunction() |
||
870 | { |
||
871 | $func = $this->value->createRecurringModuloFunction(); |
||
872 | return function (BigInteger $x) use ($func) { |
||
873 | return new static($func($x->value)); |
||
874 | }; |
||
875 | } |
||
876 | |||
877 | /** |
||
878 | * Bitwise Split |
||
879 | * |
||
880 | * Splits BigInteger's into chunks of $split bits |
||
881 | * |
||
882 | * @param int $split |
||
883 | * @return BigInteger[] |
||
884 | */ |
||
885 | public function bitwise_split($split) |
||
886 | { |
||
887 | return array_map(function ($val) { |
||
888 | return new static($val); |
||
889 | }, $this->value->bitwise_split($split)); |
||
890 | } |
||
1114 | daniel-mar | 891 | } |