PageRenderTime 9ms CodeModel.GetById 6ms app.highlight 47ms RepoModel.GetById 1ms app.codeStats 1ms

/vendor/phpseclib/Math/BigInteger.php

http://github.com/spotweb/spotweb
PHP | 3630 lines | 1917 code | 482 blank | 1231 comment | 384 complexity | b02a8604aac27beca3892fa471ee8702 MD5 | raw file

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

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

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