Failed Conditions
Push — PHPSecLib_Rid ( 6db4d2...2ba149 )
by Florent
03:21
created

src/Util/BigInteger.php (2 issues)

Labels
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
     * Karatsuba Cutoff.
59
     *
60
     * At what point do we switch between Karatsuba multiplication and schoolbook long multiplication?
61
     */
62
    const KARATSUBA_CUTOFF = 25;
63
64
    /**#@+
65
     * Static properties used by the pure-PHP implementation.
66
     *
67
     * @see __construct()
68
     */
69
    protected static $base;
70
    protected static $baseFull;
71
    protected static $maxDigit;
72
    protected static $msb;
73
74
    /**
75
     * $max10 in greatest $max10Len satisfying
76
     * $max10 = 10**$max10Len <= 2**$base.
77
     */
78
    protected static $max10;
79
80
    /**
81
     * $max10Len in greatest $max10Len satisfying
82
     * $max10 = 10**$max10Len <= 2**$base.
83
     */
84
    protected static $max10Len;
85
    protected static $maxDigit2;
86
    /**#@-*/
87
88
    /**
89
     * Holds the BigInteger's value.
90
     *
91
     * @var array
92
     */
93
    private $value;
94
95
    /**
96
     * Holds the BigInteger's magnitude.
97
     *
98
     * @var bool
99
     */
100
    private $is_negative = false;
101
102
    /**
103
     * Precision.
104
     */
105
    private $precision = -1;
106
107
    /**
108
     * Precision Bitmask.
109
     */
110
    private $bitmask = false;
111
112
    /**
113
     * Converts base-2, base-10, base-16, and binary strings (base-256) to BigIntegers.
114
     *
115
     * If the second parameter - $base - is negative, then it will be assumed that the number's are encoded using
116
     * two's compliment.  The sole exception to this is -10, which is treated the same as 10 is.
117
     *
118
     * Here's an example:
119
     * <code>
120
     * <?php
121
     *    $a = new \Jose\Util\in base-16
122
     *
123
     *    echo $a->toString(); // outputs 50
124
     * ?>
125
     * </code>
126
     *
127
     * @param $x base-10 number or base-$base number if $base set.
128
     * @param int $base
129
     *
130
     * @return \Jose\Util\BigInteger
131
     */
132
    public function __construct($x = 0, $base = 10)
133
    {
134
        if (extension_loaded('openssl') && !defined('MATH_BIGINTEGER_OPENSSL_DISABLE') && !defined('MATH_BIGINTEGER_OPENSSL_ENABLED')) {
135
            define('MATH_BIGINTEGER_OPENSSL_ENABLED', true);
136
        }
137
138
        switch (true) {
139
            case is_resource($x) && get_resource_type($x) == 'GMP integer':
140
                // PHP 5.6 switched GMP from using resources to objects
141
            case $x instanceof \GMP:
142
                $this->value = $x;
143
144
                return;
145
        }
146
        $this->value = gmp_init(0);
147
148
        // '0' counts as empty() but when the base is 256 '0' is equal to ord('0') or 48
149
        // '0' is the only value like this per http://php.net/empty
150
        if (empty($x) && (abs($base) != 256 || $x !== '0')) {
151
            return;
152
        }
153
154
        switch ($base) {
155
            case -256:
156
                if (ord($x[0]) & 0x80) {
157
                    $x = ~$x;
158
                    $this->is_negative = true;
159
                }
160
            case 256:
161
                $sign = $this->is_negative ? '-' : '';
162
                $this->value = gmp_init($sign.'0x'.bin2hex($x));
163
164
                if ($this->is_negative) {
165
                    $this->is_negative = false;
166
                    $temp = $this->add(new static('-1'));
167
                    $this->value = $temp->value;
168
                }
169
                break;
170
            case 16:
171
            case -16:
172
                if ($base > 0 && $x[0] == '-') {
173
                    $this->is_negative = true;
174
                    $x = substr($x, 1);
175
                }
176
177
                $x = preg_replace('#^(?:0x)?([A-Fa-f0-9]*).*#', '$1', $x);
178
179
                $is_negative = false;
180
                if ($base < 0 && hexdec($x[0]) >= 8) {
181
                    $this->is_negative = $is_negative = true;
182
                    $x = bin2hex(~hex2bin($x));
183
                }
184
185
            $temp = $this->is_negative ? '-0x'.$x : '0x'.$x;
186
            $this->value = gmp_init($temp);
187
            $this->is_negative = false;
188
189
                if ($is_negative) {
190
                    $temp = $this->add(new static('-1'));
191
                    $this->value = $temp->value;
192
                }
193
                break;
194
            case 10:
195
            case -10:
196
                // (?<!^)(?:-).*: find any -'s that aren't at the beginning and then any characters that follow that
197
                // (?<=^|-)0*: find any 0's that are preceded by the start of the string or by a - (ie. octals)
198
                // [^-0-9].*: find any non-numeric characters and then any characters that follow that
199
                $x = preg_replace('#(?<!^)(?:-).*|(?<=^|-)0*|[^-0-9].*#', '', $x);
200
201
                $this->value = gmp_init($x);
202
                break;
203
            case 2: // base-2 support originally implemented by Lluis Pamies - thanks!
204
            case -2:
205
                if ($base > 0 && $x[0] == '-') {
206
                    $this->is_negative = true;
207
                    $x = substr($x, 1);
208
                }
209
210
                $x = preg_replace('#^([01]*).*#', '$1', $x);
211
                $x = str_pad($x, strlen($x) + (3 * strlen($x)) % 4, 0, STR_PAD_LEFT);
212
213
                $str = '0x';
214
                while (strlen($x)) {
215
                    $part = substr($x, 0, 4);
216
                    $str .= dechex(bindec($part));
217
                    $x = substr($x, 4);
218
                }
219
220
                if ($this->is_negative) {
221
                    $str = '-'.$str;
222
                }
223
224
                $temp = new static($str, 8 * $base); // ie. either -16 or +16
225
                $this->value = $temp->value;
226
                $this->is_negative = $temp->is_negative;
227
228
                break;
229
            default:
230
                // base not supported, so we'll let $this == 0
231
        }
232
    }
233
234
    /**
235
     * Converts a BigInteger to a byte string (eg. base-256).
236
     *
237
     * Negative numbers are saved as positive numbers, unless $twos_compliment is set to true, at which point, they're
238
     * saved as two's compliment.
239
     *
240
     * Here's an example:
241
     * <code>
242
     * <?php
243
     *    $a = new \Jose\Util\ger('65');
244
     *
245
     *    echo $a->toBytes(); // outputs chr(65)
246
     * ?>
247
     * </code>
248
     *
249
     * @param bool $twos_compliment
250
     *
251
     * @return string
252
     *
253
     */
254
    public function toBytes($twos_compliment = false)
255
    {
256
        if ($twos_compliment) {
257
            $comparison = $this->compare(new static());
258
            if ($comparison == 0) {
259
                return $this->precision > 0 ? str_repeat(chr(0), ($this->precision + 1) >> 3) : '';
260
            }
261
262
            $temp = $comparison < 0 ? $this->add(new static(1)) : $this;
263
            $bytes = $temp->toBytes();
264
265
            if (empty($bytes)) { // eg. if the number we're trying to convert is -1
266
                $bytes = chr(0);
267
            }
268
269
            if (ord($bytes[0]) & 0x80) {
270
                $bytes = chr(0).$bytes;
271
            }
272
273
            return $comparison < 0 ? ~$bytes : $bytes;
274
        }
275
276
        if (gmp_cmp($this->value, gmp_init(0)) == 0) {
277
            return $this->precision > 0 ? str_repeat(chr(0), ($this->precision + 1) >> 3) : '';
278
        }
279
280
        $temp = gmp_strval(gmp_abs($this->value), 16);
281
        $temp = (strlen($temp) & 1) ? '0'.$temp : $temp;
282
        $temp = hex2bin($temp);
283
284
        return $this->precision > 0 ?
285
            substr(str_pad($temp, $this->precision >> 3, chr(0), STR_PAD_LEFT), -($this->precision >> 3)) :
286
            ltrim($temp, chr(0));
287
    }
288
289
    /**
290
     * Converts a BigInteger to a hex string (eg. base-16)).
291
     *
292
     * Negative numbers are saved as positive numbers, unless $twos_compliment is set to true, at which point, they're
293
     * saved as two's compliment.
294
     *
295
     * Here's an example:
296
     * <code>
297
     * <?php
298
     *    $a = new \Jose\Util\ger('65');
299
     *
300
     *    echo $a->toHex(); // outputs '41'
301
     * ?>
302
     * </code>
303
     *
304
     * @param bool $twos_compliment
305
     *
306
     * @return string
307
     *
308
     */
309
    public function toHex($twos_compliment = false)
310
    {
311
        return bin2hex($this->toBytes($twos_compliment));
312
    }
313
314
    /**
315
     * Converts a BigInteger to a bit string (eg. base-2).
316
     *
317
     * Negative numbers are saved as positive numbers, unless $twos_compliment is set to true, at which point, they're
318
     * saved as two's compliment.
319
     *
320
     * Here's an example:
321
     * <code>
322
     * <?php
323
     *    $a = new \Jose\Util\ger('65');
324
     *
325
     *    echo $a->toBits(); // outputs '1000001'
326
     * ?>
327
     * </code>
328
     *
329
     * @param bool $twos_compliment
330
     *
331
     * @return string
332
     *
333
     */
