PageRenderTime 8ms CodeModel.GetById 10ms app.highlight 61ms RepoModel.GetById 1ms app.codeStats 1ms

/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger.php

https://bitbucket.org/openemr/openemr
PHP | 3754 lines | 2027 code | 494 blank | 1233 comment | 399 complexity | 9dff1fa96f84567b85082175a13679f5 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1<?php
   2
   3/**
   4 * Pure-PHP arbitrary precision integer arithmetic library.
   5 *
   6 * Supports base-2, base-10, base-16, and base-256 numbers.  Uses the GMP or BCMath extensions, if available,
   7 * and an internal implementation, otherwise.
   8 *
   9 * PHP version 5
  10 *
  11 * {@internal (all DocBlock comments regarding implementation - such as the one that follows - refer to the
  12 * {@link self::MODE_INTERNAL self::MODE_INTERNAL} mode)
  13 *
  14 * BigInteger uses base-2**26 to perform operations such as multiplication and division and
  15 * base-2**52 (ie. two base 2**26 digits) to perform addition and subtraction.  Because the largest possible
  16 * value when multiplying two base-2**26 numbers together is a base-2**52 number, double precision floating
  17 * point numbers - numbers that should be supported on most hardware and whose significand is 53 bits - are
  18 * used.  As a consequence, bitwise operators such as >> and << cannot be used, nor can the modulo operator %,
  19 * which only supports integers.  Although this fact will slow this library down, the fact that such a high
  20 * base is being used should more than compensate.
  21 *
  22 * Numbers are stored in {@link http://en.wikipedia.org/wiki/Endianness little endian} format.  ie.
  23 * (new \phpseclib\Math\BigInteger(pow(2, 26)))->value = array(0, 1)
  24 *
  25 * Useful resources are as follows:
  26 *
  27 *  - {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf Handbook of Applied Cryptography (HAC)}
  28 *  - {@link http://math.libtomcrypt.com/files/tommath.pdf Multi-Precision Math (MPM)}
  29 *  - Java's BigInteger classes.  See /j2se/src/share/classes/java/math in jdk-1_5_0-src-jrl.zip
  30 *
  31 * Here's an example of how to use this library:
  32 * <code>
  33 * <?php
  34 *    $a = new \phpseclib\Math\BigInteger(2);
  35 *    $b = new \phpseclib\Math\BigInteger(3);
  36 *
  37 *    $c = $a->add($b);
  38 *
  39 *    echo $c->toString(); // outputs 5
  40 * ?>
  41 * </code>
  42 *
  43 * @category  Math
  44 * @package   BigInteger
  45 * @author    Jim Wigginton <terrafrost@php.net>
  46 * @copyright 2006 Jim Wigginton
  47 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
  48 * @link      http://pear.php.net/package/Math_BigInteger
  49 */
  50
  51namespace phpseclib\Math;
  52
  53use phpseclib\Crypt\Random;
  54
  55/**
  56 * Pure-PHP arbitrary precision integer arithmetic library. Supports base-2, base-10, base-16, and base-256
  57 * numbers.
  58 *
  59 * @package BigInteger
  60 * @author  Jim Wigginton <terrafrost@php.net>
  61 * @access  public
  62 */
  63class BigInteger
  64{
  65    /**#@+
  66     * Reduction constants
  67     *
  68     * @access private
  69     * @see BigInteger::_reduce()
  70     */
  71    /**
  72     * @see BigInteger::_montgomery()
  73     * @see BigInteger::_prepMontgomery()
  74     */
  75    const MONTGOMERY = 0;
  76    /**
  77     * @see BigInteger::_barrett()
  78     */
  79    const BARRETT = 1;
  80    /**
  81     * @see BigInteger::_mod2()
  82     */
  83    const POWEROF2 = 2;
  84    /**
  85     * @see BigInteger::_remainder()
  86     */
  87    const CLASSIC = 3;
  88    /**
  89     * @see BigInteger::__clone()
  90     */
  91    const NONE = 4;
  92    /**#@-*/
  93
  94    /**#@+
  95     * Array constants
  96     *
  97     * Rather than create a thousands and thousands of new BigInteger objects in repeated function calls to add() and
  98     * multiply() or whatever, we'll just work directly on arrays, taking them in as parameters and returning them.
  99     *
 100     * @access private
 101    */
 102    /**
 103     * $result[self::VALUE] contains the value.
 104     */
 105    const VALUE = 0;
 106    /**
 107     * $result[self::SIGN] contains the sign.
 108     */
 109    const SIGN = 1;
 110    /**#@-*/
 111
 112    /**#@+
 113     * @access private
 114     * @see BigInteger::_montgomery()
 115     * @see BigInteger::_barrett()
 116    */
 117    /**
 118     * Cache constants
 119     *
 120     * $cache[self::VARIABLE] tells us whether or not the cached data is still valid.
 121     */
 122    const VARIABLE = 0;
 123    /**
 124     * $cache[self::DATA] contains the cached data.
 125     */
 126    const DATA = 1;
 127    /**#@-*/
 128
 129    /**#@+
 130     * Mode constants.
 131     *
 132     * @access private
 133     * @see BigInteger::__construct()
 134    */
 135    /**
 136     * To use the pure-PHP implementation
 137     */
 138    const MODE_INTERNAL = 1;
 139    /**
 140     * To use the BCMath library
 141     *
 142     * (if enabled; otherwise, the internal implementation will be used)
 143     */
 144    const MODE_BCMATH = 2;
 145    /**
 146     * To use the GMP library
 147     *
 148     * (if present; otherwise, either the BCMath or the internal implementation will be used)
 149     */
 150    const MODE_GMP = 3;
 151    /**#@-*/
 152
 153    /**
 154     * Karatsuba Cutoff
 155     *
 156     * At what point do we switch between Karatsuba multiplication and schoolbook long multiplication?
 157     *
 158     * @access private
 159     */
 160    const KARATSUBA_CUTOFF = 25;
 161
 162    /**#@+
 163     * Static properties used by the pure-PHP implementation.
 164     *
 165     * @see __construct()
 166     */
 167    protected static $base;
 168    protected static $baseFull;
 169    protected static $maxDigit;
 170    protected static $msb;
 171
 172    /**
 173     * $max10 in greatest $max10Len satisfying
 174     * $max10 = 10**$max10Len <= 2**$base.
 175     */
 176    protected static $max10;
 177
 178    /**
 179     * $max10Len in greatest $max10Len satisfying
 180     * $max10 = 10**$max10Len <= 2**$base.
 181     */
 182    protected static $max10Len;
 183    protected static $maxDigit2;
 184    /**#@-*/
 185
 186    /**
 187     * Holds the BigInteger's value.
 188     *
 189     * @var array
 190     * @access private
 191     */
 192    var $value;
 193
 194    /**
 195     * Holds the BigInteger's magnitude.
 196     *
 197     * @var bool
 198     * @access private
 199     */
 200    var $is_negative = false;
 201
 202    /**
 203     * Precision
 204     *
 205     * @see self::setPrecision()
 206     * @access private
 207     */
 208    var $precision = -1;
 209
 210    /**
 211     * Precision Bitmask
 212     *
 213     * @see self::setPrecision()
 214     * @access private
 215     */
 216    var $bitmask = false;
 217
 218    /**
 219     * Mode independent value used for serialization.
 220     *
 221     * If the bcmath or gmp extensions are installed $this->value will be a non-serializable resource, hence the need for
 222     * a variable that'll be serializable regardless of whether or not extensions are being used.  Unlike $this->value,
 223     * however, $this->hex is only calculated when $this->__sleep() is called.
 224     *
 225     * @see self::__sleep()
 226     * @see self::__wakeup()
 227     * @var string
 228     * @access private
 229     */
 230    var $hex;
 231
 232    /**
 233     * Converts base-2, base-10, base-16, and binary strings (base-256) to BigIntegers.
 234     *
 235     * If the second parameter - $base - is negative, then it will be assumed that the number's are encoded using
 236     * two's compliment.  The sole exception to this is -10, which is treated the same as 10 is.
 237     *
 238     * Here's an example:
 239     * <code>
 240     * <?php
 241     *    $a = new \phpseclib\Math\BigInteger('0x32', 16); // 50 in base-16
 242     *
 243     *    echo $a->toString(); // outputs 50
 244     * ?>
 245     * </code>
 246     *
 247     * @param $x base-10 number or base-$base number if $base set.
 248     * @param int $base
 249     * @return \phpseclib\Math\BigInteger
 250     * @access public
 251     */
 252    function __construct($x = 0, $base = 10)
 253    {
 254        if (!defined('MATH_BIGINTEGER_MODE')) {
 255            switch (true) {
 256                case extension_loaded('gmp'):
 257                    define('MATH_BIGINTEGER_MODE', self::MODE_GMP);
 258                    break;
 259                case extension_loaded('bcmath'):
 260                    define('MATH_BIGINTEGER_MODE', self::MODE_BCMATH);
 261                    break;
 262                default:
 263                    define('MATH_BIGINTEGER_MODE', self::MODE_INTERNAL);
 264            }
 265        }
 266
 267        if (extension_loaded('openssl') && !defined('MATH_BIGINTEGER_OPENSSL_DISABLE') && !defined('MATH_BIGINTEGER_OPENSSL_ENABLED')) {
 268            // some versions of XAMPP have mismatched versions of OpenSSL which causes it not to work
 269            ob_start();
 270            @phpinfo();
 271            $content = ob_get_contents();
 272            ob_end_clean();
 273
 274            preg_match_all('#OpenSSL (Header|Library) Version(.*)#im', $content, $matches);
 275
 276            $versions = array();
 277            if (!empty($matches[1])) {
 278                for ($i = 0; $i < count($matches[1]); $i++) {
 279                    $fullVersion = trim(str_replace('=>', '', strip_tags($matches[2][$i])));
 280
 281                    // Remove letter part in OpenSSL version
 282                    if (!preg_match('/(\d+\.\d+\.\d+)/i', $fullVersion, $m)) {
 283                        $versions[$matches[1][$i]] = $fullVersion;
 284                    } else {
 285                        $versions[$matches[1][$i]] = $m[0];
 286                    }
 287                }
 288            }
 289
 290            // it doesn't appear that OpenSSL versions were reported upon until PHP 5.3+
 291            switch (true) {
 292                case !isset($versions['Header']):
 293                case !isset($versions['Library']):
 294                case $versions['Header'] == $versions['Library']:
 295                    define('MATH_BIGINTEGER_OPENSSL_ENABLED', true);
 296                    break;
 297                default:
 298                    define('MATH_BIGINTEGER_OPENSSL_DISABLE', true);
 299            }
 300        }
 301
 302        if (!defined('PHP_INT_SIZE')) {
 303            define('PHP_INT_SIZE', 4);
 304        }
 305
 306        if (empty(self::$base) && MATH_BIGINTEGER_MODE == self::MODE_INTERNAL) {
 307            switch (PHP_INT_SIZE) {
 308                case 8: // use 64-bit integers if int size is 8 bytes
 309                    self::$base      = 31;
 310                    self::$baseFull  = 0x80000000;
 311                    self::$maxDigit  = 0x7FFFFFFF;
 312                    self::$msb       = 0x40000000;
 313                    self::$max10     = 1000000000;
 314                    self::$max10Len  = 9;
 315                    self::$maxDigit2 = pow(2, 62);
 316                    break;
 317                //case 4: // use 64-bit floats if int size is 4 bytes
 318                default:
 319                    self::$base      = 26;
 320                    self::$baseFull  = 0x4000000;
 321                    self::$maxDigit  = 0x3FFFFFF;
 322                    self::$msb       = 0x2000000;
 323                    self::$max10     = 10000000;
 324                    self::$max10Len  = 7;
 325                    self::$maxDigit2 = pow(2, 52); // pow() prevents truncation
 326            }
 327        }
 328
 329        switch (MATH_BIGINTEGER_MODE) {
 330            case self::MODE_GMP:
 331                switch (true) {
 332                    case is_resource($x) && get_resource_type($x) == 'GMP integer':
 333                    // PHP 5.6 switched GMP from using resources to objects
 334                    case $x instanceof \GMP:
 335                        $this->value = $x;
 336                        return;
 337                }
 338                $this->value = gmp_init(0);
 339                break;
 340            case self::MODE_BCMATH:
 341                $this->value = '0';
 342                break;
 343            default:
 344                $this->value = array();
 345        }
 346
 347        // '0' counts as empty() but when the base is 256 '0' is equal to ord('0') or 48
 348        // '0' is the only value like this per http://php.net/empty
 349        if (empty($x) && (abs($base) != 256 || $x !== '0')) {
 350            return;
 351        }
 352
 353        switch ($base) {
 354            case -256:
 355                if (ord($x[0]) & 0x80) {
 356                    $x = ~$x;
 357                    $this->is_negative = true;
 358                }
 359            case 256:
 360                switch (MATH_BIGINTEGER_MODE) {
 361                    case self::MODE_GMP:
 362                        $sign = $this->is_negative ? '-' : '';
 363                        $this->value = gmp_init($sign . '0x' . bin2hex($x));
 364                        break;
 365                    case self::MODE_BCMATH:
 366                        // round $len to the nearest 4 (thanks, DavidMJ!)
 367                        $len = (strlen($x) + 3) & 0xFFFFFFFC;
 368
 369                        $x = str_pad($x, $len, chr(0), STR_PAD_LEFT);
 370
 371                        for ($i = 0; $i < $len; $i+= 4) {
 372                            $this->value = bcmul($this->value, '4294967296', 0); // 4294967296 == 2**32
 373                            $this->value = bcadd($this->value, 0x1000000 * ord($x[$i]) + ((ord($x[$i + 1]) << 16) | (ord($x[$i + 2]) << 8) | ord($x[$i + 3])), 0);
 374                        }
 375
 376                        if ($this->is_negative) {
 377                            $this->value = '-' . $this->value;
 378                        }
 379
 380                        break;
 381                    // converts a base-2**8 (big endian / msb) number to base-2**26 (little endian / lsb)
 382                    default:
 383                        while (strlen($x)) {
 384                            $this->value[] = $this->_bytes2int($this->_base256_rshift($x, self::$base));
 385                        }
 386                }
 387
 388                if ($this->is_negative) {
 389                    if (MATH_BIGINTEGER_MODE != self::MODE_INTERNAL) {
 390                        $this->is_negative = false;
 391                    }
 392                    $temp = $this->add(new static('-1'));
 393                    $this->value = $temp->value;
 394                }
 395                break;
 396            case 16:
 397            case -16:
 398                if ($base > 0 && $x[0] == '-') {
 399                    $this->is_negative = true;
 400                    $x = substr($x, 1);
 401                }
 402
 403                $x = preg_replace('#^(?:0x)?([A-Fa-f0-9]*).*#', '$1', $x);
 404
 405                $is_negative = false;
 406                if ($base < 0 && hexdec($x[0]) >= 8) {
 407                    $this->is_negative = $is_negative = true;
 408                    $x = bin2hex(~pack('H*', $x));
 409                }
 410
 411                switch (MATH_BIGINTEGER_MODE) {
 412                    case self::MODE_GMP:
 413                        $temp = $this->is_negative ? '-0x' . $x : '0x' . $x;
 414                        $this->value = gmp_init($temp);
 415                        $this->is_negative = false;
 416                        break;
 417                    case self::MODE_BCMATH:
 418                        $x = (strlen($x) & 1) ? '0' . $x : $x;
 419                        $temp = new static(pack('H*', $x), 256);
 420                        $this->value = $this->is_negative ? '-' . $temp->value : $temp->value;
 421                        $this->is_negative = false;
 422                        break;
 423                    default:
 424                        $x = (strlen($x) & 1) ? '0' . $x : $x;
 425                        $temp = new static(pack('H*', $x), 256);
 426                        $this->value = $temp->value;
 427                }
 428
 429                if ($is_negative) {
 430                    $temp = $this->add(new static('-1'));
 431                    $this->value = $temp->value;
 432                }
 433                break;
 434            case 10:
 435            case -10:
 436                // (?<!^)(?:-).*: find any -'s that aren't at the beginning and then any characters that follow that
 437                // (?<=^|-)0*: find any 0's that are preceded by the start of the string or by a - (ie. octals)
 438                // [^-0-9].*: find any non-numeric characters and then any characters that follow that
 439                $x = preg_replace('#(?<!^)(?:-).*|(?<=^|-)0*|[^-0-9].*#', '', $x);
 440
 441                switch (MATH_BIGINTEGER_MODE) {
 442                    case self::MODE_GMP:
 443                        $this->value = gmp_init($x);
 444                        break;
 445                    case self::MODE_BCMATH:
 446                        // explicitly casting $x to a string is necessary, here, since doing $x[0] on -1 yields different
 447                        // results then doing it on '-1' does (modInverse does $x[0])
 448                        $this->value = $x === '-' ? '0' : (string) $x;
 449                        break;
 450                    default:
 451                        $temp = new static();
 452
 453                        $multiplier = new static();
 454                        $multiplier->value = array(self::$max10);
 455
 456                        if ($x[0] == '-') {
 457                            $this->is_negative = true;
 458                            $x = substr($x, 1);
 459                        }
 460
 461                        $x = str_pad($x, strlen($x) + ((self::$max10Len - 1) * strlen($x)) % self::$max10Len, 0, STR_PAD_LEFT);
 462                        while (strlen($x)) {
 463                            $temp = $temp->multiply($multiplier);
 464                            $temp = $temp->add(new static($this->_int2bytes(substr($x, 0, self::$max10Len)), 256));
 465                            $x = substr($x, self::$max10Len);
 466                        }
 467
 468                        $this->value = $temp->value;
 469                }
 470                break;
 471            case 2: // base-2 support originally implemented by Lluis Pamies - thanks!
 472            case -2:
 473                if ($base > 0 && $x[0] == '-') {
 474                    $this->is_negative = true;
 475                    $x = substr($x, 1);
 476                }
 477
 478                $x = preg_replace('#^([01]*).*#', '$1', $x);
 479                $x = str_pad($x, strlen($x) + (3 * strlen($x)) % 4, 0, STR_PAD_LEFT);
 480
 481                $str = '0x';
 482                while (strlen($x)) {
 483                    $part = substr($x, 0, 4);
 484                    $str.= dechex(bindec($part));
 485                    $x = substr($x, 4);
 486                }
 487
 488                if ($this->is_negative) {
 489                    $str = '-' . $str;
 490                }
 491
 492                $temp = new static($str, 8 * $base); // ie. either -16 or +16
 493                $this->value = $temp->value;
 494                $this->is_negative = $temp->is_negative;
 495
 496                break;
 497            default:
 498                // base not supported, so we'll let $this == 0
 499        }
 500    }
 501
 502    /**
 503     * Converts a BigInteger to a byte string (eg. base-256).
 504     *
 505     * Negative numbers are saved as positive numbers, unless $twos_compliment is set to true, at which point, they're
 506     * saved as two's compliment.
 507     *
 508     * Here's an example:
 509     * <code>
 510     * <?php
 511     *    $a = new \phpseclib\Math\BigInteger('65');
 512     *
 513     *    echo $a->toBytes(); // outputs chr(65)
 514     * ?>
 515     * </code>
 516     *
 517     * @param bool $twos_compliment
 518     * @return string
 519     * @access public
 520     * @internal Converts a base-2**26 number to base-2**8
 521     */
 522    function toBytes($twos_compliment = false)
 523    {
 524        if ($twos_compliment) {
 525            $comparison = $this->compare(new static());
 526            if ($comparison == 0) {
 527                return $this->precision > 0 ? str_repeat(chr(0), ($this->precision + 1) >> 3) : '';
 528            }
 529
 530            $temp = $comparison < 0 ? $this->add(new static(1)) : $this->copy();
 531            $bytes = $temp->toBytes();
 532
 533            if (empty($bytes)) { // eg. if the number we're trying to convert is -1
 534                $bytes = chr(0);
 535            }
 536
 537            if (ord($bytes[0]) & 0x80) {
 538                $bytes = chr(0) . $bytes;
 539            }
 540
 541            return $comparison < 0 ? ~$bytes : $bytes;
 542        }
 543
 544        switch (MATH_BIGINTEGER_MODE) {
 545            case self::MODE_GMP:
 546                if (gmp_cmp($this->value, gmp_init(0)) == 0) {
 547                    return $this->precision > 0 ? str_repeat(chr(0), ($this->precision + 1) >> 3) : '';
 548                }
 549
 550                $temp = gmp_strval(gmp_abs($this->value), 16);
 551                $temp = (strlen($temp) & 1) ? '0' . $temp : $temp;
 552                $temp = pack('H*', $temp);
 553
 554                return $this->precision > 0 ?
 555                    substr(str_pad($temp, $this->precision >> 3, chr(0), STR_PAD_LEFT), -($this->precision >> 3)) :
 556                    ltrim($temp, chr(0));
 557            case self::MODE_BCMATH:
 558                if ($this->value === '0') {
 559                    return $this->precision > 0 ? str_repeat(chr(0), ($this->precision + 1) >> 3) : '';
 560                }
 561
 562                $value = '';
 563                $current = $this->value;
 564
 565                if ($current[0] == '-') {
 566                    $current = substr($current, 1);
 567                }
 568
 569                while (bccomp($current, '0', 0) > 0) {
 570                    $temp = bcmod($current, '16777216');
 571                    $value = chr($temp >> 16) . chr($temp >> 8) . chr($temp) . $value;
 572                    $current = bcdiv($current, '16777216', 0);
 573                }
 574
 575                return $this->precision > 0 ?
 576                    substr(str_pad($value, $this->precision >> 3, chr(0), STR_PAD_LEFT), -($this->precision >> 3)) :
 577                    ltrim($value, chr(0));
 578        }
 579
 580        if (!count($this->value)) {
 581            return $this->precision > 0 ? str_repeat(chr(0), ($this->precision + 1) >> 3) : '';
 582        }
 583        $result = $this->_int2bytes($this->value[count($this->value) - 1]);
 584
 585        $temp = $this->copy();
 586
 587        for ($i = count($temp->value) - 2; $i >= 0; --$i) {
 588            $temp->_base256_lshift($result, self::$base);
 589            $result = $result | str_pad($temp->_int2bytes($temp->value[$i]), strlen($result), chr(0), STR_PAD_LEFT);
 590        }
 591
 592        return $this->precision > 0 ?
 593            str_pad(substr($result, -(($this->precision + 7) >> 3)), ($this->precision + 7) >> 3, chr(0), STR_PAD_LEFT) :
 594            $result;
 595    }
 596
 597    /**
 598     * Converts a BigInteger to a hex string (eg. base-16)).
 599     *
 600     * Negative numbers are saved as positive numbers, unless $twos_compliment is set to true, at which point, they're
 601     * saved as two's compliment.
 602     *
 603     * Here's an example:
 604     * <code>
 605     * <?php
 606     *    $a = new \phpseclib\Math\BigInteger('65');
 607     *
 608     *    echo $a->toHex(); // outputs '41'
 609     * ?>
 610     * </code>
 611     *
 612     * @param bool $twos_compliment
 613     * @return string
 614     * @access public
 615     * @internal Converts a base-2**26 number to base-2**8
 616     */
 617    function toHex($twos_compliment = false)
 618    {
 619        return bin2hex($this->toBytes($twos_compliment));
 620    }
 621
 622    /**
 623     * Converts a BigInteger to a bit string (eg. base-2).
 624     *
 625     * Negative numbers are saved as positive numbers, unless $twos_compliment is set to true, at which point, they're
 626     * saved as two's compliment.
 627     *
 628     * Here's an example:
 629     * <code>
 630     * <?php
 631     *    $a = new \phpseclib\Math\BigInteger('65');
 632     *
 633     *    echo $a->toBits(); // outputs '1000001'
 634     * ?>
 635     * </code>
 636     *
 637     * @param bool $twos_compliment
 638     * @return string
 639     * @access public
 640     * @internal Converts a base-2**26 number to base-2**2
 641     */
 642    function toBits($twos_compliment = false)
 643    {
 644        $hex = $this->toHex($twos_compliment);
 645        $bits = '';
 646        for ($i = strlen($hex) - 8, $start = strlen($hex) & 7; $i >= $start; $i-=8) {
 647            $bits = str_pad(decbin(hexdec(substr($hex, $i, 8))), 32, '0', STR_PAD_LEFT) . $bits;
 648        }
 649        if ($start) { // hexdec('') == 0
 650            $bits = str_pad(decbin(hexdec(substr($hex, 0, $start))), 8, '0', STR_PAD_LEFT) . $bits;
 651        }
 652        $result = $this->precision > 0 ? substr($bits, -$this->precision) : ltrim($bits, '0');
 653
 654        if ($twos_compliment && $this->compare(new static()) > 0 && $this->precision <= 0) {
 655            return '0' . $result;
 656        }
 657
 658        return $result;
 659    }
 660
 661    /**
 662     * Converts a BigInteger to a base-10 number.
 663     *
 664     * Here's an example:
 665     * <code>
 666     * <?php
 667     *    $a = new \phpseclib\Math\BigInteger('50');
 668     *
 669     *    echo $a->toString(); // outputs 50
 670     * ?>
 671     * </code>
 672     *
 673     * @return string
 674     * @access public
 675     * @internal Converts a base-2**26 number to base-10**7 (which is pretty much base-10)
 676     */
 677    function toString()
 678    {
 679        switch (MATH_BIGINTEGER_MODE) {
 680            case self::MODE_GMP:
 681                return gmp_strval($this->value);
 682            case self::MODE_BCMATH:
 683                if ($this->value === '0') {
 684                    return '0';
 685                }
 686
 687                return ltrim($this->value, '0');
 688        }
 689
 690        if (!count($this->value)) {
 691            return '0';
 692        }
 693
 694        $temp = $this->copy();
 695        $temp->is_negative = false;
 696
 697        $divisor = new static();
 698        $divisor->value = array(self::$max10);
 699        $result = '';
 700        while (count($temp->value)) {
 701            list($temp, $mod) = $temp->divide($divisor);
 702            $result = str_pad(isset($mod->value[0]) ? $mod->value[0] : '', self::$max10Len, '0', STR_PAD_LEFT) . $result;
 703        }
 704        $result = ltrim($result, '0');
 705        if (empty($result)) {
 706            $result = '0';
 707        }
 708
 709        if ($this->is_negative) {
 710            $result = '-' . $result;
 711        }
 712
 713        return $result;
 714    }
 715
 716    /**
 717     * Copy an object
 718     *
 719     * PHP5 passes objects by reference while PHP4 passes by value.  As such, we need a function to guarantee
 720     * that all objects are passed by value, when appropriate.  More information can be found here:
 721     *
 722     * {@link http://php.net/language.oop5.basic#51624}
 723     *
 724     * @access public
 725     * @see self::__clone()
 726     * @return \phpseclib\Math\BigInteger
 727     */
 728    function copy()
 729    {
 730        $temp = new static();
 731        $temp->value = $this->value;
 732        $temp->is_negative = $this->is_negative;
 733        $temp->precision = $this->precision;
 734        $temp->bitmask = $this->bitmask;
 735        return $temp;
 736    }
 737
 738    /**
 739     *  __toString() magic method
 740     *
 741     * Will be called, automatically, if you're supporting just PHP5.  If you're supporting PHP4, you'll need to call
 742     * toString().
 743     *
 744     * @access public
 745     * @internal Implemented per a suggestion by Techie-Michael - thanks!
 746     */
 747    function __toString()
 748    {
 749        return $this->toString();
 750    }
 751
 752    /**
 753     * __clone() magic method
 754     *
 755     * Although you can call BigInteger::__toString() directly in PHP5, you cannot call BigInteger::__clone() directly
 756     * in PHP5.  You can in PHP4 since it's not a magic method, but in PHP5, you have to call it by using the PHP5
 757     * only syntax of $y = clone $x.  As such, if you're trying to write an application that works on both PHP4 and
 758     * PHP5, call BigInteger::copy(), instead.
 759     *
 760     * @access public
 761     * @see self::copy()
 762     * @return \phpseclib\Math\BigInteger
 763     */
 764    function __clone()
 765    {
 766        return $this->copy();
 767    }
 768
 769    /**
 770     *  __sleep() magic method
 771     *
 772     * Will be called, automatically, when serialize() is called on a BigInteger object.
 773     *
 774     * @see self::__wakeup()
 775     * @access public
 776     */
 777    function __sleep()
 778    {
 779        $this->hex = $this->toHex(true);
 780        $vars = array('hex');
 781        if ($this->precision > 0) {
 782            $vars[] = 'precision';
 783        }
 784        return $vars;
 785    }
 786
 787    /**
 788     *  __wakeup() magic method
 789     *
 790     * Will be called, automatically, when unserialize() is called on a BigInteger object.
 791     *
 792     * @see self::__sleep()
 793     * @access public
 794     */
 795    function __wakeup()
 796    {
 797        $temp = new static($this->hex, -16);
 798        $this->value = $temp->value;
 799        $this->is_negative = $temp->is_negative;
 800        if ($this->precision > 0) {
 801            // recalculate $this->bitmask
 802            $this->setPrecision($this->precision);
 803        }
 804    }
 805
 806    /**
 807     *  __debugInfo() magic method
 808     *
 809     * Will be called, automatically, when print_r() or var_dump() are called
 810     *
 811     * @access public
 812     */
 813    function __debugInfo()
 814    {
 815        $opts = array();
 816        switch (MATH_BIGINTEGER_MODE) {
 817            case self::MODE_GMP:
 818                $engine = 'gmp';
 819                break;
 820            case self::MODE_BCMATH:
 821                $engine = 'bcmath';
 822                break;
 823            case self::MODE_INTERNAL:
 824                $engine = 'internal';
 825                $opts[] = PHP_INT_SIZE == 8 ? '64-bit' : '32-bit';
 826        }
 827        if (MATH_BIGINTEGER_MODE != self::MODE_GMP && defined('MATH_BIGINTEGER_OPENSSL_ENABLED')) {
 828            $opts[] = 'OpenSSL';
 829        }
 830        if (!empty($opts)) {
 831            $engine.= ' (' . implode($opts, ', ') . ')';
 832        }
 833        return array(
 834            'value' => '0x' . $this->toHex(true),
 835            'engine' => $engine
 836        );
 837    }
 838
 839    /**
 840     * Adds two BigIntegers.
 841     *
 842     * Here's an example:
 843     * <code>
 844     * <?php
 845     *    $a = new \phpseclib\Math\BigInteger('10');
 846     *    $b = new \phpseclib\Math\BigInteger('20');
 847     *
 848     *    $c = $a->add($b);
 849     *
 850     *    echo $c->toString(); // outputs 30
 851     * ?>
 852     * </code>
 853     *
 854     * @param \phpseclib\Math\BigInteger $y
 855     * @return \phpseclib\Math\BigInteger
 856     * @access public
 857     * @internal Performs base-2**52 addition
 858     */
 859    function add($y)
 860    {
 861        switch (MATH_BIGINTEGER_MODE) {
 862            case self::MODE_GMP:
 863                $temp = new static();
 864                $temp->value = gmp_add($this->value, $y->value);
 865
 866                return $this->_normalize($temp);
 867            case self::MODE_BCMATH:
 868                $temp = new static();
 869                $temp->value = bcadd($this->value, $y->value, 0);
 870
 871                return $this->_normalize($temp);
 872        }
 873
 874        $temp = $this->_add($this->value, $this->is_negative, $y->value, $y->is_negative);
 875
 876        $result = new static();
 877        $result->value = $temp[self::VALUE];
 878        $result->is_negative = $temp[self::SIGN];
 879
 880        return $this->_normalize($result);
 881    }
 882
 883    /**
 884     * Performs addition.
 885     *
 886     * @param array $x_value
 887     * @param bool $x_negative
 888     * @param array $y_value
 889     * @param bool $y_negative
 890     * @return array
 891     * @access private
 892     */
 893    function _add($x_value, $x_negative, $y_value, $y_negative)
 894    {
 895        $x_size = count($x_value);
 896        $y_size = count($y_value);
 897
 898        if ($x_size == 0) {
 899            return array(
 900                self::VALUE => $y_value,
 901                self::SIGN => $y_negative
 902            );
 903        } elseif ($y_size == 0) {
 904            return array(
 905                self::VALUE => $x_value,
 906                self::SIGN => $x_negative
 907            );
 908        }
 909
 910        // subtract, if appropriate
 911        if ($x_negative != $y_negative) {
 912            if ($x_value == $y_value) {
 913                return array(
 914                    self::VALUE => array(),
 915                    self::SIGN => false
 916                );
 917            }
 918
 919            $temp = $this->_subtract($x_value, false, $y_value, false);
 920            $temp[self::SIGN] = $this->_compare($x_value, false, $y_value, false) > 0 ?
 921                                          $x_negative : $y_negative;
 922
 923            return $temp;
 924        }
 925
 926        if ($x_size < $y_size) {
 927            $size = $x_size;
 928            $value = $y_value;
 929        } else {
 930            $size = $y_size;
 931            $value = $x_value;
 932        }
 933
 934        $value[count($value)] = 0; // just in case the carry adds an extra digit
 935
 936        $carry = 0;
 937        for ($i = 0, $j = 1; $j < $size; $i+=2, $j+=2) {
 938            $sum = $x_value[$j] * self::$baseFull + $x_value[$i] + $y_value[$j] * self::$baseFull + $y_value[$i] + $carry;
 939            $carry = $sum >= self::$maxDigit2; // eg. floor($sum / 2**52); only possible values (in any base) are 0 and 1
 940            $sum = $carry ? $sum - self::$maxDigit2 : $sum;
 941
 942            $temp = self::$base === 26 ? intval($sum / 0x4000000) : ($sum >> 31);
 943
 944            $value[$i] = (int) ($sum - self::$baseFull * $temp); // eg. a faster alternative to fmod($sum, 0x4000000)
 945            $value[$j] = $temp;
 946        }
 947
 948        if ($j == $size) { // ie. if $y_size is odd
 949            $sum = $x_value[$i] + $y_value[$i] + $carry;
 950            $carry = $sum >= self::$baseFull;
 951            $value[$i] = $carry ? $sum - self::$baseFull : $sum;
 952            ++$i; // ie. let $i = $j since we've just done $value[$i]
 953        }
 954
 955        if ($carry) {
 956            for (; $value[$i] == self::$maxDigit; ++$i) {
 957                $value[$i] = 0;
 958            }
 959            ++$value[$i];
 960        }
 961
 962        return array(
 963            self::VALUE => $this->_trim($value),
 964            self::SIGN => $x_negative
 965        );
 966    }
 967
 968    /**
 969     * Subtracts two BigIntegers.
 970     *
 971     * Here's an example:
 972     * <code>
 973     * <?php
 974     *    $a = new \phpseclib\Math\BigInteger('10');
 975     *    $b = new \phpseclib\Math\BigInteger('20');
 976     *
 977     *    $c = $a->subtract($b);
 978     *
 979     *    echo $c->toString(); // outputs -10
 980     * ?>
 981     * </code>
 982     *
 983     * @param \phpseclib\Math\BigInteger $y
 984     * @return \phpseclib\Math\BigInteger
 985     * @access public
 986     * @internal Performs base-2**52 subtraction
 987     */
 988    function subtract($y)
 989    {
 990        switch (MATH_BIGINTEGER_MODE) {
 991            case self::MODE_GMP:
 992                $temp = new static();
 993                $temp->value = gmp_sub($this->value, $y->value);
 994
 995                return $this->_normalize($temp);
 996            case self::MODE_BCMATH:
 997                $temp = new static();
 998                $temp->value = bcsub($this->value, $y->value, 0);
 999
1000                return $this->_normalize($temp);
1001        }
1002
1003        $temp = $this->_subtract($this->value, $this->is_negative, $y->value, $y->is_negative);
1004
1005        $result = new static();
1006        $result->value = $temp[self::VALUE];
1007        $result->is_negative = $temp[self::SIGN];
1008
1009        return $this->_normalize($result);
1010    }
1011
1012    /**
1013     * Performs subtraction.
1014     *
1015     * @param array $x_value
1016     * @param bool $x_negative
1017     * @param array $y_value
1018     * @param bool $y_negative
1019     * @return array
1020     * @access private
1021     */
1022    function _subtract($x_value, $x_negative, $y_value, $y_negative)
1023    {
1024        $x_size = count($x_value);
1025        $y_size = count($y_value);
1026
1027        if ($x_size == 0) {
1028            return array(
1029                self::VALUE => $y_value,
1030                self::SIGN => !$y_negative
1031            );
1032        } elseif ($y_size == 0) {
1033            return array(
1034                self::VALUE => $x_value,
1035                self::SIGN => $x_negative
1036            );
1037        }
1038
1039        // add, if appropriate (ie. -$x - +$y or +$x - -$y)
1040        if ($x_negative != $y_negative) {
1041            $temp = $this->_add($x_value, false, $y_value, false);
1042            $temp[self::SIGN] = $x_negative;
1043
1044            return $temp;
1045        }
1046
1047        $diff = $this->_compare($x_value, $x_negative, $y_value, $y_negative);
1048
1049        if (!$diff) {
1050            return array(
1051                self::VALUE => array(),
1052                self::SIGN => false
1053            );
1054        }
1055
1056        // switch $x and $y around, if appropriate.
1057        if ((!$x_negative && $diff < 0) || ($x_negative && $diff > 0)) {
1058            $temp = $x_value;
1059            $x_value = $y_value;
1060            $y_value = $temp;
1061
1062            $x_negative = !$x_negative;
1063
1064            $x_size = count($x_value);
1065            $y_size = count($y_value);
1066        }
1067
1068        // at this point, $x_value should be at least as big as - if not bigger than - $y_value
1069
1070        $carry = 0;
1071        for ($i = 0, $j = 1; $j < $y_size; $i+=2, $j+=2) {
1072            $sum = $x_value[$j] * self::$baseFull + $x_value[$i] - $y_value[$j] * self::$baseFull - $y_value[$i] - $carry;
1073            $carry = $sum < 0; // eg. floor($sum / 2**52); only possible values (in any base) are 0 and 1
1074            $sum = $carry ? $sum + self::$maxDigit2 : $sum;
1075
1076            $temp = self::$base === 26 ? intval($sum / 0x4000000) : ($sum >> 31);
1077
1078            $x_value[$i] = (int) ($sum - self::$baseFull * $temp);
1079            $x_value[$j] = $temp;
1080        }
1081
1082        if ($j == $y_size) { // ie. if $y_size is odd
1083            $sum = $x_value[$i] - $y_value[$i] - $carry;
1084            $carry = $sum < 0;
1085            $x_value[$i] = $carry ? $sum + self::$baseFull : $sum;
1086            ++$i;
1087        }
1088
1089        if ($carry) {
1090            for (; !$x_value[$i]; ++$i) {
1091                $x_value[$i] = self::$maxDigit;
1092            }
1093            --$x_value[$i];
1094        }
1095
1096        return array(
1097            self::VALUE => $this->_trim($x_value),
1098            self::SIGN => $x_negative
1099        );
1100    }
1101
1102    /**
1103     * Multiplies two BigIntegers
1104     *
1105     * Here's an example:
1106     * <code>
1107     * <?php
1108     *    $a = new \phpseclib\Math\BigInteger('10');
1109     *    $b = new \phpseclib\Math\BigInteger('20');
1110     *
1111     *    $c = $a->multiply($b);
1112     *
1113     *    echo $c->toString(); // outputs 200
1114     * ?>
1115     * </code>
1116     *
1117     * @param \phpseclib\Math\BigInteger $x
1118     * @return \phpseclib\Math\BigInteger
1119     * @access public
1120     */
1121    function multiply($x)
1122    {
1123        switch (MATH_BIGINTEGER_MODE) {
1124            case self::MODE_GMP:
1125                $temp = new static();
1126                $temp->value = gmp_mul($this->value, $x->value);
1127
1128                return $this->_normalize($temp);
1129            case self::MODE_BCMATH:
1130                $temp = new static();
1131                $temp->value = bcmul($this->value, $x->value, 0);
1132
1133                return $this->_normalize($temp);
1134        }
1135
1136        $temp = $this->_multiply($this->value, $this->is_negative, $x->value, $x->is_negative);
1137
1138        $product = new static();
1139        $product->value = $temp[self::VALUE];
1140        $product->is_negative = $temp[self::SIGN];
1141
1142        return $this->_normalize($product);
1143    }
1144
1145    /**
1146     * Performs multiplication.
1147     *
1148     * @param array $x_value
1149     * @param bool $x_negative
1150     * @param array $y_value
1151     * @param bool $y_negative
1152     * @return array
1153     * @access private
1154     */
1155    function _multiply($x_value, $x_negative, $y_value, $y_negative)
1156    {
1157        //if ( $x_value == $y_value ) {
1158        //    return array(
1159        //        self::VALUE => $this->_square($x_value),
1160        //        self::SIGN => $x_sign != $y_value
1161        //    );
1162        //}
1163
1164        $x_length = count($x_value);
1165        $y_length = count($y_value);
1166
1167        if (!$x_length || !$y_length) { // a 0 is being multiplied
1168            return array(
1169                self::VALUE => array(),
1170                self::SIGN => false
1171            );
1172        }
1173
1174        return array(
1175            self::VALUE => min($x_length, $y_length) < 2 * self::KARATSUBA_CUTOFF ?
1176                $this->_trim($this->_regularMultiply($x_value, $y_value)) :
1177                $this->_trim($this->_karatsuba($x_value, $y_value)),
1178            self::SIGN => $x_negative != $y_negative
1179        );
1180    }
1181
1182    /**
1183     * Performs long multiplication on two BigIntegers
1184     *
1185     * Modeled after 'multiply' in MutableBigInteger.java.
1186     *
1187     * @param array $x_value
1188     * @param array $y_value
1189     * @return array
1190     * @access private
1191     */
1192    function _regularMultiply($x_value, $y_value)
1193    {
1194        $x_length = count($x_value);
1195        $y_length = count($y_value);
1196
1197        if (!$x_length || !$y_length) { // a 0 is being multiplied
1198            return array();
1199        }
1200
1201        if ($x_length < $y_length) {
1202            $temp = $x_value;
1203            $x_value = $y_value;
1204            $y_value = $temp;
1205
1206            $x_length = count($x_value);
1207            $y_length = count($y_value);
1208        }
1209
1210        $product_value = $this->_array_repeat(0, $x_length + $y_length);
1211
1212        // the following for loop could be removed if the for loop following it
1213        // (the one with nested for loops) initially set $i to 0, but
1214        // doing so would also make the result in one set of unnecessary adds,
1215        // since on the outermost loops first pass, $product->value[$k] is going
1216        // to always be 0
1217
1218        $carry = 0;
1219
1220        for ($j = 0; $j < $x_length; ++$j) { // ie. $i = 0
1221            $temp = $x_value[$j] * $y_value[0] + $carry; // $product_value[$k] == 0
1222            $carry = self::$base === 26 ? intval($temp / 0x4000000) : ($temp >> 31);
1223            $product_value[$j] = (int) ($temp - self::$baseFull * $carry);
1224        }
1225
1226        $product_value[$j] = $carry;
1227
1228        // the above for loop is what the previous comment was talking about.  the
1229        // following for loop is the "one with nested for loops"
1230        for ($i = 1; $i < $y_length; ++$i) {
1231            $carry = 0;
1232
1233            for ($j = 0, $k = $i; $j < $x_length; ++$j, ++$k) {
1234                $temp = $product_value[$k] + $x_value[$j] * $y_value[$i] + $carry;
1235                $carry = self::$base === 26 ? intval($temp / 0x4000000) : ($temp >> 31);
1236                $product_value[$k] = (int) ($temp - self::$baseFull * $carry);
1237            }
1238
1239            $product_value[$k] = $carry;
1240        }
1241
1242        return $product_value;
1243    }
1244
1245    /**
1246     * Performs Karatsuba multiplication on two BigIntegers
1247     *
1248     * See {@link http://en.wikipedia.org/wiki/Karatsuba_algorithm Karatsuba algorithm} and
1249     * {@link http://math.libtomcrypt.com/files/tommath.pdf#page=120 MPM 5.2.3}.
1250     *
1251     * @param array $x_value
1252     * @param array $y_value
1253     * @return array
1254     * @access private
1255     */
1256    function _karatsuba($x_value, $y_value)
1257    {
1258        $m = min(count($x_value) >> 1, count($y_value) >> 1);
1259
1260        if ($m < self::KARATSUBA_CUTOFF) {
1261            return $this->_regularMultiply($x_value, $y_value);
1262        }
1263
1264        $x1 = array_slice($x_value, $m);
1265        $x0 = array_slice($x_value, 0, $m);
1266        $y1 = array_slice($y_value, $m);
1267        $y0 = array_slice($y_value, 0, $m);
1268
1269        $z2 = $this->_karatsuba($x1, $y1);
1270        $z0 = $this->_karatsuba($x0, $y0);
1271
1272        $z1 = $this->_add($x1, false, $x0, false);
1273        $temp = $this->_add($y1, false, $y0, false);
1274        $z1 = $this->_karatsuba($z1[self::VALUE], $temp[self::VALUE]);
1275        $temp = $this->_add($z2, false, $z0, false);
1276        $z1 = $this->_subtract($z1, false, $temp[self::VALUE], false);
1277
1278        $z2 = array_merge(array_fill(0, 2 * $m, 0), $z2);
1279        $z1[self::VALUE] = array_merge(array_fill(0, $m, 0), $z1[self::VALUE]);
1280
1281        $xy = $this->_add($z2, false, $z1[self::VALUE], $z1[self::SIGN]);
1282        $xy = $this->_add($xy[self::VALUE], $xy[self::SIGN], $z0, false);
1283
1284        return $xy[self::VALUE];
1285    }
1286
1287    /**
1288     * Performs squaring
1289     *
1290     * @param array $x
1291     * @return array
1292     * @access private
1293     */
1294    function _square($x = false)
1295    {
1296        return count($x) < 2 * self::KARATSUBA_CUTOFF ?
1297            $this->_trim($this->_baseSquare($x)) :
1298            $this->_trim($this->_karatsubaSquare($x));
1299    }
1300
1301    /**
1302     * Performs traditional squaring on two BigIntegers
1303     *
1304     * Squaring can be done faster than multiplying a number by itself can be.  See
1305     * {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=7 HAC 14.2.4} /
1306     * {@link http://math.libtomcrypt.com/files/tommath.pdf#page=141 MPM 5.3} for more information.
1307     *
1308     * @param array $value
1309     * @return array
1310     * @access private
1311     */
1312    function _baseSquare($value)
1313    {
1314        if (empty($value)) {
1315            return array();
1316        }
1317        $square_value = $this->_array_repeat(0, 2 * count($value));
1318
1319        for ($i = 0, $max_index = count($value) - 1; $i <= $max_index; ++$i) {
1320            $i2 = $i << 1;
1321
1322            $temp = $square_value[$i2] + $value[$i] * $value[$i];
1323            $carry = self::$base === 26 ? intval($temp / 0x4000000) : ($temp >> 31);
1324            $square_value[$i2] = (int) ($temp - self::$baseFull * $carry);
1325
1326            // note how we start from $i+1 instead of 0 as we do in multiplication.
1327            for ($j = $i + 1, $k = $i2 + 1; $j <= $max_index; ++$j, ++$k) {
1328                $temp = $square_value[$k] + 2 * $value[$j] * $value[$i] + $carry;
1329                $carry = self::$base === 26 ? intval($temp / 0x4000000) : ($temp >> 31);
1330                $square_value[$k] = (int) ($temp - self::$baseFull * $carry);
1331            }
1332
1333            // the following line can yield values larger 2**15.  at this point, PHP should switch
1334            // over to floats.
1335            $square_value[$i + $max_index + 1] = $carry;
1336        }
1337
1338        return $square_value;
1339    }
1340
1341    /**
1342     * Performs Karatsuba "squaring" on two BigIntegers
1343     *
1344     * See {@link http://en.wikipedia.org/wiki/Karatsuba_algorithm Karatsuba algorithm} and
1345     * {@link http://math.libtomcrypt.com/files/tommath.pdf#page=151 MPM 5.3.4}.
1346     *
1347     * @param array $value
1348     * @return array
1349     * @access private
1350     */
1351    function _karatsubaSquare($value)
1352    {
1353        $m = count($value) >> 1;
1354
1355        if ($m < self::KARATSUBA_CUTOFF) {
1356            return $this->_baseSquare($value);
1357        }
1358
1359        $x1 = array_slice($value, $m);
1360        $x0 = array_slice($value, 0, $m);
1361
1362        $z2 = $this->_karatsubaSquare($x1);
1363        $z0 = $this->_karatsubaSquare($x0);
1364
1365        $z1 = $this->_add($x1, false, $x0, false);
1366        $z1 = $this->_karatsubaSquare($z1[self::VALUE]);
1367        $temp = $this->_add($z2, false, $z0, false);
1368        $z1 = $this->_subtract($z1, false, $temp[self::VALUE], false);
1369
1370        $z2 = array_merge(array_fill(0, 2 * $m, 0), $z2);
1371        $z1[self::VALUE] = array_merge(array_fill(0, $m, 0), $z1[self::VALUE]);
1372
1373        $xx = $this->_add($z2, false, $z1[self::VALUE], $z1[self::SIGN]);
1374        $xx = $this->_add($xx[self::VALUE], $xx[self::SIGN], $z0, false);
1375
1376        return $xx[self::VALUE];
1377    }
1378
1379    /**
1380     * Divides two BigIntegers.
1381     *
1382     * Returns an array whose first element contains the quotient and whose second element contains the
1383     * "common residue".  If the remainder would be positive, the "common residue" and the remainder are the
1384     * same.  If the remainder would be negative, the "common residue" is equal to the sum of the remainder
1385     * and the divisor (basically, the "common residue" is the first positive modulo).
1386     *
1387     * Here's an example:
1388     * <code>
1389     * <?php
1390     *    $a = new \phpseclib\Math\BigInteger('10');
1391     *    $b = new \phpseclib\Math\BigInteger('20');
1392     *
1393     *    list($quotient, $remainder) = $a->divide($b);
1394     *
1395     *    echo $quotient->toString(); // outputs 0
1396     *    echo "\r\n";
1397     *    echo $remainder->toString(); // outputs 10
1398     * ?>
1399     * </code>
1400     *
1401     * @param \phpseclib\Math\BigInteger $y
1402     * @return array
1403     * @access public
1404     * @internal This function is based off of {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=9 HAC 14.20}.
1405     */
1406    function divide($y)
1407    {
1408        switch (MATH_BIGINTEGER_MODE) {
1409            case self::MODE_GMP:
1410                $quotient = new static();
1411                $remainder = new static();
1412
1413                list($quotient->value, $remainder->value) = gmp_div_qr($this->value, $y->value);
1414
1415                if (gmp_sign($remainder->value) < 0) {
1416                    $remainder->value = gmp_add($remainder->value, gmp_abs($y->value));
1417                }
1418
1419                return array($this->_normalize($quotient), $this->_normalize($remainder));
1420            case self::MODE_BCMATH:
1421                $quotient = new static();
1422                $remainder = new static();
1423
1424                $quotient->value = bcdiv($this->value, $y->value, 0);
1425                $remainder->value = bcmod($this->value, $y->value);
1426
1427                if ($remainder->value[0] == '-') {
1428                    $remainder->value = bcadd($remainder->value, $y->value[0] == '-' ? substr($y->value, 1) : $y->value, 0);
1429                }
1430
1431                return array($this->_normalize($quotient), $this->_normalize($remainder));
1432        }
1433
1434        if (count($y->value) == 1) {
1435            list($q, $r) = $this->_divide_digit($this->value, $y->value[0]);
1436            $quotient = new static();
1437            $remainder = new static();
1438            $quotient->value = $q;
1439            $remainder->value = array($r);
1440            $quotient->is_negative = $this->is_negative != $y->is_negative;
1441            return array($this->_normalize($quotient), $this->_normalize($remainder));
1442        }
1443
1444        static $zero;
1445        if (!isset($zero)) {
1446            $zero = new static();
1447        }
1448
1449        $x = $this->copy();
1450        $y = $y->copy();
1451
1452        $x_sign = $x->is_negative;
1453        $y_sign = $y->is_negative;
1454
1455        $x->is_negative = $y->is_negative = false;
1456
1457        $diff = $x->compare($y);
1458
1459        if (!$diff) {
1460            $temp = new static();
1461            $temp->value = array(1);
1462            $temp->is_negative = $x_sign != $y_sign;
1463            return array($this->_normalize($temp), $this->_normalize(new static()));
1464        }
1465
1466        if ($diff < 0) {
1467            // if $x is negative, "add" $y.
1468            if ($x_sign) {
1469                $x = $y->subtract($x);
1470            }
1471            return array($this->_normalize(new static()), $this->_normalize($x));
1472        }
1473
1474        // normalize $x and $y as described in HAC 14.23 / 14.24
1475        $msb = $y->value[count($y->value) - 1];
1476        for ($shift = 0; !($msb & self::$msb); ++$shift) {
1477            $msb <<= 1;
1478        }
1479        $x->_lshift($shift);
1480        $y->_lshift($shift);
1481        $y_value = &$y->value;
1482
1483        $x_max = count($x->value) - 1;
1484        $y_max = count($y->value) - 1;
1485
1486        $quotient = new static();
1487        $quotient_value = &$quotient->value;
1488        $quotient_value = $this->_array_repeat(0, $x_max - $y_max + 1);
1489
1490        static $temp, $lhs, $rhs;
1491        if (!isset($temp)) {
1492            $temp = new static();
1493            $lhs =  new static();
1494            $rhs =  new static();
1495        }
1496        $temp_value = &$temp->value;
1497        $rhs_value =  &$rhs->value;
1498
1499        // $temp = $y << ($x_max - $y_max-1) in base 2**26
1500        $temp_value = array_merge($this->_array_repeat(0, $x_max - $y_max), $y_value);
1501
1502        while ($x->compare($temp) >= 0) {
1503            // calculate the "common residue"
1504            ++$quotient_value[$x_max - $y_max];
1505            $x = $x->subtract($temp);
1506            $x_max = count($x->value) - 1;
1507        }
1508
1509        for ($i = $x_max; $i >= $y_max + 1; --$i) {
1510            $x_value = &$x->value;
1511            $x_window = array(
1512                isset($x_value[$i]) ? $x_value[$i] : 0,
1513                isset($x_value[$i - 1]) ? $x_value[$i - 1] : 0,
1514                isset($x_value[$i - 2]) ? $x_value[$i - 2] : 0
1515            );
1516            $y_window = array(
1517                $y_value[$y_max],
1518                ($y_max > 0) ? $y_value[$y_max - 1] : 0
1519            );
1520
1521            $q_index = $i - $y_max - 1;
1522            if ($x_window[0] == $y_window[0]) {
1523                $quotient_value[$q_index] = self::$maxDigit;
1524            } else {
1525                $quotient_value[$q_index] = $this->_safe_divide(
1526                    $x_window[0] * self::$baseFull + $x_windo…

Large files files are truncated, but you can click here to view the full file