Failed Conditions
Push — analysis-zYOGLy ( 0d6226 )
by Florent
09:58 queued 05:42
created

src/Util/BigInteger.php (1 issue)

Severity

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
/*
4
 * The MIT License (MIT)
5
 *
6
 * Copyright (c) 2014-2016 Spomky-Labs
7
 *
8
 * This software may be modified and distributed under the terms
9
 * of the MIT license.  See the LICENSE file for details.
10
 */
11
12
namespace Jose\Util;
13
14
class BigInteger
15
{
16
    const MONTGOMERY = 0;
17
18
    const BARRETT = 1;
19
20
    const POWEROF2 = 2;
21
22
    const CLASSIC = 3;
23
24
    const NONE = 4;
25
26
    /**#@+
27
     * Array constants
28
     *
29
     * Rather than create a thousands and thousands of new BigInteger objects in repeated function calls to add() and
30
     * multiply() or whatever, we'll just work directly on arrays, taking them in as parameters and returning them.
31
     *
32
     */
33
    /**
34
     * $result[self::VALUE] contains the value.
35
     */
36
    const VALUE = 0;
37
    /**
38
     * $result[self::SIGN] contains the sign.
39
     */
40
    const SIGN = 1;
41
    /**#@-*/
42
43
    /**#@+
44
     */
45
    /**
46
     * Cache constants.
47
     *
48
     * $cache[self::VARIABLE] tells us whether or not the cached data is still valid.
49
     */
50
    const VARIABLE = 0;
51
    /**
52
     * $cache[self::DATA] contains the cached data.
53
     */
54
    const DATA = 1;
55
    /**#@-*/
56
57
    /**#@+
58
     * Mode constants.
59
     *
60
     */
61
    /**
62
     * To use the pure-PHP implementation.
63
     */
64
    const MODE_INTERNAL = 1;
65
    /**
66
     * To use the BCMath library.
67
     *
68
     * (if enabled; otherwise, the internal implementation will be used)
69
     */
70
    const MODE_BCMATH = 2;
71
    /**
72
     * To use the GMP library.
73
     *
74
     * (if present; otherwise, either the BCMath or the internal implementation will be used)
75
     */
76
    const MODE_GMP = 3;
77
    /**#@-*/
78
79
    /**
80
     * Karatsuba Cutoff.
81
     *
82
     * At what point do we switch between Karatsuba multiplication and schoolbook long multiplication?
83
     */
84
    const KARATSUBA_CUTOFF = 25;
85
86
    /**#@+
87
     * Static properties used by the pure-PHP implementation.
88
     *
89
     * @see __construct()
90
     */
91
    protected static $base;
92
    protected static $baseFull;
93
    protected static $maxDigit;
94
    protected static $msb;
95
96
    /**
97
     * $max10 in greatest $max10Len satisfying
98
     * $max10 = 10**$max10Len <= 2**$base.
99
     */
100
    protected static $max10;
101
102
    /**
103
     * $max10Len in greatest $max10Len satisfying
104
     * $max10 = 10**$max10Len <= 2**$base.
105
     */
106
    protected static $max10Len;
107
    protected static $maxDigit2;
108
    /**#@-*/
109
110
    /**
111
     * Holds the BigInteger's value.
112
     *
113
     * @var array
114
     */
115
    private $value;
116
117
    /**
118
     * Holds the BigInteger's magnitude.
119
     *
120
     * @var bool
121
     */
122
    private $is_negative = false;
123
124
    /**
125
     * Precision.
126
     */
127
    private $precision = -1;
128
129
    /**
130
     * Precision Bitmask.
131
     */
132
    private $bitmask = false;
133
134
    /**
135
     * Mode independent value used for serialization.
136
     *
137
     * If the bcmath or gmp extensions are installed $this->value will be a non-serializable resource, hence the need for
138
     * a variable that'll be serializable regardless of whether or not extensions are being used.  Unlike $this->value,
139
     * however, $this->hex is only calculated when $this->__sleep() is called.
140
     *
141
     * @var string
142
     */
143
    private $hex;
144
145
    /**
146
     * Converts base-2, base-10, base-16, and binary strings (base-256) to BigIntegers.
147
     *
148
     * If the second parameter - $base - is negative, then it will be assumed that the number's are encoded using
149
     * two's compliment.  The sole exception to this is -10, which is treated the same as 10 is.
150
     *
151
     * Here's an example:
152
     * <code>
153
     * <?php
154
     *    $a = new \Jose\Util\in base-16
155
     *
156
     *    echo $a->toString(); // outputs 50
157
     * ?>
158
     * </code>
159
     *
160
     * @param $x base-10 number or base-$base number if $base set.
161
     * @param int $base
162
     *
163
     * @return \Jose\Util\BigInteger
164
     */
165
    public function __construct($x = 0, $base = 10)
166
    {
167
        if (!defined('MATH_BIGINTEGER_MODE')) {
168
            switch (true) {
169
                case extension_loaded('gmp'):
170
                    define('MATH_BIGINTEGER_MODE', self::MODE_GMP);
171
                    break;
172
                case extension_loaded('bcmath'):
173
                    define('MATH_BIGINTEGER_MODE', self::MODE_BCMATH);
174
                    break;
175
                default:
176
                    define('MATH_BIGINTEGER_MODE', self::MODE_INTERNAL);
177
            }
178
        }
179
180
        if (extension_loaded('openssl') && !defined('MATH_BIGINTEGER_OPENSSL_DISABLE') && !defined('MATH_BIGINTEGER_OPENSSL_ENABLED')) {
181
            define('MATH_BIGINTEGER_OPENSSL_ENABLED', true);
182
        }
183
184
        if (!defined('PHP_INT_SIZE')) {
185
            define('PHP_INT_SIZE', 4);
186
        }
187
188
        if (empty(self::$base) && MATH_BIGINTEGER_MODE == self::MODE_INTERNAL) {
189
            switch (PHP_INT_SIZE) {
190
                case 8: // use 64-bit integers if int size is 8 bytes
191
                    self::$base = 31;
192
                    self::$baseFull = 0x80000000;
193
                    self::$maxDigit = 0x7FFFFFFF;
194
                    self::$msb = 0x40000000;
195
                    self::$max10 = 1000000000;
196
                    self::$max10Len = 9;
197
                    self::$maxDigit2 = pow(2, 62);
198
                    break;
199
                //case 4: // use 64-bit floats if int size is 4 bytes
200
                default:
201
                    self::$base = 26;
202
                    self::$baseFull = 0x4000000;
203
                    self::$maxDigit = 0x3FFFFFF;
204
                    self::$msb = 0x2000000;
205
                    self::$max10 = 10000000;
206
                    self::$max10Len = 7;
207
                    self::$maxDigit2 = pow(2, 52); // pow() prevents truncation
208
            }
209
        }
210
211
        switch (MATH_BIGINTEGER_MODE) {
212
            case self::MODE_GMP:
213
                switch (true) {
214
                    case is_resource($x) && get_resource_type($x) == 'GMP integer':
215
                        // PHP 5.6 switched GMP from using resources to objects
216
                    case $x instanceof \GMP:
217
                        $this->value = $x;
218
219
                        return;
220
                }
221
                $this->value = gmp_init(0);
222
                break;
223
            case self::MODE_BCMATH:
224
                $this->value = '0';
225
                break;
226
            default:
227
                $this->value = [];
228
        }
229
230
        // '0' counts as empty() but when the base is 256 '0' is equal to ord('0') or 48
231
        // '0' is the only value like this per http://php.net/empty
232
        if (empty($x) && (abs($base) != 256 || $x !== '0')) {
233
            return;
234
        }
235
236
        switch ($base) {
237
            case -256:
238
                if (ord($x[0]) & 0x80) {
239
                    $x = ~$x;
240
                    $this->is_negative = true;
241
                }
242
            case 256:
243
                switch (MATH_BIGINTEGER_MODE) {
244
                    case self::MODE_GMP:
245
                        $sign = $this->is_negative ? '-' : '';
246
                        $this->value = gmp_init($sign.'0x'.bin2hex($x));
247
                        break;
248
                    case self::MODE_BCMATH:
249
                        // round $len to the nearest 4 (thanks, DavidMJ!)
250
                        $len = (strlen($x) + 3) & 0xFFFFFFFC;
251
252
                        $x = str_pad($x, $len, chr(0), STR_PAD_LEFT);
253
254
                        for ($i = 0; $i < $len; $i += 4) {
255
                            $this->value = bcmul($this->value, '4294967296', 0); // 4294967296 == 2**32
256
                            $this->value = bcadd($this->value, 0x1000000 * ord($x[$i]) + ((ord($x[$i + 1]) << 16) | (ord($x[$i + 2]) << 8) | ord($x[$i + 3])), 0);
257
                        }
258
259
                        if ($this->is_negative) {
260
                            $this->value = '-'.$this->value;
261
                        }
262
263
                        break;
264
                    // converts a base-2**8 (big endian / msb) number to base-2**26 (little endian / lsb)
265
                    default:
266
                        while (strlen($x)) {
267
                            $this->value[] = $this->_bytes2int($this->_base256_rshift($x, self::$base));
268
                        }
269
                }
270
271
                if ($this->is_negative) {
272
                    if (MATH_BIGINTEGER_MODE != self::MODE_INTERNAL) {
273
                        $this->is_negative = false;
274
                    }
275
                    $temp = $this->add(new static('-1'));
276
                    $this->value = $temp->value;
277
                }
278
                break;
279
            case 16:
280
            case -16:
281
                if ($base > 0 && $x[0] == '-') {
282
                    $this->is_negative = true;
283
                    $x = substr($x, 1);
284
                }
285
286
                $x = preg_replace('#^(?:0x)?([A-Fa-f0-9]*).*#', '$1', $x);
287
288
                $is_negative = false;
289
                if ($base < 0 && hexdec($x[0]) >= 8) {
290
                    $this->is_negative = $is_negative = true;
291
                    $x = bin2hex(~hex2bin($x));
292
                }
293
294
                switch (MATH_BIGINTEGER_MODE) {
295
                    case self::MODE_GMP:
296
                        $temp = $this->is_negative ? '-0x'.$x : '0x'.$x;
297
                        $this->value = gmp_init($temp);
298
                        $this->is_negative = false;
299
                        break;
300
                    case self::MODE_BCMATH:
301
                        $x = (strlen($x) & 1) ? '0'.$x : $x;
302
                        $temp = new static(hex2bin($x), 256);
303
                        $this->value = $this->is_negative ? '-'.$temp->value : $temp->value;
304
                        $this->is_negative = false;
305
                        break;
306
                    default:
307
                        $x = (strlen($x) & 1) ? '0'.$x : $x;
308
                        $temp = new static(hex2bin($x), 256);
309
                        $this->value = $temp->value;
310
                }
311
312
                if ($is_negative) {
313
                    $temp = $this->add(new static('-1'));
314
                    $this->value = $temp->value;
315
                }
316
                break;
317
            case 10:
318
            case -10:
319
                // (?<!^)(?:-).*: find any -'s that aren't at the beginning and then any characters that follow that
320
                // (?<=^|-)0*: find any 0's that are preceded by the start of the string or by a - (ie. octals)
321
                // [^-0-9].*: find any non-numeric characters and then any characters that follow that
322
                $x = preg_replace('#(?<!^)(?:-).*|(?<=^|-)0*|[^-0-9].*#', '', $x);
323
324
                switch (MATH_BIGINTEGER_MODE) {
325
                    case self::MODE_GMP:
326
                        $this->value = gmp_init($x);
327
                        break;
328
                    case self::MODE_BCMATH:
329
                        // explicitly casting $x to a string is necessary, here, since doing $x[0] on -1 yields different
330
                        // results then doing it on '-1' does (modInverse does $x[0])
331
                        $this->value = $x === '-' ? '0' : (string) $x;
332
                        break;
333
                    default:
334
                        $temp = new static();
335
336
                        $multiplier = new static();
337
                        $multiplier->value = [self::$max10];
338
339
                        if ($x[0] == '-') {
340
                            $this->is_negative = true;
341
                            $x = substr($x, 1);
342
                        }
343
344
                        $x = str_pad($x, strlen($x) + ((self::$max10Len - 1) * strlen($x)) % self::$max10Len, 0, STR_PAD_LEFT);
345
                        while (strlen($x)) {
346
                            $temp = $temp->multiply($multiplier);
347
                            $temp = $temp->add(new static($this->_int2bytes(substr($x, 0, self::$max10Len)), 256));
348
                            $x = substr($x, self::$max10Len);
349
                        }
350
351
                        $this->value = $temp->value;
352
                }
353
                break;
354
            case 2: // base-2 support originally implemented by Lluis Pamies - thanks!
355
            case -2:
356
                if ($base > 0 && $x[0] == '-') {
357
                    $this->is_negative = true;
358
                    $x = substr($x, 1);
359
                }
360
361
                $x = preg_replace('#^([01]*).*#', '$1', $x);
362
                $x = str_pad($x, strlen($x) + (3 * strlen($x)) % 4, 0, STR_PAD_LEFT);
363
364
                $str = '0x';
365
                while (strlen($x)) {
366
                    $part = substr($x, 0, 4);
367
                    $str .= dechex(bindec($part));
368
                    $x = substr($x, 4);
369
                }
370
371
                if ($this->is_negative) {
372
                    $str = '-'.$str;
373
                }
374
375
                $temp = new static($str, 8 * $base); // ie. either -16 or +16
376
                $this->value = $temp->value;
377
                $this->is_negative = $temp->is_negative;
378
379
                break;
380
            default:
381
                // base not supported, so we'll let $this == 0
382
        }
383
    }
384
385
    /**
386
     * Converts a BigInteger to a byte string (eg. base-256).
387
     *
388
     * Negative numbers are saved as positive numbers, unless $twos_compliment is set to true, at which point, they're
389
     * saved as two's compliment.
390
     *
391
     * Here's an example:
392
     * <code>
393
     * <?php
394
     *    $a = new \Jose\Util\ger('65');
395
     *
396
     *    echo $a->toBytes(); // outputs chr(65)
397
     * ?>
398
     * </code>
399
     *
400
     * @param bool $twos_compliment
401
     *
402
     * @return string
403
     *
404
     * @internal Converts a base-2**26 number to base-2**8
405
     */
406
    public function toBytes($twos_compliment = false)
407
    {
408
        if ($twos_compliment) {
409
            $comparison = $this->compare(new static());
410
            if ($comparison == 0) {
411
                return $this->precision > 0 ? str_repeat(chr(0), ($this->precision + 1) >> 3) : '';
412
            }
413
414
            $temp = $comparison < 0 ? $this->add(new static(1)) : $this;
415
            $bytes = $temp->toBytes();
416
417
            if (empty($bytes)) { // eg. if the number we're trying to convert is -1
418
                $bytes = chr(0);
419
            }
420
421
            if (ord($bytes[0]) & 0x80) {
422
                $bytes = chr(0).$bytes;
423
            }
424
425
            return $comparison < 0 ? ~$bytes : $bytes;
426
        }
427
428
        switch (MATH_BIGINTEGER_MODE) {
429
            case self::MODE_GMP:
430
                if (gmp_cmp($this->value, gmp_init(0)) == 0) {
431
                    return $this->precision > 0 ? str_repeat(chr(0), ($this->precision + 1) >> 3) : '';
432
                }
433
434
                $temp = gmp_strval(gmp_abs($this->value), 16);
435
                $temp = (strlen($temp) & 1) ? '0'.$temp : $temp;
436
                $temp = hex2bin($temp);
437
438
                return $this->precision > 0 ?
439
                    substr(str_pad($temp, $this->precision >> 3, chr(0), STR_PAD_LEFT), -($this->precision >> 3)) :
440
                    ltrim($temp, chr(0));
441
            case self::MODE_BCMATH:
442
                if ($this->value === '0') {
443
                    return $this->precision > 0 ? str_repeat(chr(0), ($this->precision + 1) >> 3) : '';
444
                }
445
446
                $value = '';
447
                $current = $this->value;
448
449
                if ($current[0] == '-') {
450
                    $current = substr($current, 1);
451
                }
452
453
                while (bccomp($current, '0', 0) > 0) {
454
                    $temp = bcmod($current, '16777216');
455
                    $value = chr($temp >> 16).chr($temp >> 8).chr($temp).$value;
456
                    $current = bcdiv($current, '16777216', 0);
457
                }
458
459
                return $this->precision > 0 ?
460
                    substr(str_pad($value, $this->precision >> 3, chr(0), STR_PAD_LEFT), -($this->precision >> 3)) :
461
                    ltrim($value, chr(0));
462
        }
463
464
        if (!count($this->value)) {
465
            return $this->precision > 0 ? str_repeat(chr(0), ($this->precision + 1) >> 3) : '';
466
        }
467
        $result = self::_int2bytes($this->value[count($this->value) - 1]);
468
469
        for ($i = count($this->value) - 2; $i >= 0; --$i) {
470
            self::_base256_lshift($result, self::$base);
471
            $result = $result | str_pad(self::_int2bytes($this->value[$i]), strlen($result), chr(0), STR_PAD_LEFT);
472
        }
473
474
        return $this->precision > 0 ?
475
            str_pad(substr($result, -(($this->precision + 7) >> 3)), ($this->precision + 7) >> 3, chr(0), STR_PAD_LEFT) :
476
            $result;
477
    }
478
479
    /**
480
     * Converts a BigInteger to a hex string (eg. base-16)).
481
     *
482
     * Negative numbers are saved as positive numbers, unless $twos_compliment is set to true, at which point, they're
483
     * saved as two's compliment.
484
     *
485
     * Here's an example:
486
     * <code>
487
     * <?php
488
     *    $a = new \Jose\Util\ger('65');
489
     *
490
     *    echo $a->toHex(); // outputs '41'
491
     * ?>
492
     * </code>
493
     *
494
     * @param bool $twos_compliment
495
     *
496
     * @return string
497
     *
498
     * @internal Converts a base-2**26 number to base-2**8
499
     */
500
    public function toHex($twos_compliment = false)
501
    {
502
        return bin2hex($this->toBytes($twos_compliment));
503
    }
504
505
    /**
506
     * Converts a BigInteger to a bit string (eg. base-2).
507
     *
508
     * Negative numbers are saved as positive numbers, unless $twos_compliment is set to true, at which point, they're
509
     * saved as two's compliment.
510
     *
511
     * Here's an example:
512
     * <code>
513
     * <?php
514
     *    $a = new \Jose\Util\ger('65');
515
     *
516
     *    echo $a->toBits(); // outputs '1000001'
517
     * ?>
518
     * </code>
519
     *
520
     * @param bool $twos_compliment
521
     *
522
     * @return string
523
     *
524
     * @internal Converts a base-2**26 number to base-2**2
525
     */
526
    public function toBits($twos_compliment = false)
527
    {
528
        $hex = $this->toHex($twos_compliment);
529
        $bits = '';
530
        for ($i = strlen($hex) - 8, $start = strlen($hex) & 7; $i >= $start; $i -= 8) {
531
            $bits = str_pad(decbin(hexdec(substr($hex, $i, 8))), 32, '0', STR_PAD_LEFT).$bits;
532
        }
533
        if ($start) { // hexdec('') == 0
534
            $bits = str_pad(decbin(hexdec(substr($hex, 0, $start))), 8, '0', STR_PAD_LEFT).$bits;
535
        }
536
        $result = $this->precision > 0 ? substr($bits, -$this->precision) : ltrim($bits, '0');
537
538
        if ($twos_compliment && $this->compare(new static()) > 0 && $this->precision <= 0) {
539
            return '0'.$result;
540
        }
541
542
        return $result;
543
    }
544
545
    /**
546
     * Converts a BigInteger to a base-10 number.
547
     *
548
     * Here's an example:
549
     * <code>
550
     * <?php
551
     *    $a = new \Jose\Util\ger('50');
552
     *
553
     *    echo $a->toString(); // outputs 50
554
     * ?>
555
     * </code>
556
     *
557
     * @return string
558
     *
559
     * @internal Converts a base-2**26 number to base-10**7 (which is pretty much base-10)
560
     */
561
    public function toString()
562
    {
563
        switch (MATH_BIGINTEGER_MODE) {
564
            case self::MODE_GMP:
565
                return gmp_strval($this->value);
566
            case self::MODE_BCMATH:
567
                if ($this->value === '0') {
568
                    return '0';
569
                }
570
571
                return ltrim($this->value, '0');
572
        }
573
574
        if (!count($this->value)) {
575
            return '0';
576
        }
577
578
        $temp = clone $this;
579
        $temp->is_negative = false;
580
581
        $divisor = new static();
582
        $divisor->value = [self::$max10];
583
        $result = '';
584
        while (count($temp->value)) {
585
            list($temp, $mod) = $temp->divide($divisor);
586
            $result = str_pad(isset($mod->value[0]) ? $mod->value[0] : '', self::$max10Len, '0', STR_PAD_LEFT).$result;
587
        }
588
        $result = ltrim($result, '0');
589
        if (empty($result)) {
590
            $result = '0';
591
        }
592
593
        if ($this->is_negative) {
594
            $result = '-'.$result;
595
        }
596
597
        return $result;
598
    }
599
600
    /**
601
     *  __toString() magic method.
602
     *
603
     * Will be called, automatically, if you're supporting just PHP5.  If you're supporting PHP4, you'll need to call
604
     * toString().
605
     *
606
     * @internal Implemented per a suggestion by Techie-Michael - thanks!
607
     */
608
    public function __toString()
609
    {
610
        return $this->toString();
611
    }
612
613
    /**
614
     *  __sleep() magic method.
615
     *
616
     * Will be called, automatically, when serialize() is called on a BigInteger object.
617
     */
618
    public function __sleep()
619
    {
620
        $this->hex = $this->toHex(true);
621
        $vars = ['hex'];
622
        if ($this->precision > 0) {
623
            $vars[] = 'precision';
624
        }
625
626
        return $vars;
627
    }
628
629
    /**
630
     *  __wakeup() magic method.
631
     *
632
     * Will be called, automatically, when unserialize() is called on a BigInteger object.
633
     */
634
    private function __wakeup()
635
    {
636
        $temp = new static($this->hex, -16);
637
        $this->value = $temp->value;
638
        $this->is_negative = $temp->is_negative;
639
        if ($this->precision > 0) {
640
            // recalculate $this->bitmask
641
            $this->setPrecision($this->precision);
642
        }
643
    }
644
645
    /**
646
     *  __debugInfo() magic method.
647
     *
648
     * Will be called, automatically, when print_r() or var_dump() are called
649
     */
650
    public function __debugInfo()
651
    {
652
        $opts = [];
653
        switch (MATH_BIGINTEGER_MODE) {
654
            case self::MODE_GMP:
655
                $engine = 'gmp';
656
                break;
657
            case self::MODE_BCMATH:
658
                $engine = 'bcmath';
659
                break;
660
            case self::MODE_INTERNAL:
661
                $engine = 'internal';
662
                $opts[] = PHP_INT_SIZE == 8 ? '64-bit' : '32-bit';
663
        }
664
        if (MATH_BIGINTEGER_MODE != self::MODE_GMP && defined('MATH_BIGINTEGER_OPENSSL_ENABLED')) {
665
            $opts[] = 'OpenSSL';
666
        }
667
        if (!empty($opts)) {
668
            $engine .= ' ('.implode($opts, ', ').')';
669
        }
670
671
        return [
672
            'value'  => '0x'.$this->toHex(true),
673
            'engine' => $engine,
674
        ];
675
    }
676
677
    /**
678
     * Adds two BigIntegers.
679
     *
680
     * Here's an example:
681
     * <code>
682
     * <?php
683
     *    $a = new \Jose\Util\ger('10');
684
     *    $b = new \Jose\Util\ger('20');
685
     *
686
     *    $c = $a->add($b);
687
     *
688
     *    echo $c->toString(); // outputs 30
689
     * ?>
690
     * </code>
691
     *
692
     * @param \Jose\Util\Integer $y
693
     *
694
     * @return \Jose\Util\BigInteger
695
     *
696
     * @internal Performs base-2**52 addition
697
     */
698
    public function add(BigInteger $y)
699
    {
700
        switch (MATH_BIGINTEGER_MODE) {
701
            case self::MODE_GMP:
702
                $temp = new static();
703
                $temp->value = gmp_add($this->value, $y->value);
704
705
                return $this->_normalize($temp);
706
            case self::MODE_BCMATH:
707
                $temp = new static();
708
                $temp->value = bcadd($this->value, $y->value, 0);
709
710
                return $this->_normalize($temp);
711
        }
712
713
        $temp = self::_add($this->value, $this->is_negative, $y->value, $y->is_negative);
714
715
        $result = new static();
716
        $result->value = $temp[self::VALUE];
717
        $result->is_negative = $temp[self::SIGN];
718
719
        return $this->_normalize($result);
720
    }
721
722
    /**
723
     * Performs addition.
724
     *
725
     * @param array $x_value
726
     * @param bool  $x_negative
727
     * @param array $y_value
728
     * @param bool  $y_negative
729
     *
730
     * @return array
731
     */
732
    private static function _add($x_value, $x_negative, $y_value, $y_negative)
733
    {
734
        $x_size = count($x_value);
735
        $y_size = count($y_value);
736
737
        if ($x_size == 0) {
738
            return [
739
                self::VALUE => $y_value,
740
                self::SIGN  => $y_negative,
741
            ];
742
        } elseif ($y_size == 0) {
743
            return [
744
                self::VALUE => $x_value,
745
                self::SIGN  => $x_negative,
746
            ];
747
        }
748
749
        // subtract, if appropriate
750
        if ($x_negative != $y_negative) {
751
            if ($x_value == $y_value) {
752
                return [
753
                    self::VALUE => [],
754
                    self::SIGN  => false,
755
                ];
756
            }
757
758
            $temp = self::_subtract($x_value, false, $y_value, false);
759
            $temp[self::SIGN] = self::_compare($x_value, false, $y_value, false) > 0 ?
760
                $x_negative : $y_negative;
761
762
            return $temp;
763
        }
764
765
        if ($x_size < $y_size) {
766
            $size = $x_size;
767
            $value = $y_value;
768
        } else {
769
            $size = $y_size;
770
            $value = $x_value;
771
        }
772
773
        $value[count($value)] = 0; // just in case the carry adds an extra digit
774
775
        $carry = 0;
776
        for ($i = 0, $j = 1; $j < $size; $i += 2, $j += 2) {
777
            $sum = $x_value[$j] * self::$baseFull + $x_value[$i] + $y_value[$j] * self::$baseFull + $y_value[$i] + $carry;
778
            $carry = $sum >= self::$maxDigit2; // eg. floor($sum / 2**52); only possible values (in any base) are 0 and 1
779
            $sum = $carry ? $sum - self::$maxDigit2 : $sum;
780
781
            $temp = self::$base === 26 ? intval($sum / 0x4000000) : ($sum >> 31);
782
783
            $value[$i] = (int) ($sum - self::$baseFull * $temp); // eg. a faster alternative to fmod($sum, 0x4000000)
784
            $value[$j] = $temp;
785
        }
786
787
        if ($j == $size) { // ie. if $y_size is odd
788
            $sum = $x_value[$i] + $y_value[$i] + $carry;
789
            $carry = $sum >= self::$baseFull;
790
            $value[$i] = $carry ? $sum - self::$baseFull : $sum;
791
            ++$i; // ie. let $i = $j since we've just done $value[$i]
792
        }
793
794
        if ($carry) {
795
            for (; $value[$i] == self::$maxDigit; ++$i) {
796
                $value[$i] = 0;
797
            }
798
            ++$value[$i];
799
        }
800
801
        return [
802
            self::VALUE => self::_trim($value),
803
            self::SIGN  => $x_negative,
804
        ];
805
    }
806
807
    /**
808
     * Subtracts two BigIntegers.
809
     *
810
     * Here's an example:
811
     * <code>
812
     * <?php
813
     *    $a = new \Jose\Util\ger('10');
814
     *    $b = new \Jose\Util\ger('20');
815
     *
816
     *    $c = $a->subtract($b);
817
     *
818
     *    echo $c->toString(); // outputs -10
819
     * ?>
820
     * </code>
821
     *
822
     * @param \Jose\Util\Integer $y
823
     *
824
     * @return \Jose\Util\BigInteger
825
     *
826
     * @internal Performs base-2**52 subtraction
827
     */
828
    public function subtract(BigInteger $y)
829
    {
830
        switch (MATH_BIGINTEGER_MODE) {
831
            case self::MODE_GMP:
832
                $temp = new static();
833
                $temp->value = gmp_sub($this->value, $y->value);
834
835
                return $this->_normalize($temp);
836
            case self::MODE_BCMATH:
837
                $temp = new static();
838
                $temp->value = bcsub($this->value, $y->value, 0);
839
840
                return $this->_normalize($temp);
841
        }
842
843
        $temp = self::_subtract($this->value, $this->is_negative, $y->value, $y->is_negative);
844
845
        $result = new static();
846
        $result->value = $temp[self::VALUE];
847
        $result->is_negative = $temp[self::SIGN];
848
849
        return $this->_normalize($result);
850
    }
851
852
    /**
853
     * Performs subtraction.
854
     *
855
     * @param array $x_value
856
     * @param bool  $x_negative
857
     * @param array $y_value
858
     * @param bool  $y_negative
859
     *
860
     * @return array
861
     */
862
    private static function _subtract($x_value, $x_negative, $y_value, $y_negative)
863
    {
864
        $x_size = count($x_value);
865
        $y_size = count($y_value);
866
867
        if ($x_size == 0) {
868
            return [
869
                self::VALUE => $y_value,
870
                self::SIGN  => !$y_negative,
871
            ];
872
        } elseif ($y_size == 0) {
873
            return [
874
                self::VALUE => $x_value,
875
                self::SIGN  => $x_negative,
876
            ];
877
        }
878
879
        // add, if appropriate (ie. -$x - +$y or +$x - -$y)
880
        if ($x_negative != $y_negative) {
881
            $temp = self::_add($x_value, false, $y_value, false);
882
            $temp[self::SIGN] = $x_negative;
883
884
            return $temp;
885
        }
886
887
        $diff = self::_compare($x_value, $x_negative, $y_value, $y_negative);
888
889
        if (!$diff) {
890
            return [
891
                self::VALUE => [],
892
                self::SIGN  => false,
893
            ];
894
        }
895
896
        // switch $x and $y around, if appropriate.
897
        if ((!$x_negative && $diff < 0) || ($x_negative && $diff > 0)) {
898
            $temp = $x_value;
899
            $x_value = $y_value;
900
            $y_value = $temp;
901
902
            $x_negative = !$x_negative;
903
904
            $x_size = count($x_value);
905
            $y_size = count($y_value);
906
        }
907
908
        // at this point, $x_value should be at least as big as - if not bigger than - $y_value
909
910
        $carry = 0;
911
        for ($i = 0, $j = 1; $j < $y_size; $i += 2, $j += 2) {
912
            $sum = $x_value[$j] * self::$baseFull + $x_value[$i] - $y_value[$j] * self::$baseFull - $y_value[$i] - $carry;
913
            $carry = $sum < 0; // eg. floor($sum / 2**52); only possible values (in any base) are 0 and 1
914
            $sum = $carry ? $sum + self::$maxDigit2 : $sum;
915
916
            $temp = self::$base === 26 ? intval($sum / 0x4000000) : ($sum >> 31);
917
918
            $x_value[$i] = (int) ($sum - self::$baseFull * $temp);
919
            $x_value[$j] = $temp;
920
        }
921
922
        if ($j == $y_size) { // ie. if $y_size is odd
923
            $sum = $x_value[$i] - $y_value[$i] - $carry;
924
            $carry = $sum < 0;
925
            $x_value[$i] = $carry ? $sum + self::$baseFull : $sum;
926
            ++$i;
927
        }
928
929
        if ($carry) {
930
            for (; !$x_value[$i]; ++$i) {
931
                $x_value[$i] = self::$maxDigit;
932
            }
933
            --$x_value[$i];
934
        }
935
936
        return [
937
            self::VALUE => self::_trim($x_value),
938
            self::SIGN  => $x_negative,
939
        ];
940
    }
941
942
    /**
943
     * Multiplies two BigIntegers.
944
     *
945
     * Here's an example:
946
     * <code>
947
     * <?php
948
     *    $a = new \Jose\Util\ger('10');
949
     *    $b = new \Jose\Util\ger('20');
950
     *
951
     *    $c = $a->multiply($b);
952
     *
953
     *    echo $c->toString(); // outputs 200
954
     * ?>
955
     * </code>
956
     *
957
     * @param \Jose\Util\Integer $x
958
     *
959
     * @return \Jose\Util\BigInteger
960
     */
961
    public function multiply(BigInteger $x)
962
    {
963
        switch (MATH_BIGINTEGER_MODE) {
964
            case self::MODE_GMP:
965
                $temp = new static();
966
                $temp->value = gmp_mul($this->value, $x->value);
967
968
                return $this->_normalize($temp);
969
            case self::MODE_BCMATH:
970
                $temp = new static();
971
                $temp->value = bcmul($this->value, $x->value, 0);
972
973
                return $this->_normalize($temp);
974
        }
975
976
        $temp = self::_multiply($this->value, $this->is_negative, $x->value, $x->is_negative);
977
978
        $product = new static();
979
        $product->value = $temp[self::VALUE];
980
        $product->is_negative = $temp[self::SIGN];
981
982
        return $this->_normalize($product);
983
    }
984
985
    /**
986
     * Performs multiplication.
987
     *
988
     * @param array $x_value
989
     * @param bool  $x_negative
990
     * @param array $y_value
991
     * @param bool  $y_negative
992
     *
993
     * @return array
994
     */
995
    private static function _multiply($x_value, $x_negative, $y_value, $y_negative)
996
    {
997
        //if ( $x_value == $y_value ) {
998
        //    return array(
999
        //        self::VALUE => $this->_square($x_value),
1000
        //        self::SIGN => $x_sign != $y_value
1001
        //    );
1002
        //}
1003
1004
        $x_length = count($x_value);
1005
        $y_length = count($y_value);
1006
1007
        if (!$x_length || !$y_length) { // a 0 is being multiplied
1008
            return [
1009
                self::VALUE => [],
1010
                self::SIGN  => false,
1011
            ];
1012
        }
1013
1014
        return [
1015
            self::VALUE => min($x_length, $y_length) < 2 * self::KARATSUBA_CUTOFF ?
1016
                self::_trim(self::_regularMultiply($x_value, $y_value)) :
1017
                self::_trim(self::_karatsuba($x_value, $y_value)),
1018
            self::SIGN => $x_negative != $y_negative,
1019
        ];
1020
    }
1021
1022
    /**
1023
     * Performs long multiplication on two BigIntegers.
1024
     *
1025
     * Modeled after 'multiply' in MutableBigInteger.java.
1026
     *
1027
     * @param array $x_value
1028
     * @param array $y_value
1029
     *
1030
     * @return array
1031
     */
1032
    private static function _regularMultiply($x_value, $y_value)
1033
    {
1034
        $x_length = count($x_value);
1035
        $y_length = count($y_value);
1036
1037
        if (!$x_length || !$y_length) { // a 0 is being multiplied
1038
            return [];
1039
        }
1040
1041
        if ($x_length < $y_length) {
1042
            $temp = $x_value;
1043
            $x_value = $y_value;
1044
            $y_value = $temp;
1045
1046
            $x_length = count($x_value);
1047
            $y_length = count($y_value);
1048
        }
1049
1050
        $product_value = self::_array_repeat(0, $x_length + $y_length);
1051
1052
        // the following for loop could be removed if the for loop following it
1053
        // (the one with nested for loops) initially set $i to 0, but
1054
        // doing so would also make the result in one set of unnecessary adds,
1055
        // since on the outermost loops first pass, $product->value[$k] is going
1056
        // to always be 0
1057
1058
        $carry = 0;
1059
1060
        for ($j = 0; $j < $x_length; ++$j) { // ie. $i = 0
1061
            $temp = $x_value[$j] * $y_value[0] + $carry; // $product_value[$k] == 0
1062
            $carry = self::$base === 26 ? intval($temp / 0x4000000) : ($temp >> 31);
1063
            $product_value[$j] = (int) ($temp - self::$baseFull * $carry);
1064
        }
1065
1066
        $product_value[$j] = $carry;
1067
1068
        // the above for loop is what the previous comment was talking about.  the
1069
        // following for loop is the "one with nested for loops"
1070
        for ($i = 1; $i < $y_length; ++$i) {
1071
            $carry = 0;
1072
1073
            for ($j = 0, $k = $i; $j < $x_length; ++$j, ++$k) {
1074
                $temp = $product_value[$k] + $x_value[$j] * $y_value[$i] + $carry;
1075
                $carry = self::$base === 26 ? intval($temp / 0x4000000) : ($temp >> 31);
1076
                $product_value[$k] = (int) ($temp - self::$baseFull * $carry);
1077
            }
1078
1079
            $product_value[$k] = $carry;
1080
        }
1081
1082
        return $product_value;
1083
    }
1084
1085
    /**
1086
     * Performs Karatsuba multiplication on two BigIntegers.
1087
     *
1088
     * See {@link http://en.wikipedia.org/wiki/Karatsuba_algorithm Karatsuba algorithm} and
1089
     * {@link http://math.libtomcrypt.com/files/tommath.pdf#page=120 MPM 5.2.3}.
1090
     *
1091
     * @param array $x_value
1092
     * @param array $y_value
1093
     *
1094
     * @return array
1095
     */
1096
    private static function _karatsuba($x_value, $y_value)
1097
    {
1098
        $m = min(count($x_value) >> 1, count($y_value) >> 1);
1099
1100
        if ($m < self::KARATSUBA_CUTOFF) {
1101
            return self::_regularMultiply($x_value, $y_value);
1102
        }
1103
1104
        $x1 = array_slice($x_value, $m);
1105
        $x0 = array_slice($x_value, 0, $m);
1106
        $y1 = array_slice($y_value, $m);
1107
        $y0 = array_slice($y_value, 0, $m);
1108
1109
        $z2 = self::_karatsuba($x1, $y1);
1110
        $z0 = self::_karatsuba($x0, $y0);
1111
1112
        $z1 = self::_add($x1, false, $x0, false);
1113
        $temp = self::_add($y1, false, $y0, false);
1114
        $z1 = self::_karatsuba($z1[self::VALUE], $temp[self::VALUE]);
1115
        $temp = self::_add($z2, false, $z0, false);
1116
        $z1 = self::_subtract($z1, false, $temp[self::VALUE], false);
1117
1118
        $z2 = array_merge(array_fill(0, 2 * $m, 0), $z2);
1119
        $z1[self::VALUE] = array_merge(array_fill(0, $m, 0), $z1[self::VALUE]);
1120
1121
        $xy = self::_add($z2, false, $z1[self::VALUE], $z1[self::SIGN]);
1122
        $xy = self::_add($xy[self::VALUE], $xy[self::SIGN], $z0, false);
1123
1124
        return $xy[self::VALUE];
1125
    }
1126
1127
    /**
1128
     * Performs squaring.
1129
     *
1130
     * @param array $x
1131
     *
1132
     * @return array
1133
     */
1134
    private static function _square($x = false)
1135
    {
1136
        return count($x) < 2 * self::KARATSUBA_CUTOFF ?
1137
            self::_trim(self::_baseSquare($x)) :
1138
            self::_trim(self::_karatsubaSquare($x));
1139
    }
1140
1141
    /**
1142
     * Performs traditional squaring on two BigIntegers.
1143
     *
1144
     * Squaring can be done faster than multiplying a number by itself can be.  See
1145
     * {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=7 HAC 14.2.4} /
1146
     * {@link http://math.libtomcrypt.com/files/tommath.pdf#page=141 MPM 5.3} for more information.
1147
     *
1148
     * @param array $value
1149
     *
1150
     * @return array
1151
     */
1152
    private static function _baseSquare($value)
1153
    {
1154
        if (empty($value)) {
1155
            return [];
1156
        }
1157
        $square_value = self::_array_repeat(0, 2 * count($value));
1158
1159
        for ($i = 0, $max_index = count($value) - 1; $i <= $max_index; ++$i) {
1160
            $i2 = $i << 1;
1161
1162
            $temp = $square_value[$i2] + $value[$i] * $value[$i];
1163
            $carry = self::$base === 26 ? intval($temp / 0x4000000) : ($temp >> 31);
1164
            $square_value[$i2] = (int) ($temp - self::$baseFull * $carry);
1165
1166
            // note how we start from $i+1 instead of 0 as we do in multiplication.
1167
            for ($j = $i + 1, $k = $i2 + 1; $j <= $max_index; ++$j, ++$k) {
1168
                $temp = $square_value[$k] + 2 * $value[$j] * $value[$i] + $carry;
1169
                $carry = self::$base === 26 ? intval($temp / 0x4000000) : ($temp >> 31);
1170
                $square_value[$k] = (int) ($temp - self::$baseFull * $carry);
1171
            }
1172
1173
            // the following line can yield values larger 2**15.  at this point, PHP should switch
1174
            // over to floats.
1175
            $square_value[$i + $max_index + 1] = $carry;
1176
        }
1177
1178
        return $square_value;
1179
    }
1180
1181
    /**
1182
     * Performs Karatsuba "squaring" on two BigIntegers.
1183
     *
1184
     * See {@link http://en.wikipedia.org/wiki/Karatsuba_algorithm Karatsuba algorithm} and
1185
     * {@link http://math.libtomcrypt.com/files/tommath.pdf#page=151 MPM 5.3.4}.
1186
     *
1187
     * @param array $value
1188
     *
1189
     * @return array
1190
     */
1191
    private static function _karatsubaSquare($value)
1192
    {
1193
        $m = count($value) >> 1;
1194
1195
        if ($m < self::KARATSUBA_CUTOFF) {
1196
            return self::_baseSquare($value);
1197
        }
1198
1199
        $x1 = array_slice($value, $m);
1200
        $x0 = array_slice($value, 0, $m);
1201
1202
        $z2 = self::_karatsubaSquare($x1);
1203
        $z0 = self::_karatsubaSquare($x0);
1204
1205
        $z1 = self::_add($x1, false, $x0, false);
1206
        $z1 = self::_karatsubaSquare($z1[self::VALUE]);
1207
        $temp = self::_add($z2, false, $z0, false);
1208
        $z1 = self::_subtract($z1, false, $temp[self::VALUE], false);
1209
1210
        $z2 = array_merge(array_fill(0, 2 * $m, 0), $z2);
1211
        $z1[self::VALUE] = array_merge(array_fill(0, $m, 0), $z1[self::VALUE]);
1212
1213
        $xx = self::_add($z2, false, $z1[self::VALUE], $z1[self::SIGN]);
1214
        $xx = self::_add($xx[self::VALUE], $xx[self::SIGN], $z0, false);
1215
1216
        return $xx[self::VALUE];
1217
    }
1218
1219
    /**
1220
     * Divides two BigIntegers.
1221
     *
1222
     * Returns an array whose first element contains the quotient and whose second element contains the
1223
     * "common residue".  If the remainder would be positive, the "common residue" and the remainder are the
1224
     * same.  If the remainder would be negative, the "common residue" is equal to the sum of the remainder
1225
     * and the divisor (basically, the "common residue" is the first positive modulo).
1226
     *
1227
     * Here's an example:
1228
     * <code>
1229
     * <?php
1230
     *    $a = new \Jose\Util\ger('10');
1231
     *    $b = new \Jose\Util\ger('20');
1232
     *
1233
     *    list($quotient, $remainder) = $a->divide($b);
1234
     *
1235
     *    echo $quotient->toString(); // outputs 0
1236
     *    echo "\r\n";
1237
     *    echo $remainder->toString(); // outputs 10
1238
     * ?>
1239
     * </code>
1240
     *
1241
     * @param \Jose\Util\Integer $y
1242
     *
1243
     * @return array
1244
     *
1245
     * @internal This function is based off of {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=9 HAC 14.20}.
1246
     */
1247
    public function divide(BigInteger $y)
1248
    {
1249
        switch (MATH_BIGINTEGER_MODE) {
1250
            case self::MODE_GMP:
1251
                $quotient = new static();
1252
                $remainder = new static();
1253
1254
                list($quotient->value, $remainder->value) = gmp_div_qr($this->value, $y->value);
1255
1256
                if (gmp_sign($remainder->value) < 0) {
1257
                    $remainder->value = gmp_add($remainder->value, gmp_abs($y->value));
1258
                }
1259
1260
                return [$this->_normalize($quotient), $this->_normalize($remainder)];
1261
            case self::MODE_BCMATH:
1262
                $quotient = new static();
1263
                $remainder = new static();
1264
1265
                $quotient->value = bcdiv($this->value, $y->value, 0);
1266
                $remainder->value = bcmod($this->value, $y->value);
1267
1268
                if ($remainder->value[0] == '-') {
1269
                    $remainder->value = bcadd($remainder->value, $y->value[0] == '-' ? substr($y->value, 1) : $y->value, 0);
1270
                }
1271
1272
                return [$this->_normalize($quotient), $this->_normalize($remainder)];
1273
        }
1274
1275
        if (count($y->value) == 1) {
1276
            list($q, $r) = $this->_divide_digit($this->value, $y->value[0]);
1277
            $quotient = new static();
1278
            $remainder = new static();
1279
            $quotient->value = $q;
1280
            $remainder->value = [$r];
1281
            $quotient->is_negative = $this->is_negative != $y->is_negative;
1282
1283
            return [$this->_normalize($quotient), $this->_normalize($remainder)];
1284
        }
1285
1286
        static $zero;
1287
        if (!isset($zero)) {
1288
            $zero = new static();
1289
        }
1290
1291
        $x = clone $this;
1292
        $y = clone $y;
1293
1294
        $x_sign = $x->is_negative;
1295
        $y_sign = $y->is_negative;
1296
1297
        $x->is_negative = $y->is_negative = false;
1298
1299
        $diff = $x->compare($y);
1300
1301
        if (!$diff) {
1302
            $temp = new static();
1303
            $temp->value = [1];
1304
            $temp->is_negative = $x_sign != $y_sign;
1305
1306
            return [$this->_normalize($temp), $this->_normalize(new static())];
1307
        }
1308
1309
        if ($diff < 0) {
1310
            // if $x is negative, "add" $y.
1311
            if ($x_sign) {
1312
                $x = $y->subtract($x);
1313
            }
1314
1315
            return [$this->_normalize(new static()), $this->_normalize($x)];
1316
        }
1317
1318
        // normalize $x and $y as described in HAC 14.23 / 14.24
1319
        $msb = $y->value[count($y->value) - 1];
1320
        for ($shift = 0; !($msb & self::$msb); ++$shift) {
1321
            $msb <<= 1;
1322
        }
1323
        $x->_lshift($shift);
1324
        $y->_lshift($shift);
1325
        $y_value = &$y->value;
1326
1327
        $x_max = count($x->value) - 1;
1328
        $y_max = count($y->value) - 1;
1329
1330
        $quotient = new static();
1331
        $quotient_value = &$quotient->value;
1332
        $quotient_value = $this->_array_repeat(0, $x_max - $y_max + 1);
1333
1334
        static $temp, $lhs, $rhs;
1335
        if (!isset($temp)) {
1336
            $temp = new static();
1337
            $lhs = new static();
1338
            $rhs = new static();
1339
        }
1340
        $temp_value = &$temp->value;
1341
        $rhs_value = &$rhs->value;
1342
1343
        // $temp = $y << ($x_max - $y_max-1) in base 2**26
1344
        $temp_value = array_merge($this->_array_repeat(0, $x_max - $y_max), $y_value);
1345
1346
        while ($x->compare($temp) >= 0) {
1347
            // calculate the "common residue"
1348
            ++$quotient_value[$x_max - $y_max];
1349
            $x = $x->subtract($temp);
1350
            $x_max = count($x->value) - 1;
1351
        }
1352
1353
        for ($i = $x_max; $i >= $y_max + 1; --$i) {
1354
            $x_value = &$x->value;
1355
            $x_window = [
1356
                isset($x_value[$i]) ? $x_value[$i] : 0,
1357
                isset($x_value[$i - 1]) ? $x_value[$i - 1] : 0,
1358
                isset($x_value[$i - 2]) ? $x_value[$i - 2] : 0,
1359
            ];
1360
            $y_window = [
1361
                $y_value[$y_max],
1362
                ($y_max > 0) ? $y_value[$y_max - 1] : 0,
1363
            ];
1364
1365
            $q_index = $i - $y_max - 1;
1366
            if ($x_window[0] == $y_window[0]) {
1367
                $quotient_value[$q_index] = self::$maxDigit;
1368
            } else {
1369
                $quotient_value[$q_index] = $this->_safe_divide(
1370
                    $x_window[0] * self::$baseFull + $x_window[1],
1371
                    $y_window[0]
1372
                );
1373
            }
1374
1375
            $temp_value = [$y_window[1], $y_window[0]];
1376
1377
            $lhs->value = [$quotient_value[$q_index]];
1378
            $lhs = $lhs->multiply($temp);
1379
1380
            $rhs_value = [$x_window[2], $x_window[1], $x_window[0]];
1381
1382
            while ($lhs->compare($rhs) > 0) {
1383
                --$quotient_value[$q_index];
1384
1385
                $lhs->value = [$quotient_value[$q_index]];
1386
                $lhs = $lhs->multiply($temp);
1387
            }
1388
1389
            $adjust = $this->_array_repeat(0, $q_index);
1390
            $temp_value = [$quotient_value[$q_index]];
1391
            $temp = $temp->multiply($y);
1392
            $temp_value = &$temp->value;
1393
            $temp_value = array_merge($adjust, $temp_value);
1394
1395
            $x = $x->subtract($temp);
1396
1397
            if ($x->compare($zero) < 0) {
1398
                $temp_value = array_merge($adjust, $y_value);
1399
                $x = $x->add($temp);
1400
1401
                --$quotient_value[$q_index];
1402
            }
1403
1404
            $x_max = count($x_value) - 1;
1405
        }
1406
1407
        // unnormalize the remainder
1408
        $x->_rshift($shift);
1409
1410
        $quotient->is_negative = $x_sign != $y_sign;
1411
1412
        // calculate the "common residue", if appropriate
1413
        if ($x_sign) {
1414
            $y->_rshift($shift);
1415
            $x = $y->subtract($x);
1416
        }
1417
1418
        return [$this->_normalize($quotient), $this->_normalize($x)];
1419
    }
1420
1421
    /**
1422
     * Divides a BigInteger by a regular integer.
1423
     *
1424
     * abc / x = a00 / x + b0 / x + c / x
1425
     *
1426
     * @param array $dividend
1427
     * @param array $divisor
1428
     *
1429
     * @return array
1430
     */
1431
    private static function _divide_digit($dividend, $divisor)
1432
    {
1433
        $carry = 0;
1434
        $result = [];
1435
1436
        for ($i = count($dividend) - 1; $i >= 0; --$i) {
1437
            $temp = self::$baseFull * $carry + $dividend[$i];
1438
            $result[$i] = self::_safe_divide($temp, $divisor);
1439
            $carry = (int) ($temp - $divisor * $result[$i]);
1440
        }
1441
1442
        return [$result, $carry];
1443
    }
1444
1445
    /**
1446
     * Performs modular exponentiation.
1447
     *
1448
     * Here's an example:
1449
     * <code>
1450
     * <?php
1451
     *    $a = new \Jose\Util\ger('10');
1452
     *    $b = new \Jose\Util\ger('20');
1453
     *    $c = new \Jose\Util\ger('30');
1454
     *
1455
     *    $c = $a->modPow($b, $c);
1456
     *
1457
     *    echo $c->toString(); // outputs 10
1458
     * ?>
1459
     * </code>
1460
     *
1461
     * @param \Jose\Util\Integer $e
1462
     * @param \Jose\Util\Integer $n
1463
     *
1464
     * @return \Jose\Util\BigInteger
1465
     *
1466
     * @internal The most naive approach to modular exponentiation has very unreasonable requirements, and
1467
     *    and although the approach involving repeated squaring does vastly better, it, too, is impractical
1468
     *    for our purposes.  The reason being that division - by far the most complicated and time-consuming
1469
     *    of the basic operations (eg. +,-,*,/) - occurs multiple times within it.
1470
     *
1471
     *    Modular reductions resolve this issue.  Although an individual modular reduction takes more time
1472
     *    then an individual division, when performed in succession (with the same modulo), they're a lot faster.
1473
     *
1474
     *    The two most commonly used modular reductions are Barrett and Montgomery reduction.  Montgomery reduction,
1475
     *    although faster, only works when the gcd of the modulo and of the base being used is 1.  In RSA, when the
1476
     *    base is a power of two, the modulo - a product of two primes - is always going to have a gcd of 1 (because
1477
     *    the product of two odd numbers is odd), but what about when RSA isn't used?
1478
     *
1479
     *    In contrast, Barrett reduction has no such constraint.  As such, some bigint implementations perform a
1480
     *    Barrett reduction after every operation in the modpow function.  Others perform Barrett reductions when the
1481
     *    modulo is even and Montgomery reductions when the modulo is odd.  BigInteger.java's modPow method, however,
1482
     *    uses a trick involving the Chinese Remainder Theorem to factor the even modulo into two numbers - one odd and
1483
     *    the other, a power of two - and recombine them, later.  This is the method that this modPow function uses.
1484
     *    {@link http://islab.oregonstate.edu/papers/j34monex.pdf Montgomery Reduction with Even Modulus} elaborates.
1485
     */
1486
    public function modPow(BigInteger $e, BigInteger $n)
1487
    {
1488
        $n = $this->bitmask !== false && $this->bitmask->compare($n) < 0 ? $this->bitmask : $n->abs();
1489
1490
        if ($e->compare(new static()) < 0) {
1491
            $e = $e->abs();
1492
1493
            $temp = $this->modInverse($n);
1494
            if ($temp === false) {
1495
                return false;
1496
            }
1497
1498
            return $this->_normalize($temp->modPow($e, $n));
1499
        }
1500
1501
        if (MATH_BIGINTEGER_MODE == self::MODE_GMP) {
1502
            $temp = new static();
1503
            $temp->value = gmp_powm($this->value, $e->value, $n->value);
1504
1505
            return $this->_normalize($temp);
1506
        }
1507
1508
        if ($this->compare(new static()) < 0 || $this->compare($n) > 0) {
1509
            list(, $temp) = $this->divide($n);
1510
1511
            return $temp->modPow($e, $n);
1512
        }
1513
1514
        if (defined('MATH_BIGINTEGER_OPENSSL_ENABLED')) {
1515
            $components = [
1516
                'modulus'        => $n->toBytes(true),
1517
                'publicExponent' => $e->toBytes(true),
1518
            ];
1519
1520
            $components = [
1521
                'modulus'        => pack('Ca*a*', 2, self::_encodeASN1Length(strlen($components['modulus'])), $components['modulus']),
1522
                'publicExponent' => pack('Ca*a*', 2, self::_encodeASN1Length(strlen($components['publicExponent'])), $components['publicExponent']),
1523
            ];
1524
1525
            $RSAPublicKey = pack(
1526
                'Ca*a*a*',
1527
                48,
1528
                self::_encodeASN1Length(strlen($components['modulus']) + strlen($components['publicExponent'])),
1529
                $components['modulus'],
1530
                $components['publicExponent']
1531
            );
1532
1533
            $rsaOID = "\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00"; // hex version of MA0GCSqGSIb3DQEBAQUA
1534
            $RSAPublicKey = chr(0).$RSAPublicKey;
1535
            $RSAPublicKey = chr(3).self::_encodeASN1Length(strlen($RSAPublicKey)).$RSAPublicKey;
1536
1537
            $encapsulated = pack(
1538
                'Ca*a*',
1539
                48,
1540
                self::_encodeASN1Length(strlen($rsaOID.$RSAPublicKey)),
1541
                $rsaOID.$RSAPublicKey
1542
            );
1543
1544
            $RSAPublicKey = "-----BEGIN PUBLIC KEY-----\r\n".
1545
                chunk_split(base64_encode($encapsulated)).
1546
                '-----END PUBLIC KEY-----';
1547
1548
            $plaintext = str_pad($this->toBytes(), strlen($n->toBytes(true)) - 1, "\0", STR_PAD_LEFT);
1549
1550
            if (openssl_public_encrypt($plaintext, $result, $RSAPublicKey, OPENSSL_NO_PADDING)) {
1551
                return new static($result, 256);
1552
            }
1553
        }
1554
1555
        if (MATH_BIGINTEGER_MODE == self::MODE_BCMATH) {
1556
            $temp = new static();
1557
            $temp->value = bcpowmod($this->value, $e->value, $n->value, 0);
1558
1559
            return $this->_normalize($temp);
1560
        }
1561
1562
        if (empty($e->value)) {
1563
            $temp = new static();
1564
            $temp->value = [1];
1565
1566
            return $this->_normalize($temp);
1567
        }
1568
1569
        if ($e->value == [1]) {
1570
            list(, $temp) = $this->divide($n);
1571
1572
            return $this->_normalize($temp);
1573
        }
1574
1575
        if ($e->value == [2]) {
1576
            $temp = new static();
1577
            $temp->value = self::_square($this->value);
1578
            list(, $temp) = $temp->divide($n);
1579
1580
            return $this->_normalize($temp);
1581
        }
1582
1583
        return $this->_normalize($this->_slidingWindow($e, $n, self::BARRETT));
1584
1585
        // the following code, although not callable, can be run independently of the above code
1586
        // although the above code performed better in my benchmarks the following could might
1587
        // perform better under different circumstances. in lieu of deleting it it's just been
1588
        // made uncallable
1589
1590
        // is the modulo odd?
1591
        if ($n->value[0] & 1) {
1592
            return $this->_normalize($this->_slidingWindow($e, $n, self::MONTGOMERY));
1593
        }
1594
        // if it's not, it's even
1595
1596
        // find the lowest set bit (eg. the max pow of 2 that divides $n)
1597
        for ($i = 0; $i < count($n->value); ++$i) {
1598
            if ($n->value[$i]) {
1599
                $temp = decbin($n->value[$i]);
1600
                $j = strlen($temp) - strrpos($temp, '1') - 1;
1601
                $j += 26 * $i;
1602
                break;
1603
            }
1604
        }
1605
        // at this point, 2^$j * $n/(2^$j) == $n
1606
1607
        $mod1 = clone $n;
1608
        $mod1->_rshift($j);
1609
        $mod2 = new static();
1610
        $mod2->value = [1];
1611
        $mod2->_lshift($j);
1612
1613
        $part1 = ($mod1->value != [1]) ? $this->_slidingWindow($e, $mod1, self::MONTGOMERY) : new static();
1614
        $part2 = $this->_slidingWindow($e, $mod2, self::POWEROF2);
1615
1616
        $y1 = $mod2->modInverse($mod1);
1617
        $y2 = $mod1->modInverse($mod2);
1618
1619
        $result = $part1->multiply($mod2);
1620
        $result = $result->multiply($y1);
1621
1622
        $temp = $part2->multiply($mod1);
1623
        $temp = $temp->multiply($y2);
1624
1625
        $result = $result->add($temp);
1626
        list(, $result) = $result->divide($n);
1627
1628
        return $this->_normalize($result);
1629
    }
1630
1631
    /**
1632
     * Performs modular exponentiation.
1633
     *
1634
     * Alias for modPow().
1635
     *
1636
     * @param \Jose\Util\Integer $e
1637
     * @param \Jose\Util\Integer $n
1638
     *
1639
     * @return \Jose\Util\BigInteger
1640
     */
1641
    public function powMod(BigInteger $e, BigInteger $n)
1642
    {
1643
        return $this->modPow($e, $n);
1644
    }
1645
1646
    /**
1647
     * Sliding Window k-ary Modular Exponentiation.
1648
     *
1649
     * Based on {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=27 HAC 14.85} /
1650
     * {@link http://math.libtomcrypt.com/files/tommath.pdf#page=210 MPM 7.7}.  In a departure from those algorithims,
1651
     * however, this function performs a modular reduction after every multiplication and squaring operation.
1652
     * As such, this function has the same preconditions that the reductions being used do.
1653
     *
1654
     * @param \Jose\Util\Integer $e
1655
     * @param \Jose\Util\Integer $n
1656
     * @param int                $mode
1657
     *
1658
     * @return \Jose\Util\BigInteger
1659
     */
1660
    private function _slidingWindow($e, $n, $mode)
1661
    {
1662
        static $window_ranges = [7, 25, 81, 241, 673, 1793]; // from BigInteger.java's oddModPow function
1663
        //static $window_ranges = array(0, 7, 36, 140, 450, 1303, 3529); // from MPM 7.3.1
1664
1665
        $e_value = $e->value;
1666
        $e_length = count($e_value) - 1;
1667
        $e_bits = decbin($e_value[$e_length]);
1668
        for ($i = $e_length - 1; $i >= 0; --$i) {
1669
            $e_bits .= str_pad(decbin($e_value[$i]), self::$base, '0', STR_PAD_LEFT);
1670
        }
1671
1672
        $e_length = strlen($e_bits);
1673
1674
        // calculate the appropriate window size.
1675
        // $window_size == 3 if $window_ranges is between 25 and 81, for example.
1676
        for ($i = 0, $window_size = 1; $i < count($window_ranges) && $e_length > $window_ranges[$i]; ++$window_size, ++$i) {
1677
        }
1678
1679
        $n_value = $n->value;
1680
1681
        // precompute $this^0 through $this^$window_size
1682
        $powers = [];
1683
        $powers[1] = self::_prepareReduce($this->value, $n_value, $mode);
1684
        $powers[2] = self::_squareReduce($powers[1], $n_value, $mode);
1685
1686
        // we do every other number since substr($e_bits, $i, $j+1) (see below) is supposed to end
1687
        // in a 1.  ie. it's supposed to be odd.
1688
        $temp = 1 << ($window_size - 1);
1689
        for ($i = 1; $i < $temp; ++$i) {
1690
            $i2 = $i << 1;
1691
            $powers[$i2 + 1] = self::_multiplyReduce($powers[$i2 - 1], $powers[2], $n_value, $mode);
1692
        }
1693
1694
        $result = [1];
1695
        $result = self::_prepareReduce($result, $n_value, $mode);
1696
1697
        for ($i = 0; $i < $e_length;) {
1698
            if (!$e_bits[$i]) {
1699
                $result = self::_squareReduce($result, $n_value, $mode);
1700
                ++$i;
1701
            } else {
1702
                for ($j = $window_size - 1; $j > 0; --$j) {
1703
                    if (!empty($e_bits[$i + $j])) {
1704
                        break;
1705
                    }
1706
                }
1707
1708
                // eg. the length of substr($e_bits, $i, $j + 1)
1709
                for ($k = 0; $k <= $j; ++$k) {
1710
                    $result = self::_squareReduce($result, $n_value, $mode);
1711
                }
1712
1713
                $result = self::_multiplyReduce($result, $powers[bindec(substr($e_bits, $i, $j + 1))], $n_value, $mode);
1714
1715
                $i += $j + 1;
1716
            }
1717
        }
1718
1719
        $temp = new static();
1720
        $temp->value = self::_reduce($result, $n_value, $mode);
1721
1722
        return $temp;
1723
    }
1724
1725
    /**
1726
     * Modular reduction.
1727
     *
1728
     * For most $modes this will return the remainder.
1729
     *
1730
     * @param array $x
1731
     * @param array $n
1732
     * @param int   $mode
1733
     *
1734
     * @return array
1735
     */
1736
    private static function _reduce($x, $n, $mode)
1737
    {
1738
        switch ($mode) {
1739
            case self::MONTGOMERY:
1740
                return self::_montgomery($x, $n);
1741
            case self::BARRETT:
1742
                return self::_barrett($x, $n);
1743
            case self::POWEROF2:
1744
                $lhs = new static();
1745
                $lhs->value = $x;
1746
                $rhs = new static();
1747
                $rhs->value = $n;
1748
1749
                return $x->_mod2($n);
1750
            case self::CLASSIC:
1751
                $lhs = new static();
1752
                $lhs->value = $x;
1753
                $rhs = new static();
1754
                $rhs->value = $n;
1755
                list(, $temp) = $lhs->divide($rhs);
1756
1757
                return $temp->value;
1758
            case self::NONE:
1759
                return $x;
1760
            default:
1761
                // an invalid $mode was provided
1762
        }
1763
    }
1764
1765
    /**
1766
     * Modular reduction preperation.
1767
     *
1768
     * @param array $x
1769
     * @param array $n
1770
     * @param int   $mode
1771
     *
1772
     * @return array
1773
     */
1774
    private static function _prepareReduce($x, $n, $mode)
1775
    {
1776
        if ($mode == self::MONTGOMERY) {
1777
            return self::_prepMontgomery($x, $n);
1778
        }
1779
1780
        return self::_reduce($x, $n, $mode);
1781
    }
1782
1783
    /**
1784
     * Modular multiply.
1785
     *
1786
     * @param array $x
1787
     * @param array $y
1788
     * @param array $n
1789
     * @param int   $mode
1790
     *
1791
     * @return array
1792
     */
1793
    private static function _multiplyReduce($x, $y, $n, $mode)
1794
    {
1795
        if ($mode == self::MONTGOMERY) {
1796
            return self::_montgomeryMultiply($x, $y, $n);
1797
        }
1798
        $temp = self::_multiply($x, false, $y, false);
1799
1800
        return self::_reduce($temp[self::VALUE], $n, $mode);
1801
    }
1802
1803
    /**
1804
     * Modular square.
1805
     *
1806
     * @param array $x
1807
     * @param array $n
1808
     * @param int   $mode
1809
     *
1810
     * @return array
1811
     */
1812
    private static function _squareReduce($x, $n, $mode)
1813
    {
1814
        if ($mode == self::MONTGOMERY) {
1815
            return self::_montgomeryMultiply($x, $x, $n);
1816
        }
1817
1818
        return self::_reduce(self::_square($x), $n, $mode);
1819
    }
1820
1821
    /**
1822
     * Modulos for Powers of Two.
1823
     *
1824
     * Calculates $x%$n, where $n = 2**$e, for some $e.  Since this is basically the same as doing $x & ($n-1),
1825
     * we'll just use this function as a wrapper for doing that.
1826
     *
1827
     * @param \Jose\Util\BigInteger
1828
     *
1829
     * @return \Jose\Util\BigInteger
1830
     */
1831
    private function _mod2($n)
1832
    {
1833
        $temp = new static();
1834
        $temp->value = [1];
1835
1836
        return $this->bitwise_and($n->subtract($temp));
1837
    }
1838
1839
    /**
1840
     * Barrett Modular Reduction.
1841
     *
1842
     * See {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=14 HAC 14.3.3} /
1843
     * {@link http://math.libtomcrypt.com/files/tommath.pdf#page=165 MPM 6.2.5} for more information.  Modified slightly,
1844
     * so as not to require negative numbers (initially, this script didn't support negative numbers).
1845
     *
1846
     * Employs "folding", as described at
1847
     * {@link http://www.cosic.esat.kuleuven.be/publications/thesis-149.pdf#page=66 thesis-149.pdf#page=66}.  To quote from
1848
     * it, "the idea [behind folding] is to find a value x' such that x (mod m) = x' (mod m), with x' being smaller than x."
1849
     *
1850
     * Unfortunately, the "Barrett Reduction with Folding" algorithm described in thesis-149.pdf is not, as written, all that
1851
     * usable on account of (1) its not using reasonable radix points as discussed in
1852
     * {@link http://math.libtomcrypt.com/files/tommath.pdf#page=162 MPM 6.2.2} and (2) the fact that, even with reasonable
1853
     * radix points, it only works when there are an even number of digits in the denominator.  The reason for (2) is that
1854
     * (x >> 1) + (x >> 1) != x / 2 + x / 2.  If x is even, they're the same, but if x is odd, they're not.  See the in-line
1855
     * comments for details.
1856
     *
1857
     * @param array $n
1858
     * @param array $m
1859
     *
1860
     * @return array
1861
     */
1862
    private static function _barrett($n, $m)
1863
    {
1864
        static $cache = [
1865
            self::VARIABLE => [],
1866
            self::DATA     => [],
1867
        ];
1868
1869
        $m_length = count($m);
1870
1871
        // if (self::_compare($n, self::_square($m)) >= 0) {
1872
        if (count($n) > 2 * $m_length) {
1873
            $lhs = new static();
1874
            $rhs = new static();
1875
            $lhs->value = $n;
1876
            $rhs->value = $m;
1877
            list(, $temp) = $lhs->divide($rhs);
1878
1879
            return $temp->value;
1880
        }
1881
1882
        // if (m.length >> 1) + 2 <= m.length then m is too small and n can't be reduced
1883
        if ($m_length < 5) {
1884
            return self::_regularBarrett($n, $m);
1885
        }
1886
1887
        // n = 2 * m.length
1888
1889
        if (($key = array_search($m, $cache[self::VARIABLE])) === false) {
1890
            $key = count($cache[self::VARIABLE]);
1891
            $cache[self::VARIABLE][] = $m;
1892
1893
            $lhs = new static();
1894
            $lhs_value = &$lhs->value;
1895
            $lhs_value = self::_array_repeat(0, $m_length + ($m_length >> 1));
1896
            $lhs_value[] = 1;
1897
            $rhs = new static();
1898
            $rhs->value = $m;
1899
1900
            list($u, $m1) = $lhs->divide($rhs);
1901
            $u = $u->value;
1902
            $m1 = $m1->value;
1903
1904
            $cache[self::DATA][] = [
1905
                'u'  => $u, // m.length >> 1 (technically (m.length >> 1) + 1)
1906
                'm1' => $m1, // m.length
1907
            ];
1908
        } else {
1909
            extract($cache[self::DATA][$key]);
1910
        }
1911
1912
        $cutoff = $m_length + ($m_length >> 1);
1913
        $lsd = array_slice($n, 0, $cutoff); // m.length + (m.length >> 1)
1914
        $msd = array_slice($n, $cutoff);    // m.length >> 1
1915
        $lsd = self::_trim($lsd);
1916
        $temp = self::_multiply($msd, false, $m1, false);
1917
        $n = self::_add($lsd, false, $temp[self::VALUE], false); // m.length + (m.length >> 1) + 1
1918
1919
        if ($m_length & 1) {
1920
            return self::_regularBarrett($n[self::VALUE], $m);
1921
        }
1922
1923
        // (m.length + (m.length >> 1) + 1) - (m.length - 1) == (m.length >> 1) + 2
1924
        $temp = array_slice($n[self::VALUE], $m_length - 1);
1925
        // if even: ((m.length >> 1) + 2) + (m.length >> 1) == m.length + 2
1926
        // if odd:  ((m.length >> 1) + 2) + (m.length >> 1) == (m.length - 1) + 2 == m.length + 1
1927
        $temp = self::_multiply($temp, false, $u, false);
1928
        // if even: (m.length + 2) - ((m.length >> 1) + 1) = m.length - (m.length >> 1) + 1
1929
        // if odd:  (m.length + 1) - ((m.length >> 1) + 1) = m.length - (m.length >> 1)
1930
        $temp = array_slice($temp[self::VALUE], ($m_length >> 1) + 1);
1931
        // if even: (m.length - (m.length >> 1) + 1) + m.length = 2 * m.length - (m.length >> 1) + 1
1932
        // if odd:  (m.length - (m.length >> 1)) + m.length     = 2 * m.length - (m.length >> 1)
1933
        $temp = self::_multiply($temp, false, $m, false);
1934
1935
        // at this point, if m had an odd number of digits, we'd be subtracting a 2 * m.length - (m.length >> 1) digit
1936
        // number from a m.length + (m.length >> 1) + 1 digit number.  ie. there'd be an extra digit and the while loop
1937
        // following this comment would loop a lot (hence our calling _regularBarrett() in that situation).
1938
1939
        $result = self::_subtract($n[self::VALUE], false, $temp[self::VALUE], false);
1940
1941
        while (self::_compare($result[self::VALUE], $result[self::SIGN], $m, false) >= 0) {
1942
            $result = self::_subtract($result[self::VALUE], $result[self::SIGN], $m, false);
1943
        }
1944
1945
        return $result[self::VALUE];
1946
    }
1947
1948
    /**
1949
     * (Regular) Barrett Modular Reduction.
1950
     *
1951
     * For numbers with more than four digits BigInteger::_barrett() is faster.  The difference between that and this
1952
     * is that this function does not fold the denominator into a smaller form.
1953
     *
1954
     * @param array $x
1955
     * @param array $n
1956
     *
1957
     * @return array
1958
     */
1959
    private static function _regularBarrett($x, $n)
1960
    {
1961
        static $cache = [
1962
            self::VARIABLE => [],
1963
            self::DATA     => [],
1964
        ];
1965
1966
        $n_length = count($n);
1967
1968
        if (count($x) > 2 * $n_length) {
1969
            $lhs = new static();
1970
            $rhs = new static();
1971
            $lhs->value = $x;
1972
            $rhs->value = $n;
1973
            list(, $temp) = $lhs->divide($rhs);
1974
1975
            return $temp->value;
1976
        }
1977
1978
        if (($key = array_search($n, $cache[self::VARIABLE])) === false) {
1979
            $key = count($cache[self::VARIABLE]);
1980
            $cache[self::VARIABLE][] = $n;
1981
            $lhs = new static();
1982
            $lhs_value = &$lhs->value;
1983
            $lhs_value = self::_array_repeat(0, 2 * $n_length);
1984
            $lhs_value[] = 1;
1985
            $rhs = new static();
1986
            $rhs->value = $n;
1987
            list($temp) = $lhs->divide($rhs); // m.length
1988
            $cache[self::DATA][] = $temp->value;
1989
        }
1990
1991
        // 2 * m.length - (m.length - 1) = m.length + 1
1992
        $temp = array_slice($x, $n_length - 1);
1993
        // (m.length + 1) + m.length = 2 * m.length + 1
1994
        $temp = self::_multiply($temp, false, $cache[self::DATA][$key], false);
1995
        // (2 * m.length + 1) - (m.length - 1) = m.length + 2
1996
        $temp = array_slice($temp[self::VALUE], $n_length + 1);
1997
1998
        // m.length + 1
1999
        $result = array_slice($x, 0, $n_length + 1);
2000
        // m.length + 1
2001
        $temp = self::_multiplyLower($temp, false, $n, false, $n_length + 1);
2002
        // $temp == array_slice(self::_multiply($temp, false, $n, false)->value, 0, $n_length + 1)
2003
2004
        if (self::_compare($result, false, $temp[self::VALUE], $temp[self::SIGN]) < 0) {
2005
            $corrector_value = self::_array_repeat(0, $n_length + 1);
2006
            $corrector_value[count($corrector_value)] = 1;
2007
            $result = self::_add($result, false, $corrector_value, false);
2008
            $result = $result[self::VALUE];
2009
        }
2010
2011
        // at this point, we're subtracting a number with m.length + 1 digits from another number with m.length + 1 digits
2012
        $result = self::_subtract($result, false, $temp[self::VALUE], $temp[self::SIGN]);
2013
        while (self::_compare($result[self::VALUE], $result[self::SIGN], $n, false) > 0) {
2014
            $result = self::_subtract($result[self::VALUE], $result[self::SIGN], $n, false);
2015
        }
2016
2017
        return $result[self::VALUE];
2018
    }
2019
2020
    /**
2021
     * Performs long multiplication up to $stop digits.
2022
     *
2023
     * If you're going to be doing array_slice($product->value, 0, $stop), some cycles can be saved.
2024
     *
2025
     * @param array $x_value
2026
     * @param bool  $x_negative
2027
     * @param array $y_value
2028
     * @param bool  $y_negative
2029
     * @param int   $stop
2030
     *
2031
     * @return array
2032
     */
2033
    private static function _multiplyLower($x_value, $x_negative, $y_value, $y_negative, $stop)
2034
    {
2035
        $x_length = count($x_value);
2036
        $y_length = count($y_value);
2037
2038
        if (!$x_length || !$y_length) { // a 0 is being multiplied
2039
            return [
2040
                self::VALUE => [],
2041
                self::SIGN  => false,
2042
            ];
2043
        }
2044
2045
        if ($x_length < $y_length) {
2046
            $temp = $x_value;
2047
            $x_value = $y_value;
2048
            $y_value = $temp;
2049
2050
            $x_length = count($x_value);
2051
            $y_length = count($y_value);
2052
        }
2053
2054
        $product_value = self::_array_repeat(0, $x_length + $y_length);
2055
2056
        // the following for loop could be removed if the for loop following it
2057
        // (the one with nested for loops) initially set $i to 0, but
2058
        // doing so would also make the result in one set of unnecessary adds,
2059
        // since on the outermost loops first pass, $product->value[$k] is going
2060
        // to always be 0
2061
2062
        $carry = 0;
2063
2064
        for ($j = 0; $j < $x_length; ++$j) { // ie. $i = 0, $k = $i
2065
            $temp = $x_value[$j] * $y_value[0] + $carry; // $product_value[$k] == 0
2066
            $carry = self::$base === 26 ? intval($temp / 0x4000000) : ($temp >> 31);
2067
            $product_value[$j] = (int) ($temp - self::$baseFull * $carry);
2068
        }
2069
2070
        if ($j < $stop) {
2071
            $product_value[$j] = $carry;
2072
        }
2073
2074
        // the above for loop is what the previous comment was talking about.  the
2075
        // following for loop is the "one with nested for loops"
2076
2077
        for ($i = 1; $i < $y_length; ++$i) {
2078
            $carry = 0;
2079
2080
            for ($j = 0, $k = $i; $j < $x_length && $k < $stop; ++$j, ++$k) {
2081
                $temp = $product_value[$k] + $x_value[$j] * $y_value[$i] + $carry;
2082
                $carry = self::$base === 26 ? intval($temp / 0x4000000) : ($temp >> 31);
2083
                $product_value[$k] = (int) ($temp - self::$baseFull * $carry);
2084
            }
2085
2086
            if ($k < $stop) {
2087
                $product_value[$k] = $carry;
2088
            }
2089
        }
2090
2091
        return [
2092
            self::VALUE => self::_trim($product_value),
2093
            self::SIGN  => $x_negative != $y_negative,
2094
        ];
2095
    }
2096
2097
    /**
2098
     * Montgomery Modular Reduction.
2099
     *
2100
     * ($x->_prepMontgomery($n))->_montgomery($n) yields $x % $n.
2101
     * {@link http://math.libtomcrypt.com/files/tommath.pdf#page=170 MPM 6.3} provides insights on how this can be
2102
     * improved upon (basically, by using the comba method).  gcd($n, 2) must be equal to one for this function
2103
     * to work correctly.
2104
     *
2105
     * @param array $x
2106
     * @param array $n
2107
     *
2108
     * @return array
2109
     */
2110
    private static function _montgomery($x, $n)
2111
    {
2112
        static $cache = [
2113
            self::VARIABLE => [],
2114
            self::DATA     => [],
2115
        ];
2116
2117
        if (($key = array_search($n, $cache[self::VARIABLE])) === false) {
2118
            $key = count($cache[self::VARIABLE]);
2119
            $cache[self::VARIABLE][] = $x;
2120
            $cache[self::DATA][] = self::_modInverse67108864($n);
2121
        }
2122
2123
        $k = count($n);
2124
2125
        $result = [self::VALUE => $x];
2126
2127
        for ($i = 0; $i < $k; ++$i) {
2128
            $temp = $result[self::VALUE][$i] * $cache[self::DATA][$key];
2129
            $temp = $temp - self::$baseFull * (self::$base === 26 ? intval($temp / 0x4000000) : ($temp >> 31));
2130
            $temp = self::_regularMultiply([$temp], $n);
2131
            $temp = array_merge($this->_array_repeat(0, $i), $temp);
2132
            $result = self::_add($result[self::VALUE], false, $temp, false);
2133
        }
2134
2135
        $result[self::VALUE] = array_slice($result[self::VALUE], $k);
2136
2137
        if (self::_compare($result, false, $n, false) >= 0) {
2138
            $result = self::_subtract($result[self::VALUE], false, $n, false);
2139
        }
2140
2141
        return $result[self::VALUE];
2142
    }
2143
2144
    /**
2145
     * Montgomery Multiply.
2146
     *
2147
     * Interleaves the montgomery reduction and long multiplication algorithms together as described in
2148
     * {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=13 HAC 14.36}
2149
     *
2150
     * @param array $x
2151
     * @param array $y
2152
     * @param array $m
2153
     *
2154
     * @return array
2155
     */
2156
    private static function _montgomeryMultiply($x, $y, $m)
2157
    {
2158
        $temp = self::_multiply($x, false, $y, false);
2159
2160
        return self::_montgomery($temp[self::VALUE], $m);
2161
2162
        // the following code, although not callable, can be run independently of the above code
2163
        // although the above code performed better in my benchmarks the following could might
2164
        // perform better under different circumstances. in lieu of deleting it it's just been
2165
        // made uncallable
2166
2167
        static $cache = [
0 ignored issues
show
// the following code, a...self::DATA => array()); does not seem to be reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
2168
            self::VARIABLE => [],
2169
            self::DATA     => [],
2170
        ];
2171
2172
        if (($key = array_search($m, $cache[self::VARIABLE])) === false) {
2173
            $key = count($cache[self::VARIABLE]);
2174
            $cache[self::VARIABLE][] = $m;
2175
            $cache[self::DATA][] = self::_modInverse67108864($m);
2176
        }
2177
2178
        $n = max(count($x), count($y), count($m));
2179
        $x = array_pad($x, $n, 0);
2180
        $y = array_pad($y, $n, 0);
2181
        $m = array_pad($m, $n, 0);
2182
        $a = [self::VALUE => self::_array_repeat(0, $n + 1)];
2183
        for ($i = 0; $i < $n; ++$i) {
2184
            $temp = $a[self::VALUE][0] + $x[$i] * $y[0];
2185
            $temp = $temp - self::$baseFull * (self::$base === 26 ? intval($temp / 0x4000000) : ($temp >> 31));
2186
            $temp = $temp * $cache[self::DATA][$key];
2187
            $temp = $temp - self::$baseFull * (self::$base === 26 ? intval($temp / 0x4000000) : ($temp >> 31));
2188
            $temp = self::_add(self::_regularMultiply([$x[$i]], $y), false, self::_regularMultiply([$temp], $m), false);
2189
            $a = self::_add($a[self::VALUE], false, $temp[self::VALUE], false);
2190
            $a[self::VALUE] = array_slice($a[self::VALUE], 1);
2191
        }
2192
        if (self::_compare($a[self::VALUE], false, $m, false) >= 0) {
2193
            $a = self::_subtract($a[self::VALUE], false, $m, false);
2194
        }
2195
2196
        return $a[self::VALUE];
2197
    }
2198
2199
    /**
2200
     * Prepare a number for use in Montgomery Modular Reductions.
2201
     *
2202
     * @param array $x
2203
     * @param array $n
2204
     *
2205
     * @return array
2206
     */
2207
    private static function _prepMontgomery($x, $n)
2208
    {
2209
        $lhs = new static();
2210
        $lhs->value = array_merge(self::_array_repeat(0, count($n)), $x);
2211
        $rhs = new static();
2212
        $rhs->value = $n;
2213
2214
        list(, $temp) = $lhs->divide($rhs);
2215
2216
        return $temp->value;
2217
    }
2218
2219
    /**
2220
     * Modular Inverse of a number mod 2**26 (eg. 67108864).
2221
     *
2222
     * Based off of the bnpInvDigit function implemented and justified in the following URL:
2223
     *
2224
     * {@link http://www-cs-students.stanford.edu/~tjw/jsbn/jsbn.js}
2225
     *
2226
     * The following URL provides more info:
2227
     *
2228
     * {@link http://groups.google.com/group/sci.crypt/msg/7a137205c1be7d85}
2229
     *
2230
     * As for why we do all the bitmasking...  strange things can happen when converting from floats to ints. For
2231
     * instance, on some computers, var_dump((int) -4294967297) yields int(-1) and on others, it yields
2232
     * int(-2147483648).  To avoid problems stemming from this, we use bitmasks to guarantee that ints aren't
2233
     * auto-converted to floats.  The outermost bitmask is present because without it, there's no guarantee that
2234
     * the "residue" returned would be the so-called "common residue".  We use fmod, in the last step, because the
2235
     * maximum possible $x is 26 bits and the maximum $result is 16 bits.  Thus, we have to be able to handle up to
2236
     * 40 bits, which only 64-bit floating points will support.
2237
     *
2238
     * Thanks to Pedro Gimeno Fortea for input!
2239
     *
2240
     * @param array $x
2241
     *
2242
     * @return int
2243
     */
2244
    private function _modInverse67108864($x) // 2**26 == 67,108,864
2245
    {
2246
        $x = -$x[0];
2247
        $result = $x & 0x3; // x**-1 mod 2**2
2248
        $result = ($result * (2 - $x * $result)) & 0xF; // x**-1 mod 2**4
2249
        $result = ($result * (2 - ($x & 0xFF) * $result))  & 0xFF; // x**-1 mod 2**8
2250
        $result = ($result * ((2 - ($x & 0xFFFF) * $result) & 0xFFFF)) & 0xFFFF; // x**-1 mod 2**16
2251
        $result = fmod($result * (2 - fmod($x * $result, self::$baseFull)), self::$baseFull); // x**-1 mod 2**26
2252
        return $result & self::$maxDigit;
2253
    }
2254
2255
    /**
2256
     * Calculates modular inverses.
2257
     *
2258
     * Say you have (30 mod 17 * x mod 17) mod 17 == 1.  x can be found using modular inverses.
2259
     *
2260
     * Here's an example:
2261
     * <code>
2262
     * <?php
2263
     *    $a = new \Jose\Util\teger(30);
2264
     *    $b = new \Jose\Util\teger(17);
2265
     *
2266
     *    $c = $a->modInverse($b);
2267
     *    echo $c->toString(); // outputs 4
2268
     *
2269
     *    echo "\r\n";
2270
     *
2271
     *    $d = $a->multiply($c);
2272
     *    list(, $d) = $d->divide($b);
2273
     *    echo $d; // outputs 1 (as per the definition of modular inverse)
2274
     * ?>
2275
     * </code>
2276
     *
2277
     * @param \Jose\Util\Integer $n
2278
     *
2279
     * @return \Jose\Util\eger|false
2280
     *
2281
     * @internal See {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=21 HAC 14.64} for more information.
2282
     */
2283
    public function modInverse(BigInteger $n)
2284
    {
2285
        switch (MATH_BIGINTEGER_MODE) {
2286
            case self::MODE_GMP:
2287
                $temp = new static();
2288
                $temp->value = gmp_invert($this->value, $n->value);
2289
2290
                return ($temp->value === false) ? false : $this->_normalize($temp);
2291
        }
2292
2293
        static $zero, $one;
2294
        if (!isset($zero)) {
2295
            $zero = new static();
2296
            $one = new static(1);
2297
        }
2298
2299
        // $x mod -$n == $x mod $n.
2300
        $n = $n->abs();
2301
2302
        if ($this->compare($zero) < 0) {
2303
            $temp = $this->abs();
2304
            $temp = $temp->modInverse($n);
2305
2306
            return $this->_normalize($n->subtract($temp));
2307
        }
2308
2309
        extract($this->extendedGCD($n));
2310
2311
        if (!$gcd->equals($one)) {
2312
            return false;
2313
        }
2314
2315
        $x = $x->compare($zero) < 0 ? $x->add($n) : $x;
2316
2317
        return $this->compare($zero) < 0 ? $this->_normalize($n->subtract($x)) : $this->_normalize($x);
2318
    }
2319
2320
    /**
2321
     * Calculates the greatest common divisor and Bezout's identity.
2322
     *
2323
     * Say you have 693 and 609.  The GCD is 21.  Bezout's identity states that there exist integers x and y such that
2324
     * 693*x + 609*y == 21.  In point of fact, there are actually an infinite number of x and y combinations and which
2325
     * combination is returned is dependant upon which mode is in use.  See
2326
     * {@link http://en.wikipedia.org/wiki/B%C3%A9zout%27s_identity Bezout's identity - Wikipedia} for more information.
2327
     *
2328
     * Here's an example:
2329
     * <code>
2330
     * <?php
2331
     *    $a = new \Jose\Util\eger(693);
2332
     *    $b = new \Jose\Util\eger(609);
2333
     *
2334
     *    extract($a->extendedGCD($b));
2335
     *
2336
     *    echo $gcd->toString() . "\r\n"; // outputs 21
2337
     *    echo $a->toString() * $x->toString() + $b->toString() * $y->toString(); // outputs 21
2338
     * ?>
2339
     * </code>
2340
     *
2341
     * @param \Jose\Util\Integer $n
2342
     *
2343
     * @return \Jose\Util\BigInteger
2344
     *
2345
     * @internal Calculates the GCD using the binary xGCD algorithim described in
2346
     *    {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=19 HAC 14.61}.  As the text above 14.61 notes,
2347
     *    the more traditional algorithim requires "relatively costly multiple-precision divisions".
2348
     */
2349
    public function extendedGCD(BigInteger $n)
2350
    {
2351
        switch (MATH_BIGINTEGER_MODE) {
2352
            case self::MODE_GMP:
2353
                extract(gmp_gcdext($this->value, $n->value));
2354
2355
                return [
2356
                    'gcd' => $this->_normalize(new static($g)),
2357
                    'x'   => $this->_normalize(new static($s)),
2358
                    'y'   => $this->_normalize(new static($t)),
2359
                ];
2360
            case self::MODE_BCMATH:
2361
                // it might be faster to use the binary xGCD algorithim here, as well, but (1) that algorithim works
2362
                // best when the base is a power of 2 and (2) i don't think it'd make much difference, anyway.  as is,
2363
                // the basic extended euclidean algorithim is what we're using.
2364
2365
                $u = $this->value;
2366
                $v = $n->value;
2367
2368
                $a = '1';
2369
                $b = '0';
2370
                $c = '0';
2371
                $d = '1';
2372
2373
                while (bccomp($v, '0', 0) != 0) {
2374
                    $q = bcdiv($u, $v, 0);
2375
2376
                    $temp = $u;
2377
                    $u = $v;
2378
                    $v = bcsub($temp, bcmul($v, $q, 0), 0);
2379
2380
                    $temp = $a;
2381
                    $a = $c;
2382
                    $c = bcsub($temp, bcmul($a, $q, 0), 0);
2383
2384
                    $temp = $b;
2385
                    $b = $d;
2386
                    $d = bcsub($temp, bcmul($b, $q, 0), 0);
2387
                }
2388
2389
                return [
2390
                    'gcd' => $this->_normalize(new static($u)),
2391
                    'x'   => $this->_normalize(new static($a)),
2392
                    'y'   => $this->_normalize(new static($b)),
2393
                ];
2394
        }
2395
2396
        $y = clone $n;
2397
        $x = clone $this;
2398
        $g = new static();
2399
        $g->value = [1];
2400
2401
        while (!(($x->value[0] & 1) || ($y->value[0] & 1))) {
2402
            $x->_rshift(1);
2403
            $y->_rshift(1);
2404
            $g->_lshift(1);
2405
        }
2406
2407
        $u = clone $x;
2408
        $v = clone $y;
2409
2410
        $a = new static();
2411
        $b = new static();
2412
        $c = new static();
2413
        $d = new static();
2414
2415
        $a->value = $d->value = $g->value = [1];
2416
        $b->value = $c->value = [];
2417
2418
        while (!empty($u->value)) {
2419
            while (!($u->value[0] & 1)) {
2420
                $u->_rshift(1);
2421
                if ((!empty($a->value) && ($a->value[0] & 1)) || (!empty($b->value) && ($b->value[0] & 1))) {
2422
                    $a = $a->add($y);
2423
                    $b = $b->subtract($x);
2424
                }
2425
                $a->_rshift(1);
2426
                $b->_rshift(1);
2427
            }
2428
2429
            while (!($v->value[0] & 1)) {
2430
                $v->_rshift(1);
2431
                if ((!empty($d->value) && ($d->value[0] & 1)) || (!empty($c->value) && ($c->value[0] & 1))) {
2432
                    $c = $c->add($y);
2433
                    $d = $d->subtract($x);
2434
                }
2435
                $c->_rshift(1);
2436
                $d->_rshift(1);
2437
            }
2438
2439
            if ($u->compare($v) >= 0) {
2440
                $u = $u->subtract($v);
2441
                $a = $a->subtract($c);
2442
                $b = $b->subtract($d);
2443
            } else {
2444
                $v = $v->subtract($u);
2445
                $c = $c->subtract($a);
2446
                $d = $d->subtract($b);
2447
            }
2448
        }
2449
2450
        return [
2451
            'gcd' => $this->_normalize($g->multiply($v)),
2452
            'x'   => $this->_normalize($c),
2453
            'y'   => $this->_normalize($d),
2454
        ];
2455
    }
2456
2457
    /**
2458
     * Calculates the greatest common divisor.
2459
     *
2460
     * Say you have 693 and 609.  The GCD is 21.
2461
     *
2462
     * Here's an example:
2463
     * <code>
2464
     * <?php
2465
     *    $a = new \Jose\Util\eger(693);
2466
     *    $b = new \Jose\Util\eger(609);
2467
     *
2468
     *    $gcd = a->extendedGCD($b);
2469
     *
2470
     *    echo $gcd->toString() . "\r\n"; // outputs 21
2471
     * ?>
2472
     * </code>
2473
     *
2474
     * @param \Jose\Util\Integer $n
2475
     *
2476
     * @return \Jose\Util\BigInteger
2477
     */
2478
    public function gcd(BigInteger $n)
2479
    {
2480
        extract($this->extendedGCD($n));
2481
2482
        return $gcd;
2483
    }
2484
2485
    /**
2486
     * Absolute value.
2487
     *
2488
     * @return \Jose\Util\BigInteger
2489
     */
2490
    public function abs()
2491
    {
2492
        $temp = new static();
2493
2494
        switch (MATH_BIGINTEGER_MODE) {
2495
            case self::MODE_GMP:
2496
                $temp->value = gmp_abs($this->value);
2497
                break;
2498
            case self::MODE_BCMATH:
2499
                $temp->value = (bccomp($this->value, '0', 0) < 0) ? substr($this->value, 1) : $this->value;
2500
                break;
2501
            default:
2502
                $temp->value = $this->value;
2503
        }
2504
2505
        return $temp;
2506
    }
2507
2508
    /**
2509
     * Compares two numbers.
2510
     *
2511
     * Although one might think !$x->compare($y) means $x != $y, it, in fact, means the opposite.  The reason for this is
2512
     * demonstrated thusly:
2513
     *
2514
     * $x  > $y: $x->compare($y)  > 0
2515
     * $x  < $y: $x->compare($y)  < 0
2516
     * $x == $y: $x->compare($y) == 0
2517
     *
2518
     * Note how the same comparison operator is used.  If you want to test for equality, use $x->equals($y).
2519
     *
2520
     * @param \Jose\Util\Integer $y
2521
     *
2522
     * @return int < 0 if $this is less than $y; > 0 if $this is greater than $y, and 0 if they are equal.
2523
     *
2524
     * @internal Could return $this->subtract($x), but that's not as fast as what we do do.
2525
     */
2526
    public function compare(BigInteger $y)
2527
    {
2528
        switch (MATH_BIGINTEGER_MODE) {
2529
            case self::MODE_GMP:
2530
                return gmp_cmp($this->value, $y->value);
2531
            case self::MODE_BCMATH:
2532
                return bccomp($this->value, $y->value, 0);
2533
        }
2534
2535
        return self::_compare($this->value, $this->is_negative, $y->value, $y->is_negative);
2536
    }
2537
2538
    /**
2539
     * Compares two numbers.
2540
     *
2541
     * @param array $x_value
2542
     * @param bool  $x_negative
2543
     * @param array $y_value
2544
     * @param bool  $y_negative
2545
     *
2546
     * @return int
2547
     */
2548
    private static function _compare($x_value, $x_negative, $y_value, $y_negative)
2549
    {
2550
        if ($x_negative != $y_negative) {
2551
            return (!$x_negative && $y_negative) ? 1 : -1;
2552
        }
2553
2554
        $result = $x_negative ? -1 : 1;
2555
2556
        if (count($x_value) != count($y_value)) {
2557
            return (count($x_value) > count($y_value)) ? $result : -$result;
2558
        }
2559
        $size = max(count($x_value), count($y_value));
2560
2561
        $x_value = array_pad($x_value, $size, 0);
2562
        $y_value = array_pad($y_value, $size, 0);
2563
2564
        for ($i = count($x_value) - 1; $i >= 0; --$i) {
2565
            if ($x_value[$i] != $y_value[$i]) {
2566
                return ($x_value[$i] > $y_value[$i]) ? $result : -$result;
2567
            }
2568
        }
2569
2570
        return 0;
2571
    }
2572
2573
    /**
2574
     * Tests the equality of two numbers.
2575
     *
2576
     * If you need to see if one number is greater than or less than another number, use BigInteger::compare()
2577
     *
2578
     * @param \Jose\Util\Integer $x
2579
     *
2580
     * @return bool
2581
     */
2582
    public function equals(BigInteger $x)
2583
    {
2584
        switch (MATH_BIGINTEGER_MODE) {
2585
            case self::MODE_GMP:
2586
                return gmp_cmp($this->value, $x->value) == 0;
2587
            default:
2588
                return $this->value === $x->value && $this->is_negative == $x->is_negative;
2589
        }
2590
    }
2591
2592
    /**
2593
     * Set Precision.
2594
     *
2595
     * Some bitwise operations give different results depending on the precision being used.  Examples include left
2596
     * shift, not, and rotates.
2597
     *
2598
     * @param int $bits
2599
     */
2600
    public function setPrecision($bits)
2601
    {
2602
        if ($bits < 1) {
2603
            $this->precision = -1;
2604
            $this->bitmask = false;
2605
2606
            return;
2607
        }
2608
        $this->precision = $bits;
2609
        if (MATH_BIGINTEGER_MODE != self::MODE_BCMATH) {
2610
            $this->bitmask = new static(chr((1 << ($bits & 0x7)) - 1).str_repeat(chr(0xFF), $bits >> 3), 256);
2611
        } else {
2612
            $this->bitmask = new static(bcpow('2', $bits, 0));
2613
        }
2614
2615
        $temp = $this->_normalize($this);
2616
        $this->value = $temp->value;
2617
    }
2618
2619
    /**
2620
     * Get Precision.
2621
     *
2622
     * @return int
2623
     */
2624
    public function getPrecision()
2625
    {
2626
        return $this->precision;
2627
    }
2628
2629
    /**
2630
     * Logical And.
2631
     *
2632
     * @param \Jose\Util\Integer $x
2633
     *
2634
     * @internal Implemented per a request by Lluis Pamies i Juarez <lluis _a_ pamies.cat>
2635
     *
2636
     * @return \Jose\Util\BigInteger
2637
     */
2638
    public function bitwise_and(BigInteger $x)
2639
    {
2640
        switch (MATH_BIGINTEGER_MODE) {
2641
            case self::MODE_GMP:
2642
                $temp = new static();
2643
                $temp->value = gmp_and($this->value, $x->value);
2644
2645
                return $this->_normalize($temp);
2646
            case self::MODE_BCMATH:
2647
                $left = $this->toBytes();
2648
                $right = $x->toBytes();
2649
2650
                $length = max(strlen($left), strlen($right));
2651
2652
                $left = str_pad($left, $length, chr(0), STR_PAD_LEFT);
2653
                $right = str_pad($right, $length, chr(0), STR_PAD_LEFT);
2654
2655
                return $this->_normalize(new static($left & $right, 256));
2656
        }
2657
2658
        $result = clone $this;
2659
2660
        $length = min(count($x->value), count($this->value));
2661
2662
        $result->value = array_slice($result->value, 0, $length);
2663
2664
        for ($i = 0; $i < $length; ++$i) {
2665
            $result->value[$i] &= $x->value[$i];
2666
        }
2667
2668
        return $this->_normalize($result);
2669
    }
2670
2671
    /**
2672
     * Logical Or.
2673
     *
2674
     * @param \Jose\Util\Integer $x
2675
     *
2676
     * @internal Implemented per a request by Lluis Pamies i Juarez <lluis _a_ pamies.cat>
2677
     *
2678
     * @return \Jose\Util\BigInteger
2679
     */
2680
    public function bitwise_or(BigInteger $x)
2681
    {
2682
        switch (MATH_BIGINTEGER_MODE) {
2683
            case self::MODE_GMP:
2684
                $temp = new static();
2685
                $temp->value = gmp_or($this->value, $x->value);
2686
2687
                return $this->_normalize($temp);
2688
            case self::MODE_BCMATH:
2689
                $left = $this->toBytes();
2690
                $right = $x->toBytes();
2691
2692
                $length = max(strlen($left), strlen($right));
2693
2694
                $left = str_pad($left, $length, chr(0), STR_PAD_LEFT);
2695
                $right = str_pad($right, $length, chr(0), STR_PAD_LEFT);
2696
2697
                return $this->_normalize(new static($left | $right, 256));
2698
        }
2699
2700
        $length = max(count($this->value), count($x->value));
2701
        $result = clone $this;
2702
        $result->value = array_pad($result->value, $length, 0);
2703
        $x->value = array_pad($x->value, $length, 0);
2704
2705
        for ($i = 0; $i < $length; ++$i) {
2706
            $result->value[$i] |= $x->value[$i];
2707
        }
2708
2709
        return $this->_normalize($result);
2710
    }
2711
2712
    /**
2713
     * Logical Exclusive-Or.
2714
     *
2715
     * @param \Jose\Util\Integer $x
2716
     *
2717
     * @internal Implemented per a request by Lluis Pamies i Juarez <lluis _a_ pamies.cat>
2718
     *
2719
     * @return \Jose\Util\BigInteger
2720
     */
2721
    public function bitwise_xor(BigInteger $x)
2722
    {
2723
        switch (MATH_BIGINTEGER_MODE) {
2724
            case self::MODE_GMP:
2725
                $temp = new static();
2726
                $temp->value = gmp_xor($this->value, $x->value);
2727
2728
                return $this->_normalize($temp);
2729
            case self::MODE_BCMATH:
2730
                $left = $this->toBytes();
2731
                $right = $x->toBytes();
2732
2733
                $length = max(strlen($left), strlen($right));
2734
2735
                $left = str_pad($left, $length, chr(0), STR_PAD_LEFT);
2736
                $right = str_pad($right, $length, chr(0), STR_PAD_LEFT);
2737
2738
                return $this->_normalize(new static($left ^ $right, 256));
2739
        }
2740
2741
        $length = max(count($this->value), count($x->value));
2742
        $result = clone $this;
2743
        $result->value = array_pad($result->value, $length, 0);
2744
        $x->value = array_pad($x->value, $length, 0);
2745
2746
        for ($i = 0; $i < $length; ++$i) {
2747
            $result->value[$i] ^= $x->value[$i];
2748
        }
2749
2750
        return $this->_normalize($result);
2751
    }
2752
2753
    /**
2754
     * Logical Not.
2755
     *
2756
     * @internal Implemented per a request by Lluis Pamies i Juarez <lluis _a_ pamies.cat>
2757
     *
2758
     * @return \Jose\Util\BigInteger
2759
     */
2760
    public function bitwise_not()
2761
    {
2762
        // calculuate "not" without regard to $this->precision
2763
        // (will always result in a smaller number.  ie. ~1 isn't 1111 1110 - it's 0)
2764
        $temp = $this->toBytes();
2765
        if ($temp == '') {
2766
            return '';
2767
        }
2768
        $pre_msb = decbin(ord($temp[0]));
2769
        $temp = ~$temp;
2770
        $msb = decbin(ord($temp[0]));
2771
        if (strlen($msb) == 8) {
2772
            $msb = substr($msb, strpos($msb, '0'));
2773
        }
2774
        $temp[0] = chr(bindec($msb));
2775
2776
        // see if we need to add extra leading 1's
2777
        $current_bits = strlen($pre_msb) + 8 * strlen($temp) - 8;
2778
        $new_bits = $this->precision - $current_bits;
2779
        if ($new_bits <= 0) {
2780
            return $this->_normalize(new static($temp, 256));
2781
        }
2782
2783
        // generate as many leading 1's as we need to.
2784
        $leading_ones = chr((1 << ($new_bits & 0x7)) - 1).str_repeat(chr(0xFF), $new_bits >> 3);
2785
2786
        self::_base256_lshift($leading_ones, $current_bits);
2787
2788
        $temp = str_pad($temp, strlen($leading_ones), chr(0), STR_PAD_LEFT);
2789
2790
        return $this->_normalize(new static($leading_ones | $temp, 256));
2791
    }
2792
2793
    /**
2794
     * Logical Right Shift.
2795
     *
2796
     * Shifts BigInteger's by $shift bits, effectively dividing by 2**$shift.
2797
     *
2798
     * @param int $shift
2799
     *
2800
     * @return \Jose\Util\BigInteger
2801
     *
2802
     * @internal The only version that yields any speed increases is the internal version.
2803
     */
2804
    public function bitwise_rightShift($shift)
2805
    {
2806
        $temp = new static();
2807
2808
        switch (MATH_BIGINTEGER_MODE) {
2809
            case self::MODE_GMP:
2810
                static $two;
2811
2812
                if (!isset($two)) {
2813
                    $two = gmp_init('2');
2814
                }
2815
2816
                $temp->value = gmp_div_q($this->value, gmp_pow($two, $shift));
2817
2818
                break;
2819
            case self::MODE_BCMATH:
2820
                $temp->value = bcdiv($this->value, bcpow('2', $shift, 0), 0);
2821
2822
                break;
2823
            default: // could just replace _lshift with this, but then all _lshift() calls would need to be rewritten
2824
                // and I don't want to do that...
2825
                $temp->value = $this->value;
2826
                $temp->_rshift($shift);
2827
        }
2828
2829
        return $this->_normalize($temp);
2830
    }
2831
2832
    /**
2833
     * Logical Left Shift.
2834
     *
2835
     * Shifts BigInteger's by $shift bits, effectively multiplying by 2**$shift.
2836
     *
2837
     * @param int $shift
2838
     *
2839
     * @return \Jose\Util\BigInteger
2840
     *
2841
     * @internal The only version that yields any speed increases is the internal version.
2842
     */
2843
    public function bitwise_leftShift($shift)
2844
    {
2845
        $temp = new static();
2846
2847
        switch (MATH_BIGINTEGER_MODE) {
2848
            case self::MODE_GMP:
2849
                static $two;
2850
2851
                if (!isset($two)) {
2852
                    $two = gmp_init('2');
2853
                }
2854
2855
                $temp->value = gmp_mul($this->value, gmp_pow($two, $shift));
2856
2857
                break;
2858
            case self::MODE_BCMATH:
2859
                $temp->value = bcmul($this->value, bcpow('2', $shift, 0), 0);
2860
2861
                break;
2862
            default: // could just replace _rshift with this, but then all _lshift() calls would need to be rewritten
2863
                // and I don't want to do that...
2864
                $temp->value = $this->value;
2865
                $temp->_lshift($shift);
2866
        }
2867
2868
        return $this->_normalize($temp);
2869
    }
2870
2871
    /**
2872
     * Logical Left Rotate.
2873
     *
2874
     * Instead of the top x bits being dropped they're appended to the shifted bit string.
2875
     *
2876
     * @param int $shift
2877
     *
2878
     * @return \Jose\Util\BigInteger
2879
     */
2880
    public function bitwise_leftRotate($shift)
2881
    {
2882
        $bits = $this->toBytes();
2883
2884
        if ($this->precision > 0) {
2885
            $precision = $this->precision;
2886
            if (MATH_BIGINTEGER_MODE == self::MODE_BCMATH) {
2887
                $mask = $this->bitmask->subtract(new static(1));
2888
                $mask = $mask->toBytes();
2889
            } else {
2890
                $mask = $this->bitmask->toBytes();
2891
            }
2892
        } else {
2893
            $temp = ord($bits[0]);
2894
            for ($i = 0; $temp >> $i; ++$i) {
2895
            }
2896
            $precision = 8 * strlen($bits) - 8 + $i;
2897
            $mask = chr((1 << ($precision & 0x7)) - 1).str_repeat(chr(0xFF), $precision >> 3);
2898
        }
2899
2900
        if ($shift < 0) {
2901
            $shift += $precision;
2902
        }
2903
        $shift %= $precision;
2904
2905
        if (!$shift) {
2906
            return clone $this;
2907
        }
2908
2909
        $left = $this->bitwise_leftShift($shift);
2910
        $left = $left->bitwise_and(new static($mask, 256));
2911
        $right = $this->bitwise_rightShift($precision - $shift);
2912
        $result = MATH_BIGINTEGER_MODE != self::MODE_BCMATH ? $left->bitwise_or($right) : $left->add($right);
2913
2914
        return $this->_normalize($result);
2915
    }
2916
2917
    /**
2918
     * Logical Right Rotate.
2919
     *
2920
     * Instead of the bottom x bits being dropped they're prepended to the shifted bit string.
2921
     *
2922
     * @param int $shift
2923
     *
2924
     * @return \Jose\Util\BigInteger
2925
     */
2926
    public function bitwise_rightRotate($shift)
2927
    {
2928
        return $this->bitwise_leftRotate(-$shift);
2929
    }
2930
2931
    /**
2932
     * Generates a random BigInteger.
2933
     *
2934
     * Byte length is equal to $length. Uses \phpseclib\Crypt\Random if it's loaded and mt_rand if it's not.
2935
     *
2936
     * @param int $length
2937
     *
2938
     * @return \Jose\Util\BigInteger
2939
     */
2940
    private static function _random_number_helper($size)
2941
    {
2942
        if (class_exists('\phpseclib\Crypt\Random')) {
2943
            $random = random_bytes($size);
2944
        } else {
2945
            $random = '';
2946
2947
            if ($size & 1) {
2948
                $random .= chr(mt_rand(0, 255));
2949
            }
2950
2951
            $blocks = $size >> 1;
2952
            for ($i = 0; $i < $blocks; ++$i) {
2953
                // mt_rand(-2147483648, 0x7FFFFFFF) always produces -2147483648 on some systems
2954
                $random .= pack('n', mt_rand(0, 0xFFFF));
2955
            }
2956
        }
2957
2958
        return new static($random, 256);
2959
    }
2960
2961
    /**
2962
     * Generate a random number.
2963
     *
2964
     * Returns a random number between $min and $max where $min and $max
2965
     * can be defined using one of the two methods:
2966
     *
2967
     * BigInteger::random($min, $max)
2968
     * BigInteger::random($max, $min)
2969
     *
2970
     * @param \Jose\Util\eger $arg1
2971
     * @param \Jose\Util\eger $arg2
2972
     *
2973
     * @return \Jose\Util\BigInteger
2974
     */
2975
    public static function random(BigInteger $min, BigInteger $max)
2976
    {
2977
        $compare = $max->compare($min);
2978
2979
        if (!$compare) {
2980
            return $this->_normalize($min);
2981
        } elseif ($compare < 0) {
2982
            // if $min is bigger then $max, swap $min and $max
2983
            $temp = $max;
2984
            $max = $min;
2985
            $min = $temp;
2986
        }
2987
2988
        static $one;
2989
        if (!isset($one)) {
2990
            $one = new static(1);
2991
        }
2992
2993
        $max = $max->subtract($min->subtract($one));
2994
        $size = strlen(ltrim($max->toBytes(), chr(0)));
2995
2996
        /*
2997
            doing $random % $max doesn't work because some numbers will be more likely to occur than others.
2998
            eg. if $max is 140 and $random's max is 255 then that'd mean both $random = 5 and $random = 145
2999
            would produce 5 whereas the only value of random that could produce 139 would be 139. ie.
3000
            not all numbers would be equally likely. some would be more likely than others.
3001
3002
            creating a whole new random number until you find one that is within the range doesn't work
3003
            because, for sufficiently small ranges, the likelihood that you'd get a number within that range
3004
            would be pretty small. eg. with $random's max being 255 and if your $max being 1 the probability
3005
            would be pretty high that $random would be greater than $max.
3006
3007
            phpseclib works around this using the technique described here:
3008
3009
            http://crypto.stackexchange.com/questions/5708/creating-a-small-number-from-a-cryptographically-secure-random-string
3010
        */
3011
        $random_max = new static(chr(1).str_repeat("\0", $size), 256);
3012
        $random = static::_random_number_helper($size);
3013
3014
        list($max_multiple) = $random_max->divide($max);
3015
        $max_multiple = $max_multiple->multiply($max);
3016
3017
        while ($random->compare($max_multiple) >= 0) {
3018
            $random = $random->subtract($max_multiple);
3019
            $random_max = $random_max->subtract($max_multiple);
3020
            $random = $random->bitwise_leftShift(8);
3021
            $random = $random->add(self::_random_number_helper(1));
3022
            $random_max = $random_max->bitwise_leftShift(8);
3023
            list($max_multiple) = $random_max->divide($max);
3024
            $max_multiple = $max_multiple->multiply($max);
3025
        }
3026
        list(, $random) = $random->divide($max);
3027
3028
        return $random->add($min);
3029
    }
3030
3031
    /**
3032
     * Generate a random prime number.
3033
     *
3034
     * If there's not a prime within the given range, false will be returned.
3035
     * If more than $timeout seconds have elapsed, give up and return false.
3036
     *
3037
     * @param \Jose\Util\teger $min
3038
     * @param \Jose\Util\teger $max
3039
     * @param int              $timeout
3040
     *
3041
     * @return Math_BigInteger|false
3042
     *
3043
     * @internal See {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap4.pdf#page=15 HAC 4.44}.
3044
     */
3045
    public static function randomPrime(BigInteger $min, BigInteger $max, $timeout = false)
3046
    {
3047
        $compare = $max->compare($min);
3048
3049
        if (!$compare) {
3050
            return $min->isPrime() ? $min : false;
3051
        } elseif ($compare < 0) {
3052
            // if $min is bigger then $max, swap $min and $max
3053
            $temp = $max;
3054
            $max = $min;
3055
            $min = $temp;
3056
        }
3057
3058
        static $one, $two;
3059
        if (!isset($one)) {
3060
            $one = new static(1);
3061
            $two = new static(2);
3062
        }
3063
3064
        $start = time();
3065
3066
        $x = self::random($min, $max);
3067
3068
        // gmp_nextprime() requires PHP 5 >= 5.2.0 per <http://php.net/gmp-nextprime>.
3069
        if (MATH_BIGINTEGER_MODE == self::MODE_GMP && extension_loaded('gmp')) {
3070
            $p = new static();
3071
            $p->value = gmp_nextprime($x->value);
3072
3073
            if ($p->compare($max) <= 0) {
3074
                return $p;
3075
            }
3076
3077
            if (!$min->equals($x)) {
3078
                $x = $x->subtract($one);
3079
            }
3080
3081
            return self::randomPrime($min, $x);
3082
        }
3083
3084
        if ($x->equals($two)) {
3085
            return $x;
3086
        }
3087
3088
        $x->_make_odd();
3089
        if ($x->compare($max) > 0) {
3090
            // if $x > $max then $max is even and if $min == $max then no prime number exists between the specified range
3091
            if ($min->equals($max)) {
3092
                return false;
3093
            }
3094
            $x = clone $min;
3095
            $x->_make_odd();
3096
        }
3097
3098
        $initial_x = clone $x;
3099
3100
        while (true) {
3101
            if ($timeout !== false && time() - $start > $timeout) {
3102
                return false;
3103
            }
3104
3105
            if ($x->isPrime()) {
3106
                return $x;
3107
            }
3108
3109
            $x = $x->add($two);
3110
3111
            if ($x->compare($max) > 0) {
3112
                $x = clone $min;
3113
                if ($x->equals($two)) {
3114
                    return $x;
3115
                }
3116
                $x->_make_odd();
3117
            }
3118
3119
            if ($x->equals($initial_x)) {
3120
                return false;
3121
            }
3122
        }
3123
    }
3124
3125
    /**
3126
     * Make the current number odd.
3127
     *
3128
     * If the current number is odd it'll be unchanged.  If it's even, one will be added to it.
3129
     */
3130
    private function _make_odd()
3131
    {
3132
        switch (MATH_BIGINTEGER_MODE) {
3133
            case self::MODE_GMP:
3134
                gmp_setbit($this->value, 0);
3135
                break;
3136
            case self::MODE_BCMATH:
3137
                if ($this->value[strlen($this->value) - 1] % 2 == 0) {
3138
                    $this->value = bcadd($this->value, '1');
3139
                }
3140
                break;
3141
            default:
3142
                $this->value[0] |= 1;
3143
        }
3144
    }
3145
3146
    /**
3147
     * Checks a numer to see if it's prime.
3148
     *
3149
     * Assuming the $t parameter is not set, this function has an error rate of 2**-80.  The main motivation for the
3150
     * $t parameter is distributability.  BigInteger::randomPrime() can be distributed across multiple pageloads
3151
     * on a website instead of just one.
3152
     *
3153
     * @param \Jose\Util\Integer $t
3154
     *
3155
     * @return bool
3156
     *
3157
     * @internal Uses the
3158
     *     {@link http://en.wikipedia.org/wiki/Miller%E2%80%93Rabin_primality_test Miller-Rabin primality test}.  See
3159
     *     {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap4.pdf#page=8 HAC 4.24}.
3160
     */
3161
    public function isPrime($t = false)
3162
    {
3163
        $length = strlen($this->toBytes());
3164
3165
        if (!$t) {
3166
            // see HAC 4.49 "Note (controlling the error probability)"
3167
            // @codingStandardsIgnoreStart
3168
            if ($length >= 163) {
3169
                $t = 2;
3170
            } // floor(1300 / 8)
3171
            elseif ($length >= 106) {
3172
                $t = 3;
3173
            } // floor( 850 / 8)
3174
            elseif ($length >= 81) {
3175
                $t = 4;
3176
            } // floor( 650 / 8)
3177
            elseif ($length >= 68) {
3178
                $t = 5;
3179
            } // floor( 550 / 8)
3180
            elseif ($length >= 56) {
3181
                $t = 6;
3182
            } // floor( 450 / 8)
3183
            elseif ($length >= 50) {
3184
                $t = 7;
3185
            } // floor( 400 / 8)
3186
            elseif ($length >= 43) {
3187
                $t = 8;
3188
            } // floor( 350 / 8)
3189
            elseif ($length >= 37) {
3190
                $t = 9;
3191
            } // floor( 300 / 8)
3192
            elseif ($length >= 31) {
3193
                $t = 12;
3194
            } // floor( 250 / 8)
3195
            elseif ($length >= 25) {
3196
                $t = 15;
3197
            } // floor( 200 / 8)
3198
            elseif ($length >= 18) {
3199
                $t = 18;
3200
            } // floor( 150 / 8)
3201
            else {
3202
                $t = 27;
3203
            }
3204
            // @codingStandardsIgnoreEnd
3205
        }
3206
3207
        // ie. gmp_testbit($this, 0)
3208
        // ie. isEven() or !isOdd()
3209
        switch (MATH_BIGINTEGER_MODE) {
3210
            case self::MODE_GMP:
3211
                return gmp_prob_prime($this->value, $t) != 0;
3212
            case self::MODE_BCMATH:
3213
                if ($this->value === '2') {
3214
                    return true;
3215
                }
3216
                if ($this->value[strlen($this->value) - 1] % 2 == 0) {
3217
                    return false;
3218
                }
3219
                break;
3220
            default:
3221
                if ($this->value == [2]) {
3222
                    return true;
3223
                }
3224
                if (~$this->value[0] & 1) {
3225
                    return false;
3226
                }
3227
        }
3228
3229
        static $primes, $zero, $one, $two;
3230
3231
        if (!isset($primes)) {
3232
            $primes = [
3233
                3,    5,    7,    11,   13,   17,   19,   23,   29,   31,   37,   41,   43,   47,   53,   59,
3234
                61,   67,   71,   73,   79,   83,   89,   97,   101,  103,  107,  109,  113,  127,  131,  137,
3235
                139,  149,  151,  157,  163,  167,  173,  179,  181,  191,  193,  197,  199,  211,  223,  227,
3236
                229,  233,  239,  241,  251,  257,  263,  269,  271,  277,  281,  283,  293,  307,  311,  313,
3237
                317,  331,  337,  347,  349,  353,  359,  367,  373,  379,  383,  389,  397,  401,  409,  419,
3238
                421,  431,  433,  439,  443,  449,  457,  461,  463,  467,  479,  487,  491,  499,  503,  509,
3239
                521,  523,  541,  547,  557,  563,  569,  571,  577,  587,  593,  599,  601,  607,  613,  617,
3240
                619,  631,  641,  643,  647,  653,  659,  661,  673,  677,  683,  691,  701,  709,  719,  727,
3241
                733,  739,  743,  751,  757,  761,  769,  773,  787,  797,  809,  811,  821,  823,  827,  829,
3242
                839,  853,  857,  859,  863,  877,  881,  883,  887,  907,  911,  919,  929,  937,  941,  947,
3243
                953,  967,  971,  977,  983,  991,  997,
3244
            ];
3245
3246
            if (MATH_BIGINTEGER_MODE != self::MODE_INTERNAL) {
3247
                for ($i = 0; $i < count($primes); ++$i) {
3248
                    $primes[$i] = new static($primes[$i]);
3249
                }
3250
            }
3251
3252
            $zero = new static();
3253
            $one = new static(1);
3254
            $two = new static(2);
3255
        }
3256
3257
        if ($this->equals($one)) {
3258
            return false;
3259
        }
3260
3261
        // see HAC 4.4.1 "Random search for probable primes"
3262
        if (MATH_BIGINTEGER_MODE != self::MODE_INTERNAL) {
3263
            foreach ($primes as $prime) {
3264
                list(, $r) = $this->divide($prime);
3265
                if ($r->equals($zero)) {
3266
                    return $this->equals($prime);
3267
                }
3268
            }
3269
        } else {
3270
            $value = $this->value;
3271
            foreach ($primes as $prime) {
3272
                list(, $r) = self::_divide_digit($value, $prime);
3273
                if (!$r) {
3274
                    return count($value) == 1 && $value[0] == $prime;
3275
                }
3276
            }
3277
        }
3278
3279
        $n = clone $this;
3280
        $n_1 = $n->subtract($one);
3281
        $n_2 = $n->subtract($two);
3282
3283
        $r = clone $n_1;
3284
        $r_value = $r->value;
3285
        // ie. $s = gmp_scan1($n, 0) and $r = gmp_div_q($n, gmp_pow(gmp_init('2'), $s));
3286
        if (MATH_BIGINTEGER_MODE == self::MODE_BCMATH) {
3287
            $s = 0;
3288
            // if $n was 1, $r would be 0 and this would be an infinite loop, hence our $this->equals($one) check earlier
3289
            while ($r->value[strlen($r->value) - 1] % 2 == 0) {
3290
                $r->value = bcdiv($r->value, '2', 0);
3291
                ++$s;
3292
            }
3293
        } else {
3294
            for ($i = 0, $r_length = count($r_value); $i < $r_length; ++$i) {
3295
                $temp = ~$r_value[$i] & 0xFFFFFF;
3296
                for ($j = 1; ($temp >> $j) & 1; ++$j) {
3297
                }
3298
                if ($j != 25) {
3299
                    break;
3300
                }
3301
            }
3302
            $s = 26 * $i + $j - 1;
3303
            $r->_rshift($s);
3304
        }
3305
3306
        for ($i = 0; $i < $t; ++$i) {
3307
            $a = self::random($two, $n_2);
3308
            $y = $a->modPow($r, $n);
3309
3310
            if (!$y->equals($one) && !$y->equals($n_1)) {
3311
                for ($j = 1; $j < $s && !$y->equals($n_1); ++$j) {
3312
                    $y = $y->modPow($two, $n);
3313
                    if ($y->equals($one)) {
3314
                        return false;
3315
                    }
3316
                }
3317
3318
                if (!$y->equals($n_1)) {
3319
                    return false;
3320
                }
3321
            }
3322
        }
3323
3324
        return true;
3325
    }
3326
3327
    /**
3328
     * Logical Left Shift.
3329
     *
3330
     * Shifts BigInteger's by $shift bits.
3331
     *
3332
     * @param int $shift
3333
     */
3334
    private function _lshift($shift)
3335
    {
3336
        if ($shift == 0) {
3337
            return;
3338
        }
3339
3340
        $num_digits = (int) ($shift / self::$base);
3341
        $shift %= self::$base;
3342
        $shift = 1 << $shift;
3343
3344
        $carry = 0;
3345
3346
        for ($i = 0; $i < count($this->value); ++$i) {
3347
            $temp = $this->value[$i] * $shift + $carry;
3348
            $carry = self::$base === 26 ? intval($temp / 0x4000000) : ($temp >> 31);
3349
            $this->value[$i] = (int) ($temp - $carry * self::$baseFull);
3350
        }
3351
3352
        if ($carry) {
3353
            $this->value[count($this->value)] = $carry;
3354
        }
3355
3356
        while ($num_digits--) {
3357
            array_unshift($this->value, 0);
3358
        }
3359
    }
3360
3361
    /**
3362
     * Logical Right Shift.
3363
     *
3364
     * Shifts BigInteger's by $shift bits.
3365
     *
3366
     * @param int $shift
3367
     */
3368
    private function _rshift($shift)
3369
    {
3370
        if ($shift == 0) {
3371
            return;
3372
        }
3373
3374
        $num_digits = (int) ($shift / self::$base);
3375
        $shift %= self::$base;
3376
        $carry_shift = self::$base - $shift;
3377
        $carry_mask = (1 << $shift) - 1;
3378
3379
        if ($num_digits) {
3380
            $this->value = array_slice($this->value, $num_digits);
3381
        }
3382
3383
        $carry = 0;
3384
3385
        for ($i = count($this->value) - 1; $i >= 0; --$i) {
3386
            $temp = $this->value[$i] >> $shift | $carry;
3387
            $carry = ($this->value[$i] & $carry_mask) << $carry_shift;
3388
            $this->value[$i] = $temp;
3389
        }
3390
3391
        $this->value = $this->_trim($this->value);
3392
    }
3393
3394
    /**
3395
     * Normalize.
3396
     *
3397
     * Removes leading zeros and truncates (if necessary) to maintain the appropriate precision
3398
     *
3399
     * @param \Jose\Util\BigInteger
3400
     *
3401
     * @return \Jose\Util\BigInteger
3402
     */
3403
    private function _normalize($result)
3404
    {
3405
        $result->precision = $this->precision;
3406
        $result->bitmask = $this->bitmask;
3407
3408
        switch (MATH_BIGINTEGER_MODE) {
3409
            case self::MODE_GMP:
3410
                if ($this->bitmask !== false) {
3411
                    $result->value = gmp_and($result->value, $result->bitmask->value);
3412
                }
3413
3414
                return $result;
3415
            case self::MODE_BCMATH:
3416
                if (!empty($result->bitmask->value)) {
3417
                    $result->value = bcmod($result->value, $result->bitmask->value);
3418
                }
3419
3420
                return $result;
3421
        }
3422
3423
        $value = &$result->value;
3424
3425
        if (!count($value)) {
3426
            return $result;
3427
        }
3428
3429
        $value = $this->_trim($value);
3430
3431
        if (!empty($result->bitmask->value)) {
3432
            $length = min(count($value), count($this->bitmask->value));
3433
            $value = array_slice($value, 0, $length);
3434
3435
            for ($i = 0; $i < $length; ++$i) {
3436
                $value[$i] = $value[$i] & $this->bitmask->value[$i];
3437
            }
3438
        }
3439
3440
        return $result;
3441
    }
3442
3443
    /**
3444
     * Trim.
3445
     *
3446
     * Removes leading zeros
3447
     *
3448
     * @param array $value
3449
     *
3450
     * @return \Jose\Util\BigInteger
3451
     */
3452
    private static function _trim($value)
3453
    {
3454
        for ($i = count($value) - 1; $i >= 0; --$i) {
3455
            if ($value[$i]) {
3456
                break;
3457
            }
3458
            unset($value[$i]);
3459
        }
3460
3461
        return $value;
3462
    }
3463
3464
    /**
3465
     * Array Repeat.
3466
     *
3467
     * @param $input Array
3468
     * @param $multiplier mixed
3469
     *
3470
     * @return array
3471
     */
3472
    private static function _array_repeat($input, $multiplier)
3473
    {
3474
        return ($multiplier) ? array_fill(0, $multiplier, $input) : [];
3475
    }
3476
3477
    /**
3478
     * Logical Left Shift.
3479
     *
3480
     * Shifts binary strings $shift bits, essentially multiplying by 2**$shift.
3481
     *
3482
     * @param $x String
3483
     * @param $shift Integer
3484
     *
3485
     * @return string
3486
     */
3487
    private static function _base256_lshift(&$x, $shift)
3488
    {
3489
        if ($shift == 0) {
3490
            return;
3491
        }
3492
3493
        $num_bytes = $shift >> 3; // eg. floor($shift/8)
3494
        $shift &= 7; // eg. $shift % 8
3495
3496
        $carry = 0;
3497
        for ($i = strlen($x) - 1; $i >= 0; --$i) {
3498
            $temp = ord($x[$i]) << $shift | $carry;
3499
            $x[$i] = chr($temp);
3500
            $carry = $temp >> 8;
3501
        }
3502
        $carry = ($carry != 0) ? chr($carry) : '';
3503
        $x = $carry.$x.str_repeat(chr(0), $num_bytes);
3504
    }
3505
3506
    /**
3507
     * Logical Right Shift.
3508
     *
3509
     * Shifts binary strings $shift bits, essentially dividing by 2**$shift and returning the remainder.
3510
     *
3511
     * @param $x String
3512
     * @param $shift Integer
3513
     *
3514
     * @return string
3515
     */
3516
    private static function _base256_rshift(&$x, $shift)
3517
    {
3518
        if ($shift == 0) {
3519
            $x = ltrim($x, chr(0));
3520
3521
            return '';
3522
        }
3523
3524
        $num_bytes = $shift >> 3; // eg. floor($shift/8)
3525
        $shift &= 7; // eg. $shift % 8
3526
3527
        $remainder = '';
3528
        if ($num_bytes) {
3529
            $start = $num_bytes > strlen($x) ? -strlen($x) : -$num_bytes;
3530
            $remainder = substr($x, $start);
3531
            $x = substr($x, 0, -$num_bytes);
3532
        }
3533
3534
        $carry = 0;
3535
        $carry_shift = 8 - $shift;
3536
        for ($i = 0; $i < strlen($x); ++$i) {
3537
            $temp = (ord($x[$i]) >> $shift) | $carry;
3538
            $carry = (ord($x[$i]) << $carry_shift) & 0xFF;
3539
            $x[$i] = chr($temp);
3540
        }
3541
        $x = ltrim($x, chr(0));
3542
3543
        $remainder = chr($carry >> $carry_shift).$remainder;
3544
3545
        return ltrim($remainder, chr(0));
3546
    }
3547
3548
    // one quirk about how the following functions are implemented is that PHP defines N to be an unsigned long
3549
    // at 32-bits, while java's longs are 64-bits.
3550
3551
    /**
3552
     * Converts 32-bit integers to bytes.
3553
     *
3554
     * @param int $x
3555
     *
3556
     * @return string
3557
     */
3558
    private static function _int2bytes($x)
3559
    {
3560
        return ltrim(pack('N', $x), chr(0));
3561
    }
3562
3563
    /**
3564
     * Converts bytes to 32-bit integers.
3565
     *
3566
     * @param string $x
3567
     *
3568
     * @return int
3569
     */
3570
    private static function _bytes2int($x)
3571
    {
3572
        $temp = unpack('Nint', str_pad($x, 4, chr(0), STR_PAD_LEFT));
3573
3574
        return $temp['int'];
3575
    }
3576
3577
    /**
3578
     * DER-encode an integer.
3579
     *
3580
     * The ability to DER-encode integers is needed to create RSA public keys for use with OpenSSL
3581
     *
3582
     * @param int $length
3583
     *
3584
     * @return string
3585
     */
3586
    private static function _encodeASN1Length($length)
3587
    {
3588
        if ($length <= 0x7F) {
3589
            return chr($length);
3590
        }
3591
3592
        $temp = ltrim(pack('N', $length), chr(0));
3593
3594
        return pack('Ca*', 0x80 | strlen($temp), $temp);
3595
    }
3596
3597
    /**
3598
     * Single digit division.
3599
     *
3600
     * Even if int64 is being used the division operator will return a float64 value
3601
     * if the dividend is not evenly divisible by the divisor. Since a float64 doesn't
3602
     * have the precision of int64 this is a problem so, when int64 is being used,
3603
     * we'll guarantee that the dividend is divisible by first subtracting the remainder.
3604
     *
3605
     * @param int $x
3606
     * @param int $y
3607
     *
3608
     * @return int
3609
     */
3610
    private static function _safe_divide($x, $y)
3611
    {
3612
        if (self::$base === 26) {
3613
            return (int) ($x / $y);
3614
        }
3615
3616
        // self::$base === 31
3617
        return ($x - ($x % $y)) / $y;
3618
    }
3619
}
3620