334
    public function toBits($twos_compliment = false)
335
    {
336
        $hex = $this->toHex($twos_compliment);
337
        $bits = '';
338
        for ($i = strlen($hex) - 8, $start = strlen($hex) & 7; $i >= $start; $i -= 8) {
339
            $bits = str_pad(decbin(hexdec(substr($hex, $i, 8))), 32, '0', STR_PAD_LEFT).$bits;
340
        }
341
        if ($start) { // hexdec('') == 0
342
            $bits = str_pad(decbin(hexdec(substr($hex, 0, $start))), 8, '0', STR_PAD_LEFT).$bits;
343
        }
344
        $result = $this->precision > 0 ? substr($bits, -$this->precision) : ltrim($bits, '0');
345
346
        if ($twos_compliment && $this->compare(new static()) > 0 && $this->precision <= 0) {
347
            return '0'.$result;
348
        }
349
350
        return $result;
351
    }
352
353
    /**
354
     * Adds two BigIntegers.
355
     *
356
     * Here's an example:
357
     * <code>
358
     * <?php
359
     *    $a = new \Jose\Util\ger('10');
360
     *    $b = new \Jose\Util\ger('20');
361
     *
362
     *    $c = $a->add($b);
363
     *
364
     *    echo $c->toString(); // outputs 30
365
     * ?>
366
     * </code>
367
     *
368
     * @param \Jose\Util\Integer $y
369
     *
370
     * @return \Jose\Util\BigInteger
371
     *
372
     */
373
    public function add(BigInteger $y)
374
    {
375
        $temp = new static();
376
        $temp->value = gmp_add($this->value, $y->value);
377
378
        return $this->_normalize($temp);
379
    }
380
381
    /**
382
     * Performs addition.
383
     *
384
     * @param array $x_value
385
     * @param bool  $x_negative
386
     * @param array $y_value
387
     * @param bool  $y_negative
388
     *
389
     * @return array
390
     */
391
    private static function _add($x_value, $x_negative, $y_value, $y_negative)
392
    {
393
        $x_size = count($x_value);
394
        $y_size = count($y_value);
395
396
        if ($x_size == 0) {
397
            return [
398
                self::VALUE => $y_value,
399
                self::SIGN  => $y_negative,
400
            ];
401
        } elseif ($y_size == 0) {
402
            return [
403
                self::VALUE => $x_value,
404
                self::SIGN  => $x_negative,
405
            ];
406
        }
407
408
        // subtract, if appropriate
409
        if ($x_negative != $y_negative) {
410
            if ($x_value == $y_value) {
411
                return [
412
                    self::VALUE => [],
413
                    self::SIGN  => false,
414
                ];
415
            }
416
417
            $temp = self::_subtract($x_value, false, $y_value, false);
418
            $temp[self::SIGN] = self::_compare($x_value, false, $y_value, false) > 0 ?
419
                $x_negative : $y_negative;
420
421
            return $temp;
422
        }
423
424
        if ($x_size < $y_size) {
425
            $size = $x_size;
426
            $value = $y_value;
427
        } else {
428
            $size = $y_size;
429
            $value = $x_value;
430
        }
431
432
        $value[count($value)] = 0; // just in case the carry adds an extra digit
433
434
        $carry = 0;
435
        for ($i = 0, $j = 1; $j < $size; $i += 2, $j += 2) {
436
            $sum = $x_value[$j] * self::$baseFull + $x_value[$i] + $y_value[$j] * self::$baseFull + $y_value[$i] + $carry;
437
            $carry = $sum >= self::$maxDigit2; // eg. floor($sum / 2**52); only possible values (in any base) are 0 and 1
438
            $sum = $carry ? $sum - self::$maxDigit2 : $sum;
439
440
            $temp = self::$base === 26 ? intval($sum / 0x4000000) : ($sum >> 31);
441
442
            $value[$i] = (int) ($sum - self::$baseFull * $temp); // eg. a faster alternative to fmod($sum, 0x4000000)
443
            $value[$j] = $temp;
444
        }
445
446
        if ($j == $size) { // ie. if $y_size is odd
447
            $sum = $x_value[$i] + $y_value[$i] + $carry;
448
            $carry = $sum >= self::$baseFull;
449
            $value[$i] = $carry ? $sum - self::$baseFull : $sum;
450
            ++$i; // ie. let $i = $j since we've just done $value[$i]
451
        }
452
453
        if ($carry) {
454
            for (; $value[$i] == self::$maxDigit; ++$i) {
455
                $value[$i] = 0;
456
            }
457
            ++$value[$i];
458
        }
459
460
        return [
461
            self::VALUE => self::_trim($value),
462
            self::SIGN  => $x_negative,
463
        ];
464
    }
465
466
    /**
467
     * Subtracts two BigIntegers.
468
     *
469
     * Here's an example:
470
     * <code>
471
     * <?php
472
     *    $a = new \Jose\Util\ger('10');
473
     *    $b = new \Jose\Util\ger('20');
474
     *
475
     *    $c = $a->subtract($b);
476
     *
477
     *    echo $c->toString(); // outputs -10
478
     * ?>
479
     * </code>
480
     *
481
     * @param \Jose\Util\Integer $y
482
     *
483
     * @return \Jose\Util\BigInteger
484
     *
485
     */
486
    public function subtract(BigInteger $y)
487
    {
488
        $temp = new static();
489
        $temp->value = gmp_sub($this->value, $y->value);
490
491
        return $this->_normalize($temp);
492
    }
493
494
    /**
495
     * Performs subtraction.
496
     *
497
     * @param array $x_value
498
     * @param bool  $x_negative
499
     * @param array $y_value
500
     * @param bool  $y_negative
501
     *
502
     * @return array
503
     */
504
    private static function _subtract($x_value, $x_negative, $y_value, $y_negative)
505
    {
506
        $x_size = count($x_value);
507
        $y_size = count($y_value);
508
509
        if ($x_size == 0) {
510
            return [
511
                self::VALUE => $y_value,
512
                self::SIGN  => !$y_negative,
513
            ];
514
        } elseif ($y_size == 0) {
515
            return [
516
                self::VALUE => $x_value,
517
                self::SIGN  => $x_negative,
518
            ];
519
        }
520
521
        // add, if appropriate (ie. -$x - +$y or +$x - -$y)
522
        if ($x_negative != $y_negative) {
523
            $temp = self::_add($x_value, false, $y_value, false);
524
            $temp[self::SIGN] = $x_negative;
525
526
            return $temp;
527
        }
528
529
        $diff = self::_compare($x_value, $x_negative, $y_value, $y_negative);
530
531
        if (!$diff) {
532
            return [
533
                self::VALUE => [],
534
                self::SIGN  => false,
535
            ];
536
        }
537
538
        // switch $x and $y around, if appropriate.
539
        if ((!$x_negative && $diff < 0) || ($x_negative && $diff > 0)) {
540
            $temp = $x_value;
541
            $x_value = $y_value;
542
            $y_value = $temp;
543
544
            $x_negative = !$x_negative;
545
546
            $x_size = count($x_value);
547
            $y_size = count($y_value);
548
        }
549
550
        // at this point, $x_value should be at least as big as - if not bigger than - $y_value
551
552
        $carry = 0;
553
        for ($i = 0, $j = 1; $j < $y_size; $i += 2, $j += 2) {
554
            $sum = $x_value[$j] * self::$baseFull + $x_value[$i] - $y_value[$j] * self::$baseFull - $y_value[$i] - $carry;
555
            $carry = $sum < 0; // eg. floor($sum / 2**52); only possible values (in any base) are 0 and 1
556
            $sum = $carry ? $sum + self::$maxDigit2 : $sum;
557
558
            $temp = self::$base === 26 ? intval($sum / 0x4000000) : ($sum >> 31);
559
560
            $x_value[$i] = (int) ($sum - self::$baseFull * $temp);
561
            $x_value[$j] = $temp;
562
        }
563
564
        if ($j == $y_size) { // ie. if $y_size is odd
565
            $sum = $x_value[$i] - $y_value[$i] - $carry;
566
            $carry = $sum < 0;
567
            $x_value[$i] = $carry ? $sum + self::$baseFull : $sum;
568
            ++$i;
569
        }
570
571
        if ($carry) {
572
            for (; !$x_value[$i]; ++$i) {
573
                $x_value[$i] = self::$maxDigit;
574
            }
575
            --$x_value[$i];
576
        }
577
578
        return [
579
            self::VALUE => self::_trim($x_value),
580
            self::SIGN  => $x_negative,
581
        ];
582
    }
583
584
    /**
585
     * Multiplies two BigIntegers.
586
     *
587
     * Here's an example:
588
     * <code>
589
     * <?php
590
     *    $a = new \Jose\Util\ger('10');
591
     *    $b = new \Jose\Util\ger('20');
592
     *
593
     *    $c = $a->multiply($b);
594
     *
595
     *    echo $c->toString(); // outputs 200
596
     * ?>
597
     * </code>
598
     *
599
     * @param \Jose\Util\Integer $x
600
     *
601
     * @return \Jose\Util\BigInteger
602
     */
603
    public function multiply(BigInteger $x)
604
    {
605
        $temp = new static();
606
        $temp->value = gmp_mul($this->value, $x->value);
607
608
        return $this->_normalize($temp);
609
    }
610
611
    /**
612
     * Performs multiplication.
613
     *
614
     * @param array $x_value
615
     * @param bool  $x_negative
616
     * @param array $y_value
617
     * @param bool  $y_negative
618
     *
619
     * @return array
620
     */
621
    private static function _multiply($x_value, $x_negative, $y_value, $y_negative)
622
    {
623
        $x_length = count($x_value);
624
        $y_length = count($y_value);
625
626
        if (!$x_length || !$y_length) { // a 0 is being multiplied
627
            return [
628
                self::VALUE => [],
629
                self::SIGN  => false,
630
            ];
631
        }
632
633
        return [
634
            self::VALUE => min($x_length, $y_length) < 2 * self::KARATSUBA_CUTOFF ?
635
                self::_trim(self::_regularMultiply($x_value, $y_value)) :
636
                self::_trim(self::_karatsuba($x_value, $y_value)),
637
            self::SIGN => $x_negative != $y_negative,
638
        ];
639
    }
640
641
    /**
642
     * Performs long multiplication on two BigIntegers.
643
     *
644
     * Modeled after 'multiply' in MutableBigInteger.java.
645
     *
646
     * @param array $x_value
647
     * @param array $y_value
648
     *
649
     * @return array
650
     */
651
    private static function _regularMultiply($x_value, $y_value)
652
    {
653
        $x_length = count($x_value);
654
        $y_length = count($y_value);
655
656
        if (!$x_length || !$y_length) { // a 0 is being multiplied
657
            return [];
658
        }
659
660
        if ($x_length < $y_length) {
661
            $temp = $x_value;
662
            $x_value = $y_value;
663
            $y_value = $temp;
664
665
            $x_length = count($x_value);
666
            $y_length = count($y_value);
667
        }
668
669
        $product_value = self::_array_repeat(0, $x_length + $y_length);
670
671
        // the following for loop could be removed if the for loop following it
672
        // (the one with nested for loops) initially set $i to 0, but
673
        // doing so would also make the result in one set of unnecessary adds,
674
        // since on the outermost loops first pass, $product->value[$k] is going
675
        // to always be 0
676
677
        $carry = 0;
678
679
        for ($j = 0; $j < $x_length; ++$j) { // ie. $i = 0
680
            $temp = $x_value[$j] * $y_value[0] + $carry; // $product_value[$k] == 0
681
            $carry = self::$base === 26 ? intval($temp / 0x4000000) : ($temp >> 31);
682
            $product_value[$j] = (int) ($temp - self::$baseFull * $carry);
683
        }
684
685
        $product_value[$j] = $carry;
686
687
        // the above for loop is what the previous comment was talking about.  the
688
        // following for loop is the "one with nested for loops"
689
        for ($i = 1; $i < $y_length; ++$i) {
690
            $carry = 0;
691
692
            for ($j = 0, $k = $i; $j < $x_length; ++$j, ++$k) {
693
                $temp = $product_value[$k] + $x_value[$j] * $y_value[$i] + $carry;
694
                $carry = self::$base === 26 ? intval($temp / 0x4000000) : ($temp >> 31);
695
                $product_value[$k] = (int) ($temp - self::$baseFull * $carry);
696
            }
697
698
            $product_value[$k] = $carry;
699
        }
700
701
        return $product_value;
702
    }
703
704
    /**
705
     * Performs Karatsuba multiplication on two BigIntegers.
706
     *
707
     * See {@link http://en.wikipedia.org/wiki/Karatsuba_algorithm Karatsuba algorithm} and
708
     * {@link http://math.libtomcrypt.com/files/tommath.pdf#page=120 MPM 5.2.3}.
709
     *
710
     * @param array $x_value
711
     * @param array $y_value
712
     *
713
     * @return array
714
     */
715
    private static function _karatsuba($x_value, $y_value)
716
    {
717
        $m = min(count($x_value) >> 1, count($y_value) >> 1);
718
719
        if ($m < self::KARATSUBA_CUTOFF) {
720
            return self::_regularMultiply($x_value, $y_value);
721
        }
722
723
        $x1 = array_slice($x_value, $m);
724
        $x0 = array_slice($x_value, 0, $m);
725
        $y1 = array_slice($y_value, $m);
726
        $y0 = array_slice($y_value, 0, $m);
727
728
        $z2 = self::_karatsuba($x1, $y1);
729
        $z0 = self::_karatsuba($x0, $y0);
730
731
        $z1 = self::_add($x1, false, $x0, false);
732
        $temp = self::_add($y1, false, $y0, false);
733
        $z1 = self::_karatsuba($z1[self::VALUE], $temp[self::VALUE]);
734
        $temp = self::_add($z2, false, $z0, false);
735
        $z1 = self::_subtract($z1, false, $temp[self::VALUE], false);
736
737
        $z2 = array_merge(array_fill(0, 2 * $m, 0), $z2);
738
        $z1[self::VALUE] = array_merge(array_fill(0, $m, 0), $z1[self::VALUE]);
739
740
        $xy = self::_add($z2, false, $z1[self::VALUE], $z1[self::SIGN]);
741
        $xy = self::_add($xy[self::VALUE], $xy[self::SIGN], $z0, false);
742
743
        return $xy[self::VALUE];
744
    }
745
746
    /**
747
     * Performs squaring.
748
     *
749
     * @param array $x
750
     *
751
     * @return array
752
     */
753
    private static function _square($x = false)
754
    {
755
        return count($x) < 2 * self::KARATSUBA_CUTOFF ?
756
            self::_trim(self::_baseSquare($x)) :
757
            self::_trim(self::_karatsubaSquare($x));
758
    }
759
760
    /**
761
     * Performs traditional squaring on two BigIntegers.
762
     *
763
     * Squaring can be done faster than multiplying a number by itself can be.  See
764
     * {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=7 HAC 14.2.4} /
765
     * {@link http://math.libtomcrypt.com/files/tommath.pdf#page=141 MPM 5.3} for more information.
766
     *
767
     * @param array $value
768
     *
769
     * @return array
770
     */
771
    private static function _baseSquare($value)
772
    {
773
        if (empty($value)) {
774
            return [];
775
        }
776
        $square_value = self::_array_repeat(0, 2 * count($value));
777
778
        for ($i = 0, $max_index = count($value) - 1; $i <= $max_index; ++$i) {
779
            $i2 = $i << 1;
780
781
            $temp = $square_value[$i2] + $value[$i] * $value[$i];
782
            $carry = self::$base === 26 ? intval($temp / 0x4000000) : ($temp >> 31);
783
            $square_value[$i2] = (int) ($temp - self::$baseFull * $carry);
784
785
            // note how we start from $i+1 instead of 0 as we do in multiplication.
786
            for ($j = $i + 1, $k = $i2 + 1; $j <= $max_index; ++$j, ++$k) {
787
                $temp = $square_value[$k] + 2 * $value[$j] * $value[$i] + $carry;
788
                $carry = self::$base === 26 ? intval($temp / 0x4000000) : ($temp >> 31);
789
                $square_value[$k] = (int) ($temp - self::$baseFull * $carry);
790
            }
791
792
            // the following line can yield values larger 2**15.  at this point, PHP should switch
793
            // over to floats.
794
            $square_value[$i + $max_index + 1] = $carry;
795
        }
796
797
        return $square_value;
798
    }
799
800
    /**
801
     * Performs Karatsuba "squaring" on two BigIntegers.
802
     *
803
     * See {@link http://en.wikipedia.org/wiki/Karatsuba_algorithm Karatsuba algorithm} and
804
     * {@link http://math.libtomcrypt.com/files/tommath.pdf#page=151 MPM 5.3.4}.
805
     *
806
     * @param array $value
807
     *
808
     * @return array
809
     */
810
    private static function _karatsubaSquare($value)
811
    {
812
        $m = count($value) >> 1;
813
814
        if ($m < self::KARATSUBA_CUTOFF) {
815
            return self::_baseSquare($value);
816
        }
817
818
        $x1 = array_slice($value, $m);
819
        $x0 = array_slice($value, 0, $m);
820
821
        $z2 = self::_karatsubaSquare($x1);
822
        $z0 = self::_karatsubaSquare($x0);
823
824
        $z1 = self::_add($x1, false, $x0, false);
825
        $z1 = self::_karatsubaSquare($z1[self::VALUE]);
826
        $temp = self::_add($z2, false, $z0, false);
827
        $z1 = self::_subtract($z1, false, $temp[self::VALUE], false);
828
829
        $z2 = array_merge(array_fill(0, 2 * $m, 0), $z2);
830
        $z1[self::VALUE] = array_merge(array_fill(0, $m, 0), $z1[self::VALUE]);
831
832
        $xx = self::_add($z2, false, $z1[self::VALUE], $z1[self::SIGN]);
833
        $xx = self::_add($xx[self::VALUE], $xx[self::SIGN], $z0, false);
834
835
        return $xx[self::VALUE];
836
    }
837
838
    /**
839
     * Divides two BigIntegers.
840
     *
841
     * Returns an array whose first element contains the quotient and whose second element contains the
842
     * "common residue".  If the remainder would be positive, the "common residue" and the remainder are the
843
     * same.  If the remainder would be negative, the "common residue" is equal to the sum of the remainder
844
     * and the divisor (basically, the "common residue" is the first positive modulo).
845
     *
846
     * Here's an example:
847
     * <code>
848
     * <?php
849
     *    $a = new \Jose\Util\ger('10');
850
     *    $b = new \Jose\Util\ger('20');
851
     *
852
     *    list($quotient, $remainder) = $a->divide($b);
853
     *
854
     *    echo $quotient->toString(); // outputs 0
855
     *    echo "\r\n";
856
     *    echo $remainder->toString(); // outputs 10
857
     * ?>
858
     * </code>
859
     *
860
     * @param \Jose\Util\Integer $y
861
     *
862
     * @return array
863
     *
864
     */
865
    public function divide(BigInteger $y)
866
    {
867
        $quotient = new static();
868
        $remainder = new static();
869
870
        list($quotient->value, $remainder->value) = gmp_div_qr($this->value, $y->value);
871
872
        if (gmp_sign($remainder->value) < 0) {
873
            $remainder->value = gmp_add($remainder->value, gmp_abs($y->value));
874
        }
875
876
        return [$this->_normalize($quotient), $this->_normalize($remainder)];
877
    }
878
879
    /**
880
     * Divides a BigInteger by a regular integer.
881
     *
882
     * abc / x = a00 / x + b0 / x + c / x
883
     *
884
     * @param array $dividend
885
     * @param array $divisor
886
     *
887
     * @return array
888
     */
889
    private static function _divide_digit($dividend, $divisor)
890
    {
891
        $carry = 0;
892
        $result = [];
893
894
        for ($i = count($dividend) - 1; $i >= 0; --$i) {
895
            $temp = self::$baseFull * $carry + $dividend[$i];
896
            $result[$i] = self::_safe_divide($temp, $divisor);
897
            $carry = (int) ($temp - $divisor * $result[$i]);
898
        }
899
900
        return [$result, $carry];
901
    }
902
903
    /**
904
     * Performs modular exponentiation.
905
     *
906
     * Here's an example:
907
     * <code>
908
     * <?php
909
     *    $a = new \Jose\Util\ger('10');
910
     *    $b = new \Jose\Util\ger('20');
911
     *    $c = new \Jose\Util\ger('30');
912
     *
913
     *    $c = $a->modPow($b, $c);
914
     *
915
     *    echo $c->toString(); // outputs 10
916
     * ?>
917
     * </code>
918
     *
919
     * @param \Jose\Util\Integer $e
920
     * @param \Jose\Util\Integer $n
921
     *
922
     * @return \Jose\Util\BigInteger
923
     *
924
     *    and although the approach involving repeated squaring does vastly better, it, too, is impractical
925
     *    for our purposes.  The reason being that division - by far the most complicated and time-consuming
926
     *    of the basic operations (eg. +,-,*,/) - occurs multiple times within it.
927
     *
928
     *    Modular reductions resolve this issue.  Although an individual modular reduction takes more time
929
     *    then an individual division, when performed in succession (with the same modulo), they're a lot faster.
930
     *
931
     *    The two most commonly used modular reductions are Barrett and Montgomery reduction.  Montgomery reduction,
932
     *    although faster, only works when the gcd of the modulo and of the base being used is 1.  In RSA, when the
933
     *    base is a power of two, the modulo - a product of two primes - is always going to have a gcd of 1 (because
934
     *    the product of two odd numbers is odd), but what about when RSA isn't used?
935
     *
936
     *    In contrast, Barrett reduction has no such constraint.  As such, some bigint implementations perform a
937
     *    Barrett reduction after every operation in the modpow function.  Others perform Barrett reductions when the
938
     *    modulo is even and Montgomery reductions when the modulo is odd.  BigInteger.java's modPow method, however,
939
     *    uses a trick involving the Chinese Remainder Theorem to factor the even modulo into two numbers - one odd and
940
     *    the other, a power of two - and recombine them, later.  This is the method that this modPow function uses.
941
     *    {@link http://islab.oregonstate.edu/papers/j34monex.pdf Montgomery Reduction with Even Modulus} elaborates.
942
     */
943
    public function modPow(BigInteger $e, BigInteger $n)
944
    {
945
        $n = $this->bitmask !== false && $this->bitmask->compare($n) < 0 ? $this->bitmask : $n->abs();
946
947
        if ($e->compare(new static()) < 0) {
948
            $e = $e->abs();
949
950
            $temp = $this->modInverse($n);
951
            if ($temp === false) {
952
                return false;
953
            }
954
955
            return $this->_normalize($temp->modPow($e, $n));
956
        }
957
958
            $temp = new static();
959
            $temp->value = gmp_powm($this->value, $e->value, $n->value);
960
961
            return $this->_normalize($temp);
962
    }
963
964
    /**
965
     * Performs modular exponentiation.
966
     *
967
     * Alias for modPow().
968
     *
969
     * @param \Jose\Util\Integer $e
970
     * @param \Jose\Util\Integer $n
971
     *
972
     * @return \Jose\Util\BigInteger
973
     */
974
    public function powMod(BigInteger $e, BigInteger $n)
975
    {
976
        return $this->modPow($e, $n);
977
    }
978
979
    /**
980
     * Barrett Modular Reduction.
981
     *
982
     * See {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=14 HAC 14.3.3} /
983
     * {@link http://math.libtomcrypt.com/files/tommath.pdf#page=165 MPM 6.2.5} for more information.  Modified slightly,
984
     * so as not to require negative numbers (initially, this script didn't support negative numbers).
985
     *
986
     * Employs "folding", as described at
987
     * {@link http://www.cosic.esat.kuleuven.be/publications/thesis-149.pdf#page=66 thesis-149.pdf#page=66}.  To quote from
988
     * 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."
989
     *
990
     * Unfortunately, the "Barrett Reduction with Folding" algorithm described in thesis-149.pdf is not, as written, all that
991
     * usable on account of (1) its not using reasonable radix points as discussed in
992
     * {@link http://math.libtomcrypt.com/files/tommath.pdf#page=162 MPM 6.2.2} and (2) the fact that, even with reasonable
993
     * radix points, it only works when there are an even number of digits in the denominator.  The reason for (2) is that
994
     * (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
995
     * comments for details.
996
     *
997
     * @param array $n
998
     * @param array $m
999
     *
1000
     * @return array
1001
     */
1002
    private static function _barrett($n, $m)
1003
    {
1004
        static $cache = [
1005
            self::VARIABLE => [],
1006
            self::DATA     => [],
1007
        ];
1008
1009
        $m_length = count($m);
1010
1011
        // if (self::_compare($n, self::_square($m)) >= 0) {
1012
        if (count($n) > 2 * $m_length) {
1013
            $lhs = new static();
1014
            $rhs = new static();
1015
            $lhs->value = $n;
1016
            $rhs->value = $m;
1017
            list(, $temp) = $lhs->divide($rhs);
1018
1019
            return $temp->value;
1020
        }
1021
1022
        // if (m.length >> 1) + 2 <= m.length then m is too small and n can't be reduced
1023
        if ($m_length < 5) {
1024
            return self::_regularBarrett($n, $m);
1025
        }
1026
1027
        // n = 2 * m.length
1028
1029
        if (($key = array_search($m, $cache[self::VARIABLE])) === false) {
1030
            $key = count($cache[self::VARIABLE]);
1031
            $cache[self::VARIABLE][] = $m;
1032
1033
            $lhs = new static();
1034
            $lhs_value = &$lhs->value;
1035
            $lhs_value = self::_array_repeat(0, $m_length + ($m_length >> 1));
1036
            $lhs_value[] = 1;
1037
            $rhs = new static();
1038
            $rhs->value = $m;
1039
1040
            list($u, $m1) = $lhs->divide($rhs);
1041
            $u = $u->value;
1042
            $m1 = $m1->value;
1043
1044
            $cache[self::DATA][] = [
1045
                'u'  => $u, // m.length >> 1 (technically (m.length >> 1) + 1)
1046
                'm1' => $m1, // m.length
1047
            ];
1048
        } else {
1049
            extract($cache[self::DATA][$key]);
1050
        }
1051
1052
        $cutoff = $m_length + ($m_length >> 1);
1053
        $lsd = array_slice($n, 0, $cutoff); // m.length + (m.length >> 1)
1054
        $msd = array_slice($n, $cutoff);    // m.length >> 1
1055
        $lsd = self::_trim($lsd);
1056
        $temp = self::_multiply($msd, false, $m1, false);
1057
        $n = self::_add($lsd, false, $temp[self::VALUE], false); // m.length + (m.length >> 1) + 1
1058
1059
        if ($m_length & 1) {
1060
            return self::_regularBarrett($n[self::VALUE], $m);
1061
        }
1062
1063
        // (m.length + (m.length >> 1) + 1) - (m.length - 1) == (m.length >> 1) + 2
1064
        $temp = array_slice($n[self::VALUE], $m_length - 1);
1065
        // if even: ((m.length >> 1) + 2) + (m.length >> 1) == m.length + 2
1066
        // if odd:  ((m.length >> 1) + 2) + (m.length >> 1) == (m.length - 1) + 2 == m.length + 1
1067
        $temp = self::_multiply($temp, false, $u, false);
1068
        // if even: (m.length + 2) - ((m.length >> 1) + 1) = m.length - (m.length >> 1) + 1
1069
        // if odd:  (m.length + 1) - ((m.length >> 1) + 1) = m.length - (m.length >> 1)
1070
        $temp = array_slice($temp[self::VALUE], ($m_length >> 1) + 1);
1071
        // if even: (m.length - (m.length >> 1) + 1) + m.length = 2 * m.length - (m.length >> 1) + 1
1072
        // if odd:  (m.length - (m.length >> 1)) + m.length     = 2 * m.length - (m.length >> 1)
1073
        $temp = self::_multiply($temp, false, $m, false);
1074
1075
        // at this point, if m had an odd number of digits, we'd be subtracting a 2 * m.length - (m.length >> 1) digit
1076
        // number from a m.length + (m.length >> 1) + 1 digit number.  ie. there'd be an extra digit and the while loop
1077
        // following this comment would loop a lot (hence our calling _regularBarrett() in that situation).
1078
1079
        $result = self::_subtract($n[self::VALUE], false, $temp[self::VALUE], false);
1080
1081
        while (self::_compare($result[self::VALUE], $result[self::SIGN], $m, false) >= 0) {
1082
            $result = self::_subtract($result[self::VALUE], $result[self::SIGN], $m, false);
1083
        }
1084
1085
        return $result[self::VALUE];
1086
    }
1087
1088
    /**
1089
     * (Regular) Barrett Modular Reduction.
1090
     *
1091
     * For numbers with more than four digits BigInteger::_barrett() is faster.  The difference between that and this
1092
     * is that this function does not fold the denominator into a smaller form.
1093
     *
1094
     * @param array $x
1095
     * @param array $n
1096
     *
1097
     * @return array
1098
     */
1099
    private static function _regularBarrett($x, $n)
1100
    {
1101
        static $cache = [
1102
            self::VARIABLE => [],
1103
            self::DATA     => [],
1104
        ];
1105
1106
        $n_length = count($n);
1107
1108
        if (count($x) > 2 * $n_length) {
1109
            $lhs = new static();
1110
            $rhs = new static();
1111
            $lhs->value = $x;
1112
            $rhs->value = $n;
1113
            list(, $temp) = $lhs->divide($rhs);
1114
1115
            return $temp->value;
1116
        }
1117
1118
        if (($key = array_search($n, $cache[self::VARIABLE])) === false) {
1119
            $key = count($cache[self::VARIABLE]);
1120
            $cache[self::VARIABLE][] = $n;
1121
            $lhs = new static();
1122
            $lhs_value = &$lhs->value;
1123
            $lhs_value = self::_array_repeat(0, 2 * $n_length);
1124
            $lhs_value[] = 1;
1125
            $rhs = new static();
1126
            $rhs->value = $n;
1127
            list($temp) = $lhs->divide($rhs); // m.length
1128
            $cache[self::DATA][] = $temp->value;
1129
        }
1130
1131
        // 2 * m.length - (m.length - 1) = m.length + 1
1132
        $temp = array_slice($x, $n_length - 1);
1133
        // (m.length + 1) + m.length = 2 * m.length + 1
1134
        $temp = self::_multiply($temp, false, $cache[self::DATA][$key], false);
1135
        // (2 * m.length + 1) - (m.length - 1) = m.length + 2
1136
        $temp = array_slice($temp[self::VALUE], $n_length + 1);
1137
1138
        // m.length + 1
1139
        $result = array_slice($x, 0, $n_length + 1);
1140
        // m.length + 1
1141
        $temp = self::_multiplyLower($temp, false, $n, false, $n_length + 1);
1142
        // $temp == array_slice(self::_multiply($temp, false, $n, false)->value, 0, $n_length + 1)
1143
1144
        if (self::_compare($result, false, $temp[self::VALUE], $temp[self::SIGN]) < 0) {
1145
            $corrector_value = self::_array_repeat(0, $n_length + 1);
1146
            $corrector_value[count($corrector_value)] = 1;
1147
            $result = self::_add($result, false, $corrector_value, false);
1148
            $result = $result[self::VALUE];
1149
        }
1150
1151
        // at this point, we're subtracting a number with m.length + 1 digits from another number with m.length + 1 digits
1152
        $result = self::_subtract($result, false, $temp[self::VALUE], $temp[self::SIGN]);
1153
        while (self::_compare($result[self::VALUE], $result[self::SIGN], $n, false) > 0) {
1154
            $result = self::_subtract($result[self::VALUE], $result[self::SIGN], $n, false);
1155
        }
1156
1157
        return $result[self::VALUE];
1158
    }
1159
1160
    /**
1161
     * Performs long multiplication up to $stop digits.
1162
     *
1163
     * If you're going to be doing array_slice($product->value, 0, $stop), some cycles can be saved.
1164
     *
1165
     * @param array $x_value
1166
     * @param bool  $x_negative
1167
     * @param array $y_value
1168
     * @param bool  $y_negative
1169
     * @param int   $stop
1170
     *
1171
     * @return array
1172
     */
1173
    private static function _multiplyLower($x_value, $x_negative, $y_value, $y_negative, $stop)
1174
    {
1175
        $x_length = count($x_value);
1176
        $y_length = count($y_value);
1177
1178
        if (!$x_length || !$y_length) { // a 0 is being multiplied
1179
            return [
1180
                self::VALUE => [],
1181
                self::SIGN  => false,
1182
            ];
1183
        }
1184
1185
        if ($x_length < $y_length) {
1186
            $temp = $x_value;
1187
            $x_value = $y_value;
1188
            $y_value = $temp;
1189
1190
            $x_length = count($x_value);
1191
            $y_length = count($y_value);
1192
        }
1193
1194
        $product_value = self::_array_repeat(0, $x_length + $y_length);
1195
1196
        // the following for loop could be removed if the for loop following it
1197
        // (the one with nested for loops) initially set $i to 0, but
1198
        // doing so would also make the result in one set of unnecessary adds,
1199
        // since on the outermost loops first pass, $product->value[$k] is going
1200
        // to always be 0
1201
1202
        $carry = 0;
1203
1204
        for ($j = 0; $j < $x_length; ++$j) { // ie. $i = 0, $k = $i
1205
            $temp = $x_value[$j] * $y_value[0] + $carry; // $product_value[$k] == 0
1206
            $carry = self::$base === 26 ? intval($temp / 0x4000000) : ($temp >> 31);
1207
            $product_value[$j] = (int) ($temp - self::$baseFull * $carry);
1208
        }
1209
1210
        if ($j < $stop) {
1211
            $product_value[$j] = $carry;
1212
        }
1213
1214
        // the above for loop is what the previous comment was talking about.  the
1215
        // following for loop is the "one with nested for loops"
1216
1217
        for ($i = 1; $i < $y_length; ++$i) {
1218
            $carry = 0;
1219
1220
            for ($j = 0, $k = $i; $j < $x_length && $k < $stop; ++$j, ++$k) {
1221
                $temp = $product_value[$k] + $x_value[$j] * $y_value[$i] + $carry;
1222
                $carry = self::$base === 26 ? intval($temp / 0x4000000) : ($temp >> 31);
1223
                $product_value[$k] = (int) ($temp - self::$baseFull * $carry);
1224
            }
1225
1226
            if ($k < $stop) {
1227
                $product_value[$k] = $carry;
1228
            }
1229
        }
1230
1231
        return [
1232
            self::VALUE => self::_trim($product_value),
1233
            self::SIGN  => $x_negative != $y_negative,
1234
        ];
1235
    }
1236
1237
    /**
1238
     * Montgomery Modular Reduction.
1239
     *
1240
     * ($x->_prepMontgomery($n))->_montgomery($n) yields $x % $n.
1241
     * {@link http://math.libtomcrypt.com/files/tommath.pdf#page=170 MPM 6.3} provides insights on how this can be
1242
     * improved upon (basically, by using the comba method).  gcd($n, 2) must be equal to one for this function
1243
     * to work correctly.
1244
     *
1245
     * @param array $x
1246
     * @param array $n
1247
     *
1248
     * @return array
1249
     */
1250
    private static function _montgomery($x, $n)
1251
    {
1252
        static $cache = [
1253
            self::VARIABLE => [],
1254
            self::DATA     => [],
1255
        ];
1256
1257
        if (($key = array_search($n, $cache[self::VARIABLE])) === false) {
1258
            $key = count($cache[self::VARIABLE]);
1259
            $cache[self::VARIABLE][] = $x;
1260
            $cache[self::DATA][] = self::_modInverse67108864($n);
1261
        }
1262
1263
        $k = count($n);
1264
1265
        $result = [self::VALUE => $x];
1266
1267
        for ($i = 0; $i < $k; ++$i) {
1268
            $temp = $result[self::VALUE][$i] * $cache[self::DATA][$key];
1269
            $temp = $temp - self::$baseFull * (self::$base === 26 ? intval($temp / 0x4000000) : ($temp >> 31));
1270
            $temp = self::_regularMultiply([$temp], $n);
1271
            $temp = array_merge($this->_array_repeat(0, $i), $temp);
1272
            $result = self::_add($result[self::VALUE], false, $temp, false);
1273
        }
1274
1275
        $result[self::VALUE] = array_slice($result[self::VALUE], $k);
1276
1277
        if (self::_compare($result, false, $n, false) >= 0) {
1278
            $result = self::_subtract($result[self::VALUE], false, $n, false);
1279
        }
1280
1281
        return $result[self::VALUE];
1282
    }
1283
1284
    /**
1285
     * Modular Inverse of a number mod 2**26 (eg. 67108864).
1286
     *
1287
     * Based off of the bnpInvDigit function implemented and justified in the following URL:
1288
     *
1289
     * {@link http://www-cs-students.stanford.edu/~tjw/jsbn/jsbn.js}
1290
     *
1291
     * The following URL provides more info:
1292
     *
1293
     * {@link http://groups.google.com/group/sci.crypt/msg/7a137205c1be7d85}
1294
     *
1295
     * As for why we do all the bitmasking...  strange things can happen when converting from floats to ints. For
1296
     * instance, on some computers, var_dump((int) -4294967297) yields int(-1) and on others, it yields
1297
     * int(-2147483648).  To avoid problems stemming from this, we use bitmasks to guarantee that ints aren't
1298
     * auto-converted to floats.  The outermost bitmask is present because without it, there's no guarantee that
1299
     * the "residue" returned would be the so-called "common residue".  We use fmod, in the last step, because the
1300
     * maximum possible $x is 26 bits and the maximum $result is 16 bits.  Thus, we have to be able to handle up to
1301
     * 40 bits, which only 64-bit floating points will support.
1302
     *
1303
     * Thanks to Pedro Gimeno Fortea for input!
1304
     *
1305
     * @param array $x
1306
     *
1307
     * @return int
1308
     */
1309
    private function _modInverse67108864($x) // 2**26 == 67,108,864
1310
    {
1311
        $x = -$x[0];
1312
        $result = $x & 0x3; // x**-1 mod 2**2
1313
        $result = ($result * (2 - $x * $result)) & 0xF; // x**-1 mod 2**4
1314
        $result = ($result * (2 - ($x & 0xFF) * $result))  & 0xFF; // x**-1 mod 2**8
1315
        $result = ($result * ((2 - ($x & 0xFFFF) * $result) & 0xFFFF)) & 0xFFFF; // x**-1 mod 2**16
1316
        $result = fmod($result * (2 - fmod($x * $result, self::$baseFull)), self::$baseFull); // x**-1 mod 2**26
1317
        return $result & self::$maxDigit;
1318
    }
1319
1320
    /**
1321
     * Calculates modular inverses.
1322
     *
1323
     * Say you have (30 mod 17 * x mod 17) mod 17 == 1.  x can be found using modular inverses.
1324
     *
1325
     * Here's an example:
1326
     * <code>
1327
     * <?php
1328
     *    $a = new \Jose\Util\teger(30);
1329
     *    $b = new \Jose\Util\teger(17);
1330
     *
1331
     *    $c = $a->modInverse($b);
1332
     *    echo $c->toString(); // outputs 4
1333
     *
1334
     *    echo "\r\n";
1335
     *
1336
     *    $d = $a->multiply($c);
1337
     *    list(, $d) = $d->divide($b);
1338
     *    echo $d; // outputs 1 (as per the definition of modular inverse)
1339
     * ?>
1340
     * </code>
1341
     *
1342
     * @param \Jose\Util\Integer $n
1343
     *
1344
     * @return \Jose\Util\eger|false
1345
     *
1346
     */
1347
    public function modInverse(BigInteger $n)
1348
    {
1349
        $temp = new static();
1350
        $temp->value = gmp_invert($this->value, $n->value);
1351
1352
        return ($temp->value === false) ? false : $this->_normalize($temp);
1353
    }
1354
1355
    /**
1356
     * Calculates the greatest common divisor and Bezout's identity.
1357
     *
1358
     * Say you have 693 and 609.  The GCD is 21.  Bezout's identity states that there exist integers x and y such that
1359
     * 693*x + 609*y == 21.  In point of fact, there are actually an infinite number of x and y combinations and which
1360
     * combination is returned is dependant upon which mode is in use.  See
1361
     * {@link http://en.wikipedia.org/wiki/B%C3%A9zout%27s_identity Bezout's identity - Wikipedia} for more information.
1362
     *
1363
     * Here's an example:
1364
     * <code>
1365
     * <?php
1366
     *    $a = new \Jose\Util\eger(693);
1367
     *    $b = new \Jose\Util\eger(609);
1368
     *
1369
     *    extract($a->extendedGCD($b));
1370
     *
1371
     *    echo $gcd->toString() . "\r\n"; // outputs 21
1372
     *    echo $a->toString() * $x->toString() + $b->toString() * $y->toString(); // outputs 21
1373
     * ?>
1374
     * </code>
1375
     *
1376
     * @param \Jose\Util\Integer $n
1377
     *
1378
     * @return \Jose\Util\BigInteger
1379
     *
1380
     *    {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=19 HAC 14.61}.  As the text above 14.61 notes,
1381
     *    the more traditional algorithim requires "relatively costly multiple-precision divisions".
1382
     */
1383
    public function extendedGCD(BigInteger $n)
1384
    {
1385
        extract(gmp_gcdext($this->value, $n->value));
1386
1387
        return [
1388
            'gcd' => $this->_normalize(new static($g)),
1389
            'x'   => $this->_normalize(new static($s)),
1390
            'y'   => $this->_normalize(new static($t)),
1391
        ];
1392
    }
1393
1394
    /**
1395
     * Calculates the greatest common divisor.
1396
     *
1397
     * Say you have 693 and 609.  The GCD is 21.
1398
     *
1399
     * Here's an example:
1400
     * <code>
1401
     * <?php
1402
     *    $a = new \Jose\Util\eger(693);
1403
     *    $b = new \Jose\Util\eger(609);
1404
     *
1405
     *    $gcd = a->extendedGCD($b);
1406
     *
1407
     *    echo $gcd->toString() . "\r\n"; // outputs 21
1408
     * ?>
1409
     * </code>
1410
     *
1411
     * @param \Jose\Util\Integer $n
1412
     *
1413
     * @return \Jose\Util\BigInteger
1414
     */
1415
    public function gcd(BigInteger $n)
1416
    {
1417
        extract($this->extendedGCD($n));
1418
1419
        return $gcd;
1420
    }
1421
1422
    /**
1423
     * Absolute value.
1424
     *
1425
     * @return \Jose\Util\BigInteger
1426
     */
1427
    public function abs()
1428
    {
1429
        $temp = new static();
1430
1431
        $temp->value = gmp_abs($this->value);
1432
1433
        return $temp;
1434
    }
1435
1436
    /**
1437
     * Compares two numbers.
1438
     *
1439
     * Although one might think !$x->compare($y) means $x != $y, it, in fact, means the opposite.  The reason for this is
1440
     * demonstrated thusly:
1441
     *
1442
     * $x  > $y: $x->compare($y)  > 0
1443
     * $x  < $y: $x->compare($y)  < 0
1444
     * $x == $y: $x->compare($y) == 0
1445
     *
1446
     * Note how the same comparison operator is used.  If you want to test for equality, use $x->equals($y).
1447
     *
1448
     * @param \Jose\Util\Integer $y
1449
     *
1450
     * @return int < 0 if $this is less than $y; > 0 if $this is greater than $y, and 0 if they are equal.
1451
     *
1452
     */
1453
    public function compare(BigInteger $y)
1454
    {
1455
        return gmp_cmp($this->value, $y->value);
1456
    }
1457
1458
    /**
1459
     * Compares two numbers.
1460
     *
1461
     * @param array $x_value
1462
     * @param bool  $x_negative
1463
     * @param array $y_value
1464
     * @param bool  $y_negative
1465
     *
1466
     * @return int
1467
     */
1468
    private static function _compare($x_value, $x_negative, $y_value, $y_negative)
1469
    {
1470
        if ($x_negative != $y_negative) {
1471
            return (!$x_negative && $y_negative) ? 1 : -1;
1472
        }
1473
1474
        $result = $x_negative ? -1 : 1;
1475
1476
        if (count($x_value) != count($y_value)) {
1477
            return (count($x_value) > count($y_value)) ? $result : -$result;
1478
        }
1479
        $size = max(count($x_value), count($y_value));
1480
1481
        $x_value = array_pad($x_value, $size, 0);
1482
        $y_value = array_pad($y_value, $size, 0);
1483
1484
        for ($i = count($x_value) - 1; $i >= 0; --$i) {
1485
            if ($x_value[$i] != $y_value[$i]) {
1486
                return ($x_value[$i] > $y_value[$i]) ? $result : -$result;
1487
            }
1488
        }
1489
1490
        return 0;
1491
    }
1492
1493
    /**
1494
     * Tests the equality of two numbers.
1495
     *
1496
     * If you need to see if one number is greater than or less than another number, use BigInteger::compare()
1497
     *
1498
     * @param \Jose\Util\Integer $x
1499
     *
1500
     * @return bool
1501
     */
1502
    public function equals(BigInteger $x)
1503
    {
1504
        return gmp_cmp($this->value, $x->value) == 0;
1505
    }
1506
1507
    /**
1508
     * Set Precision.
1509
     *
1510
     * Some bitwise operations give different results depending on the precision being used.  Examples include left
1511
     * shift, not, and rotates.
1512
     *
1513
     * @param int $bits
1514
     */
1515
    public function setPrecision($bits)
1516
    {
1517
        if ($bits < 1) {
1518
            $this->precision = -1;
1519
            $this->bitmask = false;
1520
1521
            return;
1522
        }
1523
        $this->precision = $bits;
1524
        if (MATH_BIGINTEGER_MODE != self::MODE_BCMATH) {
1525
            $this->bitmask = new static(chr((1 << ($bits & 0x7)) - 1).str_repeat(chr(0xFF), $bits >> 3), 256);
1526
        } else {
1527
            $this->bitmask = new static(bcpow('2', $bits, 0));
1528
        }
1529
1530
        $temp = $this->_normalize($this);
1531
        $this->value = $temp->value;
1532
    }
1533
1534
    /**
1535
     * Get Precision.
1536
     *
1537
     * @return int
1538
     */
1539
    public function getPrecision()
1540
    {
1541
        return $this->precision;
1542
    }
1543
1544
    /**
1545
     * Logical And.
1546
     *
1547
     * @param \Jose\Util\Integer $x
1548
     *
1549
     *
1550
     * @return \Jose\Util\BigInteger
1551
     */
1552
    public function bitwise_and(BigInteger $x)
1553
    {
1554
        $temp = new static();
1555
        $temp->value = gmp_and($this->value, $x->value);
1556
1557
        return $this->_normalize($temp);
1558
    }
1559
1560
    /**
1561
     * Logical Or.
1562
     *
1563
     * @param \Jose\Util\Integer $x
1564
     *
1565
     *
1566
     * @return \Jose\Util\BigInteger
1567
     */
1568
    public function bitwise_or(BigInteger $x)
1569
    {
1570
                $temp = new static();
1571
                $temp->value = gmp_or($this->value, $x->value);
1572
1573
                return $this->_normalize($temp);
1574
    }
1575
1576
    /**
1577
     * Logical Exclusive-Or.
1578
     *
1579
     * @param \Jose\Util\Integer $x
1580
     *
1581
     *
1582
     * @return \Jose\Util\BigInteger
1583
     */
1584
    public function bitwise_xor(BigInteger $x)
1585
    {
1586
        $temp = new static();
1587
        $temp->value = gmp_xor($this->value, $x->value);
1588
1589
        return $this->_normalize($temp);
1590
    }
1591
1592
    /**
1593
     * Logical Not.
1594
     *
1595
     *
1596
     * @return \Jose\Util\BigInteger
1597
     */
1598
    public function bitwise_not()
1599
    {
1600
        // calculuate "not" without regard to $this->precision
1601
        // (will always result in a smaller number.  ie. ~1 isn't 1111 1110 - it's 0)
1602
        $temp = $this->toBytes();
1603
        if ($temp == '') {
1604
            return '';
1605
        }
1606
        $pre_msb = decbin(ord($temp[0]));
1607
        $temp = ~$temp;
1608
        $msb = decbin(ord($temp[0]));
1609
        if (strlen($msb) == 8) {
1610
            $msb = substr($msb, strpos($msb, '0'));
1611
        }
1612
        $temp[0] = chr(bindec($msb));
1613
1614
        // see if we need to add extra leading 1's
1615
        $current_bits = strlen($pre_msb) + 8 * strlen($temp) - 8;
1616
        $new_bits = $this->precision - $current_bits;
1617
        if ($new_bits <= 0) {
1618
            return $this->_normalize(new static($temp, 256));
1619
        }
1620
1621
        // generate as many leading 1's as we need to.
1622
        $leading_ones = chr((1 << ($new_bits & 0x7)) - 1).str_repeat(chr(0xFF), $new_bits >> 3);
1623
1624
        self::_base256_lshift($leading_ones, $current_bits);
1625
1626
        $temp = str_pad($temp, strlen($leading_ones), chr(0), STR_PAD_LEFT);
1627
1628
        return $this->_normalize(new static($leading_ones | $temp, 256));
1629
    }
1630
1631
    /**
1632
     * Logical Right Shift.
1633
     *
1634
     * Shifts BigInteger's by $shift bits, effectively dividing by 2**$shift.
1635
     *
1636
     * @param int $shift
1637
     *
1638
     * @return \Jose\Util\BigInteger
1639
     *
1640
     */
1641
    public function bitwise_rightShift($shift)
1642
    {
1643
        $temp = new static();
1644
1645
        static $two;
1646
1647
        if (!isset($two)) {
1648
            $two = gmp_init('2');
1649
        }
1650
1651
        $temp->value = gmp_div_q($this->value, gmp_pow($two, $shift));
1652
1653
        return $this->_normalize($temp);
1654
    }
1655
1656
    /**
1657
     * Logical Left Shift.
1658
     *
1659
     * Shifts BigInteger's by $shift bits, effectively multiplying by 2**$shift.
1660
     *
1661
     * @param int $shift
1662
     *
1663
     * @return \Jose\Util\BigInteger
1664
     *
1665
     */
1666
    public function bitwise_leftShift($shift)
1667
    {
1668
        $temp = new static();
1669
1670
        static $two;
1671
1672
        if (!isset($two)) {
1673
            $two = gmp_init('2');
1674
        }
1675
1676
        $temp->value = gmp_mul($this->value, gmp_pow($two, $shift));
1677
1678
        return $this->_normalize($temp);
1679
    }
1680
1681
    /**
1682
     * Logical Left Rotate.
1683
     *
1684
     * Instead of the top x bits being dropped they're appended to the shifted bit string.
1685
     *
1686
     * @param int $shift
1687
     *
1688
     * @return \Jose\Util\BigInteger
1689
     */
1690
    public function bitwise_leftRotate($shift)
1691
    {
1692
        $bits = $this->toBytes();
1693
1694
        if ($this->precision > 0) {
1695
            $precision = $this->precision;
1696
            if (MATH_BIGINTEGER_MODE == self::MODE_BCMATH) {
1697
                $mask = $this->bitmask->subtract(new static(1));
1698
                $mask = $mask->toBytes();
1699
            } else {
1700
                $mask = $this->bitmask->toBytes();
1701
            }
1702
        } else {
1703
            $temp = ord($bits[0]);
1704
            for ($i = 0; $temp >> $i; ++$i) {
1705
            }
1706
            $precision = 8 * strlen($bits) - 8 + $i;
1707
            $mask = chr((1 << ($precision & 0x7)) - 1).str_repeat(chr(0xFF), $precision >> 3);
1708
        }
1709
1710
        if ($shift < 0) {
1711
            $shift += $precision;
1712
        }
1713
        $shift %= $precision;
1714
1715
        if (!$shift) {
1716
            return clone $this;
1717
        }
1718
1719
        $left = $this->bitwise_leftShift($shift);
1720
        $left = $left->bitwise_and(new static($mask, 256));
1721
        $right = $this->bitwise_rightShift($precision - $shift);
1722
        $result = MATH_BIGINTEGER_MODE != self::MODE_BCMATH ? $left->bitwise_or($right) : $left->add($right);
1723
1724
        return $this->_normalize($result);
1725
    }
1726
1727
    /**
1728
     * Logical Right Rotate.
1729
     *
1730
     * Instead of the bottom x bits being dropped they're prepended to the shifted bit string.
1731
     *
1732
     * @param int $shift
1733
     *
1734
     * @return \Jose\Util\BigInteger
1735
     */
1736
    public function bitwise_rightRotate($shift)
1737
    {
1738
        return $this->bitwise_leftRotate(-$shift);
1739
    }
1740
1741
    /**
1742
     * Generates a random BigInteger.
1743
     *
1744
     * Byte length is equal to $length. Uses \phpseclib\Crypt\Random if it's loaded and mt_rand if it's not.
1745
     *
1746
     * @param int $length
1747
     *
1748
     * @return \Jose\Util\BigInteger
1749
     */
1750
    private static function _random_number_helper($size)
1751
    {
1752
        if (class_exists('\phpseclib\Crypt\Random')) {
1753
            $random = random_bytes($size);
1754
        } else {
1755
            $random = '';
1756
1757
            if ($size & 1) {
1758
                $random .= chr(mt_rand(0, 255));
1759
            }
1760
1761
            $blocks = $size >> 1;
1762
            for ($i = 0; $i < $blocks; ++$i) {
1763
                // mt_rand(-2147483648, 0x7FFFFFFF) always produces -2147483648 on some systems
1764
                $random .= pack('n', mt_rand(0, 0xFFFF));
1765
            }
1766
        }
1767
1768
        return new static($random, 256);
1769
    }
1770
1771
    /**
1772
     * Generate a random number.
1773
     *
1774
     * Returns a random number between $min and $max where $min and $max
1775
     * can be defined using one of the two methods:
1776
     *
1777
     * BigInteger::random($min, $max)
1778
     * BigInteger::random($max, $min)
1779
     *
1780
     * @param \Jose\Util\eger $arg1
1781
     * @param \Jose\Util\eger $arg2
1782
     *
1783
     * @return \Jose\Util\BigInteger
1784
     */
1785
    public static function random(BigInteger $min, BigInteger $max)
1786
    {
1787
        $compare = $max->compare($min);
1788
1789
        if (!$compare) {
1790
            return $this->_normalize($min);
1791
        } elseif ($compare < 0) {
1792
            // if $min is bigger then $max, swap $min and $max
1793
            $temp = $max;
1794
            $max = $min;
1795
            $min = $temp;
1796
        }
1797
1798
        static $one;
1799
        if (!isset($one)) {
1800
            $one = new static(1);
1801
        }
1802
1803
        $max = $max->subtract($min->subtract($one));
1804
        $size = strlen(ltrim($max->toBytes(), chr(0)));
1805
1806
        /*
1807
            doing $random % $max doesn't work because some numbers will be more likely to occur than others.
1808
            eg. if $max is 140 and $random's max is 255 then that'd mean both $random = 5 and $random = 145
1809
            would produce 5 whereas the only value of random that could produce 139 would be 139. ie.
1810
            not all numbers would be equally likely. some would be more likely than others.
1811
1812
            creating a whole new random number until you find one that is within the range doesn't work
1813
            because, for sufficiently small ranges, the likelihood that you'd get a number within that range
1814
            would be pretty small. eg. with $random's max being 255 and if your $max being 1 the probability
1815
            would be pretty high that $random would be greater than $max.
1816
1817
            phpseclib works around this using the technique described here:
1818
1819
            http://crypto.stackexchange.com/questions/5708/creating-a-small-number-from-a-cryptographically-secure-random-string
1820
        */
1821
        $random_max = new static(chr(1).str_repeat("\0", $size), 256);
1822
        $random = static::_random_number_helper($size);
1823
1824
        list($max_multiple) = $random_max->divide($max);
1825
        $max_multiple = $max_multiple->multiply($max);
1826
1827
        while ($random->compare($max_multiple) >= 0) {
1828
            $random = $random->subtract($max_multiple);
1829
            $random_max = $random_max->subtract($max_multiple);
1830
            $random = $random->bitwise_leftShift(8);
1831
            $random = $random->add(self::_random_number_helper(1));
1832
            $random_max = $random_max->bitwise_leftShift(8);
1833
            list($max_multiple) = $random_max->divide($max);
1834
            $max_multiple = $max_multiple->multiply($max);
1835
        }
1836
        list(, $random) = $random->divide($max);
1837
1838
        return $random->add($min);
1839
    }
1840
1841
    /**
1842
     * Generate a random prime number.
1843
     *
1844
     * If there's not a prime within the given range, false will be returned.
1845
     * If more than $timeout seconds have elapsed, give up and return false.
1846
     *
1847
     * @param \Jose\Util\teger $min
1848
     * @param \Jose\Util\teger $max
1849
     * @param int              $timeout
1850
     *
1851
     * @return Math_BigInteger|false
1852
     *
1853
     */
1854
    public static function randomPrime(BigInteger $min, BigInteger $max, $timeout = false)
1855
    {
1856
        $compare = $max->compare($min);
1857
1858
        if (!$compare) {
1859
            return $min->isPrime() ? $min : false;
0 ignored issues
show
The method isPrime() does not seem to exist on object<Jose\Util\BigInteger>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
1860
        } elseif ($compare < 0) {
1861
            // if $min is bigger then $max, swap $min and $max
1862
            $temp = $max;
1863
            $max = $min;
1864
            $min = $temp;
1865
        }
1866
1867
        static $one, $two;
1868
        if (!isset($one)) {
1869
            $one = new static(1);
1870
            $two = new static(2);
1871
        }
1872
1873
        $start = time();
1874
1875
        $x = self::random($min, $max);
1876
1877
        // gmp_nextprime() requires PHP 5 >= 5.2.0 per <http://php.net/gmp-nextprime>.
1878
        if (MATH_BIGINTEGER_MODE == self::MODE_GMP && extension_loaded('gmp')) {
1879
            $p = new static();
1880
            $p->value = gmp_nextprime($x->value);
1881
1882
            if ($p->compare($max) <= 0) {
1883
                return $p;
1884
            }
1885
1886
            if (!$min->equals($x)) {
1887
                $x = $x->subtract($one);
1888
            }
1889
1890
            return self::randomPrime($min, $x);
1891
        }
1892
1893
        if ($x->equals($two)) {
1894
            return $x;
1895
        }
1896
1897
        $x->_make_odd();
1898
        if ($x->compare($max) > 0) {
1899
            // if $x > $max then $max is even and if $min == $max then no prime number exists between the specified range
1900
            if ($min->equals($max)) {
1901
                return false;
1902
            }
1903
            $x = clone $min;
1904
            $x->_make_odd();
1905
        }
1906
1907
        $initial_x = clone $x;
1908
1909
        while (true) {
1910
            if ($timeout !== false && time() - $start > $timeout) {
1911
                return false;
1912
            }
1913
1914
            if ($x->isPrime()) {
0 ignored issues
show
The method isPrime() does not seem to exist on object<Jose\Util\BigInteger>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
1915
                return $x;
1916
            }
1917
1918
            $x = $x->add($two);
1919
1920
            if ($x->compare($max) > 0) {
1921
                $x = clone $min;
1922
                if ($x->equals($two)) {
1923
                    return $x;
1924
                }
1925
                $x->_make_odd();
1926
            }
1927
1928
            if ($x->equals($initial_x)) {
1929
                return false;
1930
            }
1931
        }
1932
    }
1933
1934
    /**
1935
     * Make the current number odd.
1936
     *
1937
     * If the current number is odd it'll be unchanged.  If it's even, one will be added to it.
1938
     */
1939
    private function _make_odd()
1940
    {
1941
        switch (MATH_BIGINTEGER_MODE) {
1942
            case self::MODE_GMP:
1943
                gmp_setbit($this->value, 0);
1944
                break;
1945
            case self::MODE_BCMATH:
1946
                if ($this->value[strlen($this->value) - 1] % 2 == 0) {
1947
                    $this->value = bcadd($this->value, '1');
1948
                }
1949
                break;
1950
            default:
1951
                $this->value[0] |= 1;
1952
        }
1953
    }
1954
1955
    /**
1956
     * Normalize.
1957
     *
1958
     * Removes leading zeros and truncates (if necessary) to maintain the appropriate precision
1959
     *
1960
     * @param \Jose\Util\BigInteger
1961
     *
1962
     * @return \Jose\Util\BigInteger
1963
     */
1964
    private function _normalize($result)
1965
    {
1966
        $result->precision = $this->precision;
1967
        $result->bitmask = $this->bitmask;
1968
1969
        if ($this->bitmask !== false) {
1970
            $result->value = gmp_and($result->value, $result->bitmask->value);
1971
        }
1972
1973
        return $result;
1974
    }
1975
1976
    /**
1977
     * Trim.
1978
     *
1979
     * Removes leading zeros
1980
     *
1981
     * @param array $value
1982
     *
1983
     * @return \Jose\Util\BigInteger
1984
     */
1985
    private static function _trim($value)
1986
    {
1987
        for ($i = count($value) - 1; $i >= 0; --$i) {
1988
            if ($value[$i]) {
1989
                break;
1990
            }
1991
            unset($value[$i]);
1992
        }
1993
1994
        return $value;
1995
    }
1996
1997
    /**
1998
     * Array Repeat.
1999
     *
2000
     * @param $input Array
2001
     * @param $multiplier mixed
2002
     *
2003
     * @return array
2004
     */
2005
    private static function _array_repeat($input, $multiplier)
2006
    {
2007
        return ($multiplier) ? array_fill(0, $multiplier, $input) : [];
2008
    }
2009
2010
    /**
2011
     * Logical Left Shift.
2012
     *
2013
     * Shifts binary strings $shift bits, essentially multiplying by 2**$shift.
2014
     *
2015
     * @param $x String
2016
     * @param $shift Integer
2017
     *
2018
     * @return string
2019
     */
2020
    private static function _base256_lshift(&$x, $shift)
2021
    {
2022
        if ($shift == 0) {
2023
            return;
2024
        }
2025
2026
        $num_bytes = $shift >> 3; // eg. floor($shift/8)
2027
        $shift &= 7; // eg. $shift % 8
2028
2029
        $carry = 0;
2030
        for ($i = strlen($x) - 1; $i >= 0; --$i) {
2031
            $temp = ord($x[$i]) << $shift | $carry;
2032
            $x[$i] = chr($temp);
2033
            $carry = $temp >> 8;
2034
        }
2035
        $carry = ($carry != 0) ? chr($carry) : '';
2036
        $x = $carry.$x.str_repeat(chr(0), $num_bytes);
2037
    }
2038
2039
    /**
2040
     * Single digit division.
2041
     *
2042
     * Even if int64 is being used the division operator will return a float64 value
2043
     * if the dividend is not evenly divisible by the divisor. Since a float64 doesn't
2044
     * have the precision of int64 this is a problem so, when int64 is being used,
2045
     * we'll guarantee that the dividend is divisible by first subtracting the remainder.
2046
     *
2047
     * @param int $x
2048
     * @param int $y
2049
     *
2050
     * @return int
2051
     */
2052
    private static function _safe_divide($x, $y)
2053
    {
2054
        if (self::$base === 26) {
2055
            return (int) ($x / $y);
2056
        }
2057
2058
        // self::$base === 31
2059
        return ($x - ($x % $y)) / $y;
2060
    }
2061
}
2062