]> git.mxchange.org Git - quix0rs-gnu-social.git/blob - plugins/OStatus/extlib/Math/BigInteger.php
Adding Crypt library from http://phpseclib.sourceforge.net/
[quix0rs-gnu-social.git] / plugins / OStatus / extlib / Math / BigInteger.php
1 <?php\r
2 /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */\r
3 \r
4 /**\r
5  * Pure-PHP arbitrary precision integer arithmetic library.\r
6  *\r
7  * Supports base-2, base-10, base-16, and base-256 numbers.  Uses the GMP or BCMath extensions, if available,\r
8  * and an internal implementation, otherwise.\r
9  *\r
10  * PHP versions 4 and 5\r
11  *\r
12  * {@internal (all DocBlock comments regarding implementation - such as the one that follows - refer to the \r
13  * {@link MATH_BIGINTEGER_MODE_INTERNAL MATH_BIGINTEGER_MODE_INTERNAL} mode)\r
14  *\r
15  * Math_BigInteger uses base-2**26 to perform operations such as multiplication and division and\r
16  * base-2**52 (ie. two base 2**26 digits) to perform addition and subtraction.  Because the largest possible\r
17  * value when multiplying two base-2**26 numbers together is a base-2**52 number, double precision floating\r
18  * point numbers - numbers that should be supported on most hardware and whose significand is 53 bits - are\r
19  * used.  As a consequence, bitwise operators such as >> and << cannot be used, nor can the modulo operator %,\r
20  * which only supports integers.  Although this fact will slow this library down, the fact that such a high\r
21  * base is being used should more than compensate.\r
22  *\r
23  * When PHP version 6 is officially released, we'll be able to use 64-bit integers.  This should, once again,\r
24  * allow bitwise operators, and will increase the maximum possible base to 2**31 (or 2**62 for addition /\r
25  * subtraction).\r
26  *\r
27  * Useful resources are as follows:\r
28  *\r
29  *  - {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf Handbook of Applied Cryptography (HAC)}\r
30  *  - {@link http://math.libtomcrypt.com/files/tommath.pdf Multi-Precision Math (MPM)}\r
31  *  - Java's BigInteger classes.  See /j2se/src/share/classes/java/math in jdk-1_5_0-src-jrl.zip\r
32  *\r
33  * One idea for optimization is to use the comba method to reduce the number of operations performed.\r
34  * MPM uses this quite extensively.  The following URL elaborates:\r
35  *\r
36  * {@link http://www.everything2.com/index.pl?node_id=1736418}}}\r
37  *\r
38  * Here's an example of how to use this library:\r
39  * <code>\r
40  * <?php\r
41  *    include('Math/BigInteger.php');\r
42  *\r
43  *    $a = new Math_BigInteger(2);\r
44  *    $b = new Math_BigInteger(3);\r
45  *\r
46  *    $c = $a->add($b);\r
47  *\r
48  *    echo $c->toString(); // outputs 5\r
49  * ?>\r
50  * </code>\r
51  *\r
52  * LICENSE: This library is free software; you can redistribute it and/or\r
53  * modify it under the terms of the GNU Lesser General Public\r
54  * License as published by the Free Software Foundation; either\r
55  * version 2.1 of the License, or (at your option) any later version.\r
56  *\r
57  * This library is distributed in the hope that it will be useful,\r
58  * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
59  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
60  * Lesser General Public License for more details.\r
61  *\r
62  * You should have received a copy of the GNU Lesser General Public\r
63  * License along with this library; if not, write to the Free Software\r
64  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,\r
65  * MA  02111-1307  USA\r
66  *\r
67  * @category   Math\r
68  * @package    Math_BigInteger\r
69  * @author     Jim Wigginton <terrafrost@php.net>\r
70  * @copyright  MMVI Jim Wigginton\r
71  * @license    http://www.gnu.org/licenses/lgpl.txt\r
72  * @version    $Id: BigInteger.php,v 1.18 2009/12/04 19:12:18 terrafrost Exp $\r
73  * @link       http://pear.php.net/package/Math_BigInteger\r
74  */\r
75 \r
76 /**#@+\r
77  * @access private\r
78  * @see Math_BigInteger::_slidingWindow()\r
79  */\r
80 /**\r
81  * @see Math_BigInteger::_montgomery()\r
82  * @see Math_BigInteger::_prepMontgomery()\r
83  */\r
84 define('MATH_BIGINTEGER_MONTGOMERY', 0);\r
85 /**\r
86  * @see Math_BigInteger::_barrett()\r
87  */\r
88 define('MATH_BIGINTEGER_BARRETT', 1);\r
89 /**\r
90  * @see Math_BigInteger::_mod2()\r
91  */\r
92 define('MATH_BIGINTEGER_POWEROF2', 2);\r
93 /**\r
94  * @see Math_BigInteger::_remainder()\r
95  */\r
96 define('MATH_BIGINTEGER_CLASSIC', 3);\r
97 /**\r
98  * @see Math_BigInteger::__clone()\r
99  */\r
100 define('MATH_BIGINTEGER_NONE', 4);\r
101 /**#@-*/\r
102 \r
103 /**#@+\r
104  * @access private\r
105  * @see Math_BigInteger::_montgomery()\r
106  * @see Math_BigInteger::_barrett()\r
107  */\r
108 /**\r
109  * $cache[MATH_BIGINTEGER_VARIABLE] tells us whether or not the cached data is still valid.\r
110  */\r
111 define('MATH_BIGINTEGER_VARIABLE', 0);\r
112 /**\r
113  * $cache[MATH_BIGINTEGER_DATA] contains the cached data.\r
114  */\r
115 define('MATH_BIGINTEGER_DATA', 1);\r
116 /**#@-*/\r
117 \r
118 /**#@+\r
119  * @access private\r
120  * @see Math_BigInteger::Math_BigInteger()\r
121  */\r
122 /**\r
123  * To use the pure-PHP implementation\r
124  */\r
125 define('MATH_BIGINTEGER_MODE_INTERNAL', 1);\r
126 /**\r
127  * To use the BCMath library\r
128  *\r
129  * (if enabled; otherwise, the internal implementation will be used)\r
130  */\r
131 define('MATH_BIGINTEGER_MODE_BCMATH', 2);\r
132 /**\r
133  * To use the GMP library\r
134  *\r
135  * (if present; otherwise, either the BCMath or the internal implementation will be used)\r
136  */\r
137 define('MATH_BIGINTEGER_MODE_GMP', 3);\r
138 /**#@-*/\r
139 \r
140 /**\r
141  * The largest digit that may be used in addition / subtraction\r
142  *\r
143  * (we do pow(2, 52) instead of using 4503599627370496, directly, because some PHP installations\r
144  *  will truncate 4503599627370496)\r
145  *\r
146  * @access private\r
147  */\r
148 define('MATH_BIGINTEGER_MAX_DIGIT52', pow(2, 52));\r
149 \r
150 /**\r
151  * Karatsuba Cutoff\r
152  *\r
153  * At what point do we switch between Karatsuba multiplication and schoolbook long multiplication?\r
154  *\r
155  * @access private\r
156  */\r
157 define('MATH_BIGINTEGER_KARATSUBA_CUTOFF', 15);\r
158 \r
159 /**\r
160  * Pure-PHP arbitrary precision integer arithmetic library. Supports base-2, base-10, base-16, and base-256\r
161  * numbers.\r
162  *\r
163  * @author  Jim Wigginton <terrafrost@php.net>\r
164  * @version 1.0.0RC3\r
165  * @access  public\r
166  * @package Math_BigInteger\r
167  */\r
168 class Math_BigInteger {\r
169     /**\r
170      * Holds the BigInteger's value.\r
171      *\r
172      * @var Array\r
173      * @access private\r
174      */\r
175     var $value;\r
176 \r
177     /**\r
178      * Holds the BigInteger's magnitude.\r
179      *\r
180      * @var Boolean\r
181      * @access private\r
182      */\r
183     var $is_negative = false;\r
184 \r
185     /**\r
186      * Random number generator function\r
187      *\r
188      * @see setRandomGenerator()\r
189      * @access private\r
190      */\r
191     var $generator = 'mt_rand';\r
192 \r
193     /**\r
194      * Precision\r
195      *\r
196      * @see setPrecision()\r
197      * @access private\r
198      */\r
199     var $precision = -1;\r
200 \r
201     /**\r
202      * Precision Bitmask\r
203      *\r
204      * @see setPrecision()\r
205      * @access private\r
206      */\r
207     var $bitmask = false;\r
208 \r
209     /**\r
210      * Converts base-2, base-10, base-16, and binary strings (eg. base-256) to BigIntegers.\r
211      *\r
212      * If the second parameter - $base - is negative, then it will be assumed that the number's are encoded using\r
213      * two's compliment.  The sole exception to this is -10, which is treated the same as 10 is.\r
214      *\r
215      * Here's an example:\r
216      * <code>\r
217      * <?php\r
218      *    include('Math/BigInteger.php');\r
219      *\r
220      *    $a = new Math_BigInteger('0x32', 16); // 50 in base-16\r
221      *\r
222      *    echo $a->toString(); // outputs 50\r
223      * ?>\r
224      * </code>\r
225      *\r
226      * @param optional $x base-10 number or base-$base number if $base set.\r
227      * @param optional integer $base\r
228      * @return Math_BigInteger\r
229      * @access public\r
230      */\r
231     function Math_BigInteger($x = 0, $base = 10)\r
232     {\r
233         if ( !defined('MATH_BIGINTEGER_MODE') ) {\r
234             switch (true) {\r
235                 case extension_loaded('gmp'):\r
236                     define('MATH_BIGINTEGER_MODE', MATH_BIGINTEGER_MODE_GMP);\r
237                     break;\r
238                 case extension_loaded('bcmath'):\r
239                     define('MATH_BIGINTEGER_MODE', MATH_BIGINTEGER_MODE_BCMATH);\r
240                     break;\r
241                 default:\r
242                     define('MATH_BIGINTEGER_MODE', MATH_BIGINTEGER_MODE_INTERNAL);\r
243             }\r
244         }\r
245 \r
246         switch ( MATH_BIGINTEGER_MODE ) {\r
247             case MATH_BIGINTEGER_MODE_GMP:\r
248                 if (is_resource($x) && get_resource_type($x) == 'GMP integer') {\r
249                     $this->value = $x;\r
250                     return;\r
251                 }\r
252                 $this->value = gmp_init(0);\r
253                 break;\r
254             case MATH_BIGINTEGER_MODE_BCMATH:\r
255                 $this->value = '0';\r
256                 break;\r
257             default:\r
258                 $this->value = array();\r
259         }\r
260 \r
261         if ($x === 0) {\r
262             return;\r
263         }\r
264 \r
265         switch ($base) {\r
266             case -256:\r
267                 if (ord($x[0]) & 0x80) {\r
268                     $x = ~$x;\r
269                     $this->is_negative = true;\r
270                 }\r
271             case  256:\r
272                 switch ( MATH_BIGINTEGER_MODE ) {\r
273                     case MATH_BIGINTEGER_MODE_GMP:\r
274                         $sign = $this->is_negative ? '-' : '';\r
275                         $this->value = gmp_init($sign . '0x' . bin2hex($x));\r
276                         break;\r
277                     case MATH_BIGINTEGER_MODE_BCMATH:\r
278                         // round $len to the nearest 4 (thanks, DavidMJ!)\r
279                         $len = (strlen($x) + 3) & 0xFFFFFFFC;\r
280 \r
281                         $x = str_pad($x, $len, chr(0), STR_PAD_LEFT);\r
282 \r
283                         for ($i = 0; $i < $len; $i+= 4) {\r
284                             $this->value = bcmul($this->value, '4294967296'); // 4294967296 == 2**32\r
285                             $this->value = bcadd($this->value, 0x1000000 * ord($x[$i]) + ((ord($x[$i + 1]) << 16) | (ord($x[$i + 2]) << 8) | ord($x[$i + 3])));\r
286                         }\r
287 \r
288                         if ($this->is_negative) {\r
289                             $this->value = '-' . $this->value;\r
290                         }\r
291 \r
292                         break;\r
293                     // converts a base-2**8 (big endian / msb) number to base-2**26 (little endian / lsb)\r
294                     default:\r
295                         while (strlen($x)) {\r
296                             $this->value[] = $this->_bytes2int($this->_base256_rshift($x, 26));\r
297                         }\r
298                 }\r
299 \r
300                 if ($this->is_negative) {\r
301                     if (MATH_BIGINTEGER_MODE != MATH_BIGINTEGER_MODE_INTERNAL) {\r
302                         $this->is_negative = false;\r
303                     }\r
304                     $temp = $this->add(new Math_BigInteger('-1'));\r
305                     $this->value = $temp->value;\r
306                 }\r
307                 break;\r
308             case  16:\r
309             case -16:\r
310                 if ($base > 0 && $x[0] == '-') {\r
311                     $this->is_negative = true;\r
312                     $x = substr($x, 1);\r
313                 }\r
314 \r
315                 $x = preg_replace('#^(?:0x)?([A-Fa-f0-9]*).*#', '$1', $x);\r
316 \r
317                 $is_negative = false;\r
318                 if ($base < 0 && hexdec($x[0]) >= 8) {\r
319                     $this->is_negative = $is_negative = true;\r
320                     $x = bin2hex(~pack('H*', $x));\r
321                 }\r
322 \r
323                 switch ( MATH_BIGINTEGER_MODE ) {\r
324                     case MATH_BIGINTEGER_MODE_GMP:\r
325                         $temp = $this->is_negative ? '-0x' . $x : '0x' . $x;\r
326                         $this->value = gmp_init($temp);\r
327                         $this->is_negative = false;\r
328                         break;\r
329                     case MATH_BIGINTEGER_MODE_BCMATH:\r
330                         $x = ( strlen($x) & 1 ) ? '0' . $x : $x;\r
331                         $temp = new Math_BigInteger(pack('H*', $x), 256);\r
332                         $this->value = $this->is_negative ? '-' . $temp->value : $temp->value;\r
333                         $this->is_negative = false;\r
334                         break;\r
335                     default:\r
336                         $x = ( strlen($x) & 1 ) ? '0' . $x : $x;\r
337                         $temp = new Math_BigInteger(pack('H*', $x), 256);\r
338                         $this->value = $temp->value;\r
339                 }\r
340 \r
341                 if ($is_negative) {\r
342                     $temp = $this->add(new Math_BigInteger('-1'));\r
343                     $this->value = $temp->value;\r
344                 }\r
345                 break;\r
346             case  10:\r
347             case -10:\r
348                 $x = preg_replace('#^(-?[0-9]*).*#', '$1', $x);\r
349 \r
350                 switch ( MATH_BIGINTEGER_MODE ) {\r
351                     case MATH_BIGINTEGER_MODE_GMP:\r
352                         $this->value = gmp_init($x);\r
353                         break;\r
354                     case MATH_BIGINTEGER_MODE_BCMATH:\r
355                         // explicitly casting $x to a string is necessary, here, since doing $x[0] on -1 yields different\r
356                         // results then doing it on '-1' does (modInverse does $x[0])\r
357                         $this->value = (string) $x;\r
358                         break;\r
359                     default:\r
360                         $temp = new Math_BigInteger();\r
361 \r
362                         // array(10000000) is 10**7 in base-2**26.  10**7 is the closest to 2**26 we can get without passing it.\r
363                         $multiplier = new Math_BigInteger();\r
364                         $multiplier->value = array(10000000);\r
365 \r
366                         if ($x[0] == '-') {\r
367                             $this->is_negative = true;\r
368                             $x = substr($x, 1);\r
369                         }\r
370 \r
371                         $x = str_pad($x, strlen($x) + (6 * strlen($x)) % 7, 0, STR_PAD_LEFT);\r
372 \r
373                         while (strlen($x)) {\r
374                             $temp = $temp->multiply($multiplier);\r
375                             $temp = $temp->add(new Math_BigInteger($this->_int2bytes(substr($x, 0, 7)), 256));\r
376                             $x = substr($x, 7);\r
377                         }\r
378 \r
379                         $this->value = $temp->value;\r
380                 }\r
381                 break;\r
382             case  2: // base-2 support originally implemented by Lluis Pamies - thanks!\r
383             case -2:\r
384                 if ($base > 0 && $x[0] == '-') {\r
385                     $this->is_negative = true;\r
386                     $x = substr($x, 1);\r
387                 }\r
388 \r
389                 $x = preg_replace('#^([01]*).*#', '$1', $x);\r
390                 $x = str_pad($x, strlen($x) + (3 * strlen($x)) % 4, 0, STR_PAD_LEFT);\r
391 \r
392                 $str = '0x';\r
393                 while (strlen($x)) {\r
394                     $part = substr($x, 0, 4);\r
395                     $str.= dechex(bindec($part));\r
396                     $x = substr($x, 4);\r
397                 }\r
398 \r
399                 if ($this->is_negative) {\r
400                     $str = '-' . $str;\r
401                 }\r
402 \r
403                 $temp = new Math_BigInteger($str, 8 * $base); // ie. either -16 or +16\r
404                 $this->value = $temp->value;\r
405                 $this->is_negative = $temp->is_negative;\r
406 \r
407                 break;\r
408             default:\r
409                 // base not supported, so we'll let $this == 0\r
410         }\r
411     }\r
412 \r
413     /**\r
414      * Converts a BigInteger to a byte string (eg. base-256).\r
415      *\r
416      * Negative numbers are saved as positive numbers, unless $twos_compliment is set to true, at which point, they're\r
417      * saved as two's compliment.\r
418      *\r
419      * Here's an example:\r
420      * <code>\r
421      * <?php\r
422      *    include('Math/BigInteger.php');\r
423      *\r
424      *    $a = new Math_BigInteger('65');\r
425      *\r
426      *    echo $a->toBytes(); // outputs chr(65)\r
427      * ?>\r
428      * </code>\r
429      *\r
430      * @param Boolean $twos_compliment\r
431      * @return String\r
432      * @access public\r
433      * @internal Converts a base-2**26 number to base-2**8\r
434      */\r
435     function toBytes($twos_compliment = false)\r
436     {\r
437         if ($twos_compliment) {\r
438             $comparison = $this->compare(new Math_BigInteger());\r
439             if ($comparison == 0) {\r
440                 return $this->precision > 0 ? str_repeat(chr(0), ($this->precision + 1) >> 3) : '';\r
441             }\r
442 \r
443             $temp = $comparison < 0 ? $this->add(new Math_BigInteger(1)) : $this->copy();\r
444             $bytes = $temp->toBytes();\r
445 \r
446             if (empty($bytes)) { // eg. if the number we're trying to convert is -1\r
447                 $bytes = chr(0);\r
448             }\r
449 \r
450             if (ord($bytes[0]) & 0x80) {\r
451                 $bytes = chr(0) . $bytes;\r
452             }\r
453 \r
454             return $comparison < 0 ? ~$bytes : $bytes;\r
455         }\r
456 \r
457         switch ( MATH_BIGINTEGER_MODE ) {\r
458             case MATH_BIGINTEGER_MODE_GMP:\r
459                 if (gmp_cmp($this->value, gmp_init(0)) == 0) {\r
460                     return $this->precision > 0 ? str_repeat(chr(0), ($this->precision + 1) >> 3) : '';\r
461                 }\r
462 \r
463                 $temp = gmp_strval(gmp_abs($this->value), 16);\r
464                 $temp = ( strlen($temp) & 1 ) ? '0' . $temp : $temp;\r
465                 $temp = pack('H*', $temp);\r
466 \r
467                 return $this->precision > 0 ?\r
468                     substr(str_pad($temp, $this->precision >> 3, chr(0), STR_PAD_LEFT), -($this->precision >> 3)) :\r
469                     ltrim($temp, chr(0));\r
470             case MATH_BIGINTEGER_MODE_BCMATH:\r
471                 if ($this->value === '0') {\r
472                     return $this->precision > 0 ? str_repeat(chr(0), ($this->precision + 1) >> 3) : '';\r
473                 }\r
474 \r
475                 $value = '';\r
476                 $current = $this->value;\r
477 \r
478                 if ($current[0] == '-') {\r
479                     $current = substr($current, 1);\r
480                 }\r
481 \r
482                 // we don't do four bytes at a time because then numbers larger than 1<<31 would be negative\r
483                 // two's complimented numbers, which would break chr.\r
484                 while (bccomp($current, '0') > 0) {\r
485                     $temp = bcmod($current, 0x1000000);\r
486                     $value = chr($temp >> 16) . chr($temp >> 8) . chr($temp) . $value;\r
487                     $current = bcdiv($current, 0x1000000);\r
488                 }\r
489 \r
490                 return $this->precision > 0 ?\r
491                     substr(str_pad($value, $this->precision >> 3, chr(0), STR_PAD_LEFT), -($this->precision >> 3)) :\r
492                     ltrim($value, chr(0));\r
493         }\r
494 \r
495         if (!count($this->value)) {\r
496             return $this->precision > 0 ? str_repeat(chr(0), ($this->precision + 1) >> 3) : '';\r
497         }\r
498         $result = $this->_int2bytes($this->value[count($this->value) - 1]);\r
499 \r
500         $temp = $this->copy();\r
501 \r
502         for ($i = count($temp->value) - 2; $i >= 0; $i--) {\r
503             $temp->_base256_lshift($result, 26);\r
504             $result = $result | str_pad($temp->_int2bytes($temp->value[$i]), strlen($result), chr(0), STR_PAD_LEFT);\r
505         }\r
506 \r
507         return $this->precision > 0 ?\r
508             substr(str_pad($result, $this->precision >> 3, chr(0), STR_PAD_LEFT), -($this->precision >> 3)) :\r
509             $result;\r
510     }\r
511 \r
512     /**\r
513      * Converts a BigInteger to a hex string (eg. base-16)).\r
514      *\r
515      * Negative numbers are saved as positive numbers, unless $twos_compliment is set to true, at which point, they're\r
516      * saved as two's compliment.\r
517      *\r
518      * Here's an example:\r
519      * <code>\r
520      * <?php\r
521      *    include('Math/BigInteger.php');\r
522      *\r
523      *    $a = new Math_BigInteger('65');\r
524      *\r
525      *    echo $a->toHex(); // outputs '41'\r
526      * ?>\r
527      * </code>\r
528      *\r
529      * @param Boolean $twos_compliment\r
530      * @return String\r
531      * @access public\r
532      * @internal Converts a base-2**26 number to base-2**8\r
533      */\r
534     function toHex($twos_compliment = false)\r
535     {\r
536         return bin2hex($this->toBytes($twos_compliment));\r
537     }\r
538 \r
539     /**\r
540      * Converts a BigInteger to a bit string (eg. base-2).\r
541      *\r
542      * Negative numbers are saved as positive numbers, unless $twos_compliment is set to true, at which point, they're\r
543      * saved as two's compliment.\r
544      *\r
545      * Here's an example:\r
546      * <code>\r
547      * <?php\r
548      *    include('Math/BigInteger.php');\r
549      *\r
550      *    $a = new Math_BigInteger('65');\r
551      *\r
552      *    echo $a->toBits(); // outputs '1000001'\r
553      * ?>\r
554      * </code>\r
555      *\r
556      * @param Boolean $twos_compliment\r
557      * @return String\r
558      * @access public\r
559      * @internal Converts a base-2**26 number to base-2**2\r
560      */\r
561     function toBits($twos_compliment = false)\r
562     {\r
563         $hex = $this->toHex($twos_compliment);\r
564         $bits = '';\r
565         for ($i = 0; $i < strlen($hex); $i+=8) {\r
566             $bits.= str_pad(decbin(hexdec(substr($hex, $i, 8))), 32, '0', STR_PAD_LEFT);\r
567         }\r
568         return $this->precision > 0 ? substr($bits, -$this->precision) : ltrim($bits, '0');\r
569     }\r
570 \r
571     /**\r
572      * Converts a BigInteger to a base-10 number.\r
573      *\r
574      * Here's an example:\r
575      * <code>\r
576      * <?php\r
577      *    include('Math/BigInteger.php');\r
578      *\r
579      *    $a = new Math_BigInteger('50');\r
580      *\r
581      *    echo $a->toString(); // outputs 50\r
582      * ?>\r
583      * </code>\r
584      *\r
585      * @return String\r
586      * @access public\r
587      * @internal Converts a base-2**26 number to base-10**7 (which is pretty much base-10)\r
588      */\r
589     function toString()\r
590     {\r
591         switch ( MATH_BIGINTEGER_MODE ) {\r
592             case MATH_BIGINTEGER_MODE_GMP:\r
593                 return gmp_strval($this->value);\r
594             case MATH_BIGINTEGER_MODE_BCMATH:\r
595                 if ($this->value === '0') {\r
596                     return '0';\r
597                 }\r
598 \r
599                 return ltrim($this->value, '0');\r
600         }\r
601 \r
602         if (!count($this->value)) {\r
603             return '0';\r
604         }\r
605 \r
606         $temp = $this->copy();\r
607         $temp->is_negative = false;\r
608 \r
609         $divisor = new Math_BigInteger();\r
610         $divisor->value = array(10000000); // eg. 10**7\r
611         $result = '';\r
612         while (count($temp->value)) {\r
613             list($temp, $mod) = $temp->divide($divisor);\r
614             $result = str_pad($mod->value[0], 7, '0', STR_PAD_LEFT) . $result;\r
615         }\r
616         $result = ltrim($result, '0');\r
617 \r
618         if ($this->is_negative) {\r
619             $result = '-' . $result;\r
620         }\r
621 \r
622         return $result;\r
623     }\r
624 \r
625     /**\r
626      * Copy an object\r
627      *\r
628      * PHP5 passes objects by reference while PHP4 passes by value.  As such, we need a function to guarantee\r
629      * that all objects are passed by value, when appropriate.  More information can be found here:\r
630      *\r
631      * {@link http://php.net/language.oop5.basic#51624}\r
632      *\r
633      * @access public\r
634      * @see __clone()\r
635      * @return Math_BigInteger\r
636      */\r
637     function copy()\r
638     {\r
639         $temp = new Math_BigInteger();\r
640         $temp->value = $this->value;\r
641         $temp->is_negative = $this->is_negative;\r
642         $temp->generator = $this->generator;\r
643         $temp->precision = $this->precision;\r
644         $temp->bitmask = $this->bitmask;\r
645         return $temp;\r
646     }\r
647 \r
648     /**\r
649      *  __toString() magic method\r
650      *\r
651      * Will be called, automatically, if you're supporting just PHP5.  If you're supporting PHP4, you'll need to call\r
652      * toString().\r
653      *\r
654      * @access public\r
655      * @internal Implemented per a suggestion by Techie-Michael - thanks!\r
656      */\r
657     function __toString()\r
658     {\r
659         return $this->toString();\r
660     }\r
661 \r
662     /**\r
663      * __clone() magic method\r
664      *\r
665      * Although you can call Math_BigInteger::__toString() directly in PHP5, you cannot call Math_BigInteger::__clone()\r
666      * 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\r
667      * only syntax of $y = clone $x.  As such, if you're trying to write an application that works on both PHP4 and PHP5,\r
668      * call Math_BigInteger::copy(), instead.\r
669      *\r
670      * @access public\r
671      * @see copy()\r
672      * @return Math_BigInteger\r
673      */\r
674     function __clone()\r
675     {\r
676         return $this->copy();\r
677     }\r
678 \r
679     /**\r
680      * Adds two BigIntegers.\r
681      *\r
682      * Here's an example:\r
683      * <code>\r
684      * <?php\r
685      *    include('Math/BigInteger.php');\r
686      *\r
687      *    $a = new Math_BigInteger('10');\r
688      *    $b = new Math_BigInteger('20');\r
689      *\r
690      *    $c = $a->add($b);\r
691      *\r
692      *    echo $c->toString(); // outputs 30\r
693      * ?>\r
694      * </code>\r
695      *\r
696      * @param Math_BigInteger $y\r
697      * @return Math_BigInteger\r
698      * @access public\r
699      * @internal Performs base-2**52 addition\r
700      */\r
701     function add($y)\r
702     {\r
703         switch ( MATH_BIGINTEGER_MODE ) {\r
704             case MATH_BIGINTEGER_MODE_GMP:\r
705                 $temp = new Math_BigInteger();\r
706                 $temp->value = gmp_add($this->value, $y->value);\r
707 \r
708                 return $this->_normalize($temp);\r
709             case MATH_BIGINTEGER_MODE_BCMATH:\r
710                 $temp = new Math_BigInteger();\r
711                 $temp->value = bcadd($this->value, $y->value);\r
712 \r
713                 return $this->_normalize($temp);\r
714         }\r
715 \r
716         $this_size = count($this->value);\r
717         $y_size = count($y->value);\r
718 \r
719         if ($this_size == 0) {\r
720             return $y->copy();\r
721         } else if ($y_size == 0) {\r
722             return $this->copy();\r
723         }\r
724 \r
725         // subtract, if appropriate\r
726         if ( $this->is_negative != $y->is_negative ) {\r
727             // is $y the negative number?\r
728             $y_negative = $this->compare($y) > 0;\r
729 \r
730             $temp = $this->copy();\r
731             $y = $y->copy();\r
732             $temp->is_negative = $y->is_negative = false;\r
733 \r
734             $diff = $temp->compare($y);\r
735             if ( !$diff ) {\r
736                 $temp = new Math_BigInteger();\r
737                 return $this->_normalize($temp);\r
738             }\r
739 \r
740             $temp = $temp->subtract($y);\r
741 \r
742             $temp->is_negative = ($diff > 0) ? !$y_negative : $y_negative;\r
743 \r
744             return $this->_normalize($temp);\r
745         }\r
746 \r
747         $result = new Math_BigInteger();\r
748         $carry = 0;\r
749 \r
750         $size = max($this_size, $y_size);\r
751         $size+= $size & 1; // rounds $size to the nearest 2.\r
752 \r
753         $x = array_pad($this->value, $size, 0);\r
754         $y = array_pad($y->value, $size, 0);\r
755 \r
756         for ($i = 0; $i < $size - 1; $i+=2) {\r
757             $sum = $x[$i + 1] * 0x4000000 + $x[$i] + $y[$i + 1] * 0x4000000 + $y[$i] + $carry;\r
758             $carry = $sum >= MATH_BIGINTEGER_MAX_DIGIT52; // eg. floor($sum / 2**52); only possible values (in any base) are 0 and 1\r
759             $sum = $carry ? $sum - MATH_BIGINTEGER_MAX_DIGIT52 : $sum;\r
760 \r
761             $temp = floor($sum / 0x4000000);\r
762 \r
763             $result->value[] = $sum - 0x4000000 * $temp; // eg. a faster alternative to fmod($sum, 0x4000000)\r
764             $result->value[] = $temp;\r
765         }\r
766 \r
767         if ($carry) {\r
768             $result->value[] = (int) $carry;\r
769         }\r
770 \r
771         $result->is_negative = $this->is_negative;\r
772 \r
773         return $this->_normalize($result);\r
774     }\r
775 \r
776     /**\r
777      * Subtracts two BigIntegers.\r
778      *\r
779      * Here's an example:\r
780      * <code>\r
781      * <?php\r
782      *    include('Math/BigInteger.php');\r
783      *\r
784      *    $a = new Math_BigInteger('10');\r
785      *    $b = new Math_BigInteger('20');\r
786      *\r
787      *    $c = $a->subtract($b);\r
788      *\r
789      *    echo $c->toString(); // outputs -10\r
790      * ?>\r
791      * </code>\r
792      *\r
793      * @param Math_BigInteger $y\r
794      * @return Math_BigInteger\r
795      * @access public\r
796      * @internal Performs base-2**52 subtraction\r
797      */\r
798     function subtract($y)\r
799     {\r
800         switch ( MATH_BIGINTEGER_MODE ) {\r
801             case MATH_BIGINTEGER_MODE_GMP:\r
802                 $temp = new Math_BigInteger();\r
803                 $temp->value = gmp_sub($this->value, $y->value);\r
804 \r
805                 return $this->_normalize($temp);\r
806             case MATH_BIGINTEGER_MODE_BCMATH:\r
807                 $temp = new Math_BigInteger();\r
808                 $temp->value = bcsub($this->value, $y->value);\r
809 \r
810                 return $this->_normalize($temp);\r
811         }\r
812 \r
813         $this_size = count($this->value);\r
814         $y_size = count($y->value);\r
815 \r
816         if ($this_size == 0) {\r
817             $temp = $y->copy();\r
818             $temp->is_negative = !$temp->is_negative;\r
819             return $temp;\r
820         } else if ($y_size == 0) {\r
821             return $this->copy();\r
822         }\r
823 \r
824         // add, if appropriate (ie. -$x - +$y or +$x - -$y)\r
825         if ( $this->is_negative != $y->is_negative ) {\r
826             $is_negative = $y->compare($this) > 0;\r
827 \r
828             $temp = $this->copy();\r
829             $y = $y->copy();\r
830             $temp->is_negative = $y->is_negative = false;\r
831 \r
832             $temp = $temp->add($y);\r
833 \r
834             $temp->is_negative = $is_negative;\r
835 \r
836             return $this->_normalize($temp);\r
837         }\r
838 \r
839         $diff = $this->compare($y);\r
840 \r
841         if ( !$diff ) {\r
842             $temp = new Math_BigInteger();\r
843             return $this->_normalize($temp);\r
844         }\r
845 \r
846         // switch $this and $y around, if appropriate.\r
847         if ( (!$this->is_negative && $diff < 0) || ($this->is_negative && $diff > 0) ) {\r
848             $is_negative = $y->is_negative;\r
849 \r
850             $temp = $this->copy();\r
851             $y = $y->copy();\r
852             $temp->is_negative = $y->is_negative = false;\r
853 \r
854             $temp = $y->subtract($temp);\r
855             $temp->is_negative = !$is_negative;\r
856 \r
857             return $this->_normalize($temp);\r
858         }\r
859 \r
860         $result = new Math_BigInteger();\r
861         $carry = 0;\r
862 \r
863         $size = max($this_size, $y_size);\r
864         $size+= $size % 2;\r
865 \r
866         $x = array_pad($this->value, $size, 0);\r
867         $y = array_pad($y->value, $size, 0);\r
868 \r
869         for ($i = 0; $i < $size - 1; $i+=2) {\r
870             $sum = $x[$i + 1] * 0x4000000 + $x[$i] - $y[$i + 1] * 0x4000000 - $y[$i] + $carry;\r
871             $carry = $sum < 0 ? -1 : 0; // eg. floor($sum / 2**52); only possible values (in any base) are 0 and 1\r
872             $sum = $carry ? $sum + MATH_BIGINTEGER_MAX_DIGIT52 : $sum;\r
873 \r
874             $temp = floor($sum / 0x4000000);\r
875 \r
876             $result->value[] = $sum - 0x4000000 * $temp;\r
877             $result->value[] = $temp;\r
878         }\r
879 \r
880         // $carry shouldn't be anything other than zero, at this point, since we already made sure that $this\r
881         // was bigger than $y.\r
882 \r
883         $result->is_negative = $this->is_negative;\r
884 \r
885         return $this->_normalize($result);\r
886     }\r
887 \r
888     /**\r
889      * Multiplies two BigIntegers\r
890      *\r
891      * Here's an example:\r
892      * <code>\r
893      * <?php\r
894      *    include('Math/BigInteger.php');\r
895      *\r
896      *    $a = new Math_BigInteger('10');\r
897      *    $b = new Math_BigInteger('20');\r
898      *\r
899      *    $c = $a->multiply($b);\r
900      *\r
901      *    echo $c->toString(); // outputs 200\r
902      * ?>\r
903      * </code>\r
904      *\r
905      * @param Math_BigInteger $x\r
906      * @return Math_BigInteger\r
907      * @access public\r
908      */\r
909     function multiply($x)\r
910     {\r
911         switch ( MATH_BIGINTEGER_MODE ) {\r
912             case MATH_BIGINTEGER_MODE_GMP:\r
913                 $temp = new Math_BigInteger();\r
914                 $temp->value = gmp_mul($this->value, $x->value);\r
915 \r
916                 return $this->_normalize($temp);\r
917             case MATH_BIGINTEGER_MODE_BCMATH:\r
918                 $temp = new Math_BigInteger();\r
919                 $temp->value = bcmul($this->value, $x->value);\r
920 \r
921                 return $this->_normalize($temp);\r
922         }\r
923 \r
924         static $cutoff = false;\r
925         if ($cutoff === false) {\r
926             $cutoff = 2 * MATH_BIGINTEGER_KARATSUBA_CUTOFF;\r
927         }\r
928 \r
929         if ( $this->equals($x) ) {\r
930             return $this->_square();\r
931         }\r
932 \r
933         $this_length = count($this->value);\r
934         $x_length = count($x->value);\r
935 \r
936         if ( !$this_length || !$x_length ) { // a 0 is being multiplied\r
937             $temp = new Math_BigInteger();\r
938             return $this->_normalize($temp);\r
939         }\r
940 \r
941         $product = min($this_length, $x_length) < $cutoff ? $this->_multiply($x) : $this->_karatsuba($x);\r
942 \r
943         $product->is_negative = $this->is_negative != $x->is_negative;\r
944 \r
945         return $this->_normalize($product);\r
946     }\r
947 \r
948     /**\r
949      * Performs long multiplication up to $stop digits\r
950      *\r
951      * If you're going to be doing array_slice($product->value, 0, $stop), some cycles can be saved.\r
952      *\r
953      * @see _barrett()\r
954      * @param Math_BigInteger $x\r
955      * @return Math_BigInteger\r
956      * @access private\r
957      */\r
958     function _multiplyLower($x, $stop)\r
959     {\r
960         $this_length = count($this->value);\r
961         $x_length = count($x->value);\r
962 \r
963         if ( !$this_length || !$x_length ) { // a 0 is being multiplied\r
964             return new Math_BigInteger();\r
965         }\r
966 \r
967         if ( $this_length < $x_length ) {\r
968             return $x->_multiplyLower($this, $stop);\r
969         }\r
970 \r
971         $product = new Math_BigInteger();\r
972         $product->value = $this->_array_repeat(0, $this_length + $x_length);\r
973 \r
974         // the following for loop could be removed if the for loop following it\r
975         // (the one with nested for loops) initially set $i to 0, but\r
976         // doing so would also make the result in one set of unnecessary adds,\r
977         // since on the outermost loops first pass, $product->value[$k] is going\r
978         // to always be 0\r
979 \r
980         $carry = 0;\r
981 \r
982         for ($j = 0; $j < $this_length; $j++) { // ie. $i = 0, $k = $i\r
983             $temp = $this->value[$j] * $x->value[0] + $carry; // $product->value[$k] == 0\r
984             $carry = floor($temp / 0x4000000);\r
985             $product->value[$j] = $temp - 0x4000000 * $carry;\r
986         }\r
987 \r
988         if ($j < $stop) {\r
989             $product->value[$j] = $carry;\r
990         }\r
991 \r
992         // the above for loop is what the previous comment was talking about.  the\r
993         // following for loop is the "one with nested for loops"\r
994 \r
995         for ($i = 1; $i < $x_length; $i++) {\r
996             $carry = 0;\r
997 \r
998             for ($j = 0, $k = $i; $j < $this_length && $k < $stop; $j++, $k++) {\r
999                 $temp = $product->value[$k] + $this->value[$j] * $x->value[$i] + $carry;\r
1000                 $carry = floor($temp / 0x4000000);\r
1001                 $product->value[$k] = $temp - 0x4000000 * $carry;\r
1002             }\r
1003 \r
1004             if ($k < $stop) {\r
1005                 $product->value[$k] = $carry;\r
1006             }\r
1007         }\r
1008 \r
1009         $product->is_negative = $this->is_negative != $x->is_negative;\r
1010 \r
1011         return $product;\r
1012     }\r
1013 \r
1014     /**\r
1015      * Performs long multiplication on two BigIntegers\r
1016      *\r
1017      * Modeled after 'multiply' in MutableBigInteger.java.\r
1018      *\r
1019      * @param Math_BigInteger $x\r
1020      * @return Math_BigInteger\r
1021      * @access private\r
1022      */\r
1023     function _multiply($x)\r
1024     {\r
1025         $this_length = count($this->value);\r
1026         $x_length = count($x->value);\r
1027 \r
1028         if ( !$this_length || !$x_length ) { // a 0 is being multiplied\r
1029             return new Math_BigInteger();\r
1030         }\r
1031 \r
1032         if ( $this_length < $x_length ) {\r
1033             return $x->_multiply($this);\r
1034         }\r
1035 \r
1036         $product = new Math_BigInteger();\r
1037         $product->value = $this->_array_repeat(0, $this_length + $x_length);\r
1038 \r
1039         // the following for loop could be removed if the for loop following it\r
1040         // (the one with nested for loops) initially set $i to 0, but\r
1041         // doing so would also make the result in one set of unnecessary adds,\r
1042         // since on the outermost loops first pass, $product->value[$k] is going\r
1043         // to always be 0\r
1044 \r
1045         $carry = 0;\r
1046 \r
1047         for ($j = 0; $j < $this_length; $j++) { // ie. $i = 0\r
1048             $temp = $this->value[$j] * $x->value[0] + $carry; // $product->value[$k] == 0\r
1049             $carry = floor($temp / 0x4000000);\r
1050             $product->value[$j] = $temp - 0x4000000 * $carry;\r
1051         }\r
1052 \r
1053         $product->value[$j] = $carry;\r
1054 \r
1055         // the above for loop is what the previous comment was talking about.  the\r
1056         // following for loop is the "one with nested for loops"\r
1057         for ($i = 1; $i < $x_length; $i++) {\r
1058             $carry = 0;\r
1059 \r
1060             for ($j = 0, $k = $i; $j < $this_length; $j++, $k++) {\r
1061                 $temp = $product->value[$k] + $this->value[$j] * $x->value[$i] + $carry;\r
1062                 $carry = floor($temp / 0x4000000);\r
1063                 $product->value[$k] = $temp - 0x4000000 * $carry;\r
1064             }\r
1065 \r
1066             $product->value[$k] = $carry;\r
1067         }\r
1068 \r
1069         $product->is_negative = $this->is_negative != $x->is_negative;\r
1070 \r
1071         return $this->_normalize($product);\r
1072     }\r
1073 \r
1074     /**\r
1075      * Performs Karatsuba multiplication on two BigIntegers\r
1076      *\r
1077      * See {@link http://en.wikipedia.org/wiki/Karatsuba_algorithm Karatsuba algorithm} and\r
1078      * {@link http://math.libtomcrypt.com/files/tommath.pdf#page=120 MPM 5.2.3}.\r
1079      *\r
1080      * @param Math_BigInteger $y\r
1081      * @return Math_BigInteger\r
1082      * @access private\r
1083      */\r
1084     function _karatsuba($y)\r
1085     {\r
1086         $x = $this->copy();\r
1087 \r
1088         $m = min(count($x->value) >> 1, count($y->value) >> 1);\r
1089 \r
1090         if ($m < MATH_BIGINTEGER_KARATSUBA_CUTOFF) {\r
1091             return $x->_multiply($y);\r
1092         }\r
1093 \r
1094         $x1 = new Math_BigInteger();\r
1095         $x0 = new Math_BigInteger();\r
1096         $y1 = new Math_BigInteger();\r
1097         $y0 = new Math_BigInteger();\r
1098 \r
1099         $x1->value = array_slice($x->value, $m);\r
1100         $x0->value = array_slice($x->value, 0, $m);\r
1101         $y1->value = array_slice($y->value, $m);\r
1102         $y0->value = array_slice($y->value, 0, $m);\r
1103 \r
1104         $z2 = $x1->_karatsuba($y1);\r
1105         $z0 = $x0->_karatsuba($y0);\r
1106 \r
1107         $z1 = $x1->add($x0);\r
1108         $z1 = $z1->_karatsuba($y1->add($y0));\r
1109         $z1 = $z1->subtract($z2->add($z0));\r
1110 \r
1111         $z2->value = array_merge(array_fill(0, 2 * $m, 0), $z2->value);\r
1112         $z1->value = array_merge(array_fill(0,     $m, 0), $z1->value);\r
1113 \r
1114         $xy = $z2->add($z1);\r
1115         $xy = $xy->add($z0);\r
1116 \r
1117         return $xy;\r
1118     }\r
1119 \r
1120     /**\r
1121      * Squares a BigInteger\r
1122      *\r
1123      * @return Math_BigInteger\r
1124      * @access private\r
1125      */\r
1126     function _square()\r
1127     {\r
1128         static $cutoff = false;\r
1129         if ($cutoff === false) {\r
1130             $cutoff = 2 * MATH_BIGINTEGER_KARATSUBA_CUTOFF;\r
1131         }\r
1132 \r
1133         return count($this->value) < $cutoff ? $this->_baseSquare() : $this->_karatsubaSquare();\r
1134     }\r
1135 \r
1136     /**\r
1137      * Performs traditional squaring on two BigIntegers\r
1138      *\r
1139      * Squaring can be done faster than multiplying a number by itself can be.  See\r
1140      * {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=7 HAC 14.2.4} /\r
1141      * {@link http://math.libtomcrypt.com/files/tommath.pdf#page=141 MPM 5.3} for more information.\r
1142      *\r
1143      * @return Math_BigInteger\r
1144      * @access private\r
1145      */\r
1146     function _baseSquare()\r
1147     {\r
1148         if ( empty($this->value) ) {\r
1149             return new Math_BigInteger();\r
1150         }\r
1151 \r
1152         $square = new Math_BigInteger();\r
1153         $square->value = $this->_array_repeat(0, 2 * count($this->value));\r
1154 \r
1155         for ($i = 0, $max_index = count($this->value) - 1; $i <= $max_index; $i++) {\r
1156             $i2 = 2 * $i;\r
1157 \r
1158             $temp = $square->value[$i2] + $this->value[$i] * $this->value[$i];\r
1159             $carry = floor($temp / 0x4000000);\r
1160             $square->value[$i2] = $temp - 0x4000000 * $carry;\r
1161 \r
1162             // note how we start from $i+1 instead of 0 as we do in multiplication.\r
1163             for ($j = $i + 1, $k = $i2 + 1; $j <= $max_index; $j++, $k++) {\r
1164                 $temp = $square->value[$k] + 2 * $this->value[$j] * $this->value[$i] + $carry;\r
1165                 $carry = floor($temp / 0x4000000);\r
1166                 $square->value[$k] = $temp - 0x4000000 * $carry;\r
1167             }\r
1168 \r
1169             // the following line can yield values larger 2**15.  at this point, PHP should switch\r
1170             // over to floats.\r
1171             $square->value[$i + $max_index + 1] = $carry;\r
1172         }\r
1173 \r
1174         return $square;\r
1175     }\r
1176 \r
1177     /**\r
1178      * Performs Karatsuba "squaring" on two BigIntegers\r
1179      *\r
1180      * See {@link http://en.wikipedia.org/wiki/Karatsuba_algorithm Karatsuba algorithm} and\r
1181      * {@link http://math.libtomcrypt.com/files/tommath.pdf#page=151 MPM 5.3.4}.\r
1182      *\r
1183      * @param Math_BigInteger $y\r
1184      * @return Math_BigInteger\r
1185      * @access private\r
1186      */\r
1187     function _karatsubaSquare()\r
1188     {\r
1189         $m = count($this->value) >> 1;\r
1190 \r
1191         if ($m < MATH_BIGINTEGER_KARATSUBA_CUTOFF) {\r
1192             return $this->_square();\r
1193         }\r
1194 \r
1195         $x1 = new Math_BigInteger();\r
1196         $x0 = new Math_BigInteger();\r
1197 \r
1198         $x1->value = array_slice($this->value, $m);\r
1199         $x0->value = array_slice($this->value, 0, $m);\r
1200 \r
1201         $z2 = $x1->_karatsubaSquare();\r
1202         $z0 = $x0->_karatsubaSquare();\r
1203 \r
1204         $z1 = $x1->add($x0);\r
1205         $z1 = $z1->_karatsubaSquare();\r
1206         $z1 = $z1->subtract($z2->add($z0));\r
1207 \r
1208         $z2->value = array_merge(array_fill(0, 2 * $m, 0), $z2->value);\r
1209         $z1->value = array_merge(array_fill(0,     $m, 0), $z1->value);\r
1210 \r
1211         $xx = $z2->add($z1);\r
1212         $xx = $xx->add($z0);\r
1213 \r
1214         return $xx;\r
1215     }\r
1216 \r
1217     /**\r
1218      * Divides two BigIntegers.\r
1219      *\r
1220      * Returns an array whose first element contains the quotient and whose second element contains the\r
1221      * "common residue".  If the remainder would be positive, the "common residue" and the remainder are the\r
1222      * same.  If the remainder would be negative, the "common residue" is equal to the sum of the remainder\r
1223      * and the divisor (basically, the "common residue" is the first positive modulo).\r
1224      *\r
1225      * Here's an example:\r
1226      * <code>\r
1227      * <?php\r
1228      *    include('Math/BigInteger.php');\r
1229      *\r
1230      *    $a = new Math_BigInteger('10');\r
1231      *    $b = new Math_BigInteger('20');\r
1232      *\r
1233      *    list($quotient, $remainder) = $a->divide($b);\r
1234      *\r
1235      *    echo $quotient->toString(); // outputs 0\r
1236      *    echo "\r\n";\r
1237      *    echo $remainder->toString(); // outputs 10\r
1238      * ?>\r
1239      * </code>\r
1240      *\r
1241      * @param Math_BigInteger $y\r
1242      * @return Array\r
1243      * @access public\r
1244      * @internal This function is based off of {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=9 HAC 14.20}.\r
1245      */\r
1246     function divide($y)\r
1247     {\r
1248         switch ( MATH_BIGINTEGER_MODE ) {\r
1249             case MATH_BIGINTEGER_MODE_GMP:\r
1250                 $quotient = new Math_BigInteger();\r
1251                 $remainder = new Math_BigInteger();\r
1252 \r
1253                 list($quotient->value, $remainder->value) = gmp_div_qr($this->value, $y->value);\r
1254 \r
1255                 if (gmp_sign($remainder->value) < 0) {\r
1256                     $remainder->value = gmp_add($remainder->value, gmp_abs($y->value));\r
1257                 }\r
1258 \r
1259                 return array($this->_normalize($quotient), $this->_normalize($remainder));\r
1260             case MATH_BIGINTEGER_MODE_BCMATH:\r
1261                 $quotient = new Math_BigInteger();\r
1262                 $remainder = new Math_BigInteger();\r
1263 \r
1264                 $quotient->value = bcdiv($this->value, $y->value);\r
1265                 $remainder->value = bcmod($this->value, $y->value);\r
1266 \r
1267                 if ($remainder->value[0] == '-') {\r
1268                     $remainder->value = bcadd($remainder->value, $y->value[0] == '-' ? substr($y->value, 1) : $y->value);\r
1269                 }\r
1270 \r
1271                 return array($this->_normalize($quotient), $this->_normalize($remainder));\r
1272         }\r
1273 \r
1274         if (count($y->value) == 1) {\r
1275             $temp = $this->_divide_digit($y->value[0]);\r
1276             $temp[0]->is_negative = $this->is_negative != $y->is_negative;\r
1277             return array($this->_normalize($temp[0]), $this->_normalize($temp[1]));\r
1278         }\r
1279 \r
1280         static $zero;\r
1281         if (!isset($zero)) {\r
1282             $zero = new Math_BigInteger();\r
1283         }\r
1284 \r
1285         $x = $this->copy();\r
1286         $y = $y->copy();\r
1287 \r
1288         $x_sign = $x->is_negative;\r
1289         $y_sign = $y->is_negative;\r
1290 \r
1291         $x->is_negative = $y->is_negative = false;\r
1292 \r
1293         $diff = $x->compare($y);\r
1294 \r
1295         if ( !$diff ) {\r
1296             $temp = new Math_BigInteger();\r
1297             $temp->value = array(1);\r
1298             $temp->is_negative = $x_sign != $y_sign;\r
1299             return array($this->_normalize($temp), $this->_normalize(new Math_BigInteger()));\r
1300         }\r
1301 \r
1302         if ( $diff < 0 ) {\r
1303             // if $x is negative, "add" $y.\r
1304             if ( $x_sign ) {\r
1305                 $x = $y->subtract($x);\r
1306             }\r
1307             return array($this->_normalize(new Math_BigInteger()), $this->_normalize($x));\r
1308         }\r
1309 \r
1310         // normalize $x and $y as described in HAC 14.23 / 14.24\r
1311         $msb = $y->value[count($y->value) - 1];\r
1312         for ($shift = 0; !($msb & 0x2000000); $shift++) {\r
1313             $msb <<= 1;\r
1314         }\r
1315         $x->_lshift($shift);\r
1316         $y->_lshift($shift);\r
1317 \r
1318         $x_max = count($x->value) - 1;\r
1319         $y_max = count($y->value) - 1;\r
1320 \r
1321         $quotient = new Math_BigInteger();\r
1322         $quotient->value = $this->_array_repeat(0, $x_max - $y_max + 1);\r
1323 \r
1324         // $temp = $y << ($x_max - $y_max-1) in base 2**26\r
1325         $temp = new Math_BigInteger();\r
1326         $temp->value = array_merge($this->_array_repeat(0, $x_max - $y_max), $y->value);\r
1327 \r
1328         while ( $x->compare($temp) >= 0 ) {\r
1329             // calculate the "common residue"\r
1330             $quotient->value[$x_max - $y_max]++;\r
1331             $x = $x->subtract($temp);\r
1332             $x_max = count($x->value) - 1;\r
1333         }\r
1334 \r
1335         for ($i = $x_max; $i >= $y_max + 1; $i--) {\r
1336             $x_value = array(\r
1337                 $x->value[$i],\r
1338                 ( $i > 0 ) ? $x->value[$i - 1] : 0,\r
1339                 ( $i > 1 ) ? $x->value[$i - 2] : 0\r
1340             );\r
1341             $y_value = array(\r
1342                 $y->value[$y_max],\r
1343                 ( $y_max > 0 ) ? $y->value[$y_max - 1] : 0\r
1344             );\r
1345 \r
1346             $q_index = $i - $y_max - 1;\r
1347             if ($x_value[0] == $y_value[0]) {\r
1348                 $quotient->value[$q_index] = 0x3FFFFFF;\r
1349             } else {\r
1350                 $quotient->value[$q_index] = floor(\r
1351                     ($x_value[0] * 0x4000000 + $x_value[1])\r
1352                     /\r
1353                     $y_value[0]\r
1354                 );\r
1355             }\r
1356 \r
1357             $temp = new Math_BigInteger();\r
1358             $temp->value = array($y_value[1], $y_value[0]);\r
1359 \r
1360             $lhs = new Math_BigInteger();\r
1361             $lhs->value = array($quotient->value[$q_index]);\r
1362             $lhs = $lhs->multiply($temp);\r
1363 \r
1364             $rhs = new Math_BigInteger();\r
1365             $rhs->value = array($x_value[2], $x_value[1], $x_value[0]);\r
1366 \r
1367             while ( $lhs->compare($rhs) > 0 ) {\r
1368                 $quotient->value[$q_index]--;\r
1369 \r
1370                 $lhs = new Math_BigInteger();\r
1371                 $lhs->value = array($quotient->value[$q_index]);\r
1372                 $lhs = $lhs->multiply($temp);\r
1373             }\r
1374 \r
1375             $adjust = $this->_array_repeat(0, $q_index);\r
1376             $temp = new Math_BigInteger();\r
1377             $temp->value = array($quotient->value[$q_index]);\r
1378             $temp = $temp->multiply($y);\r
1379             $temp->value = array_merge($adjust, $temp->value);\r
1380 \r
1381             $x = $x->subtract($temp);\r
1382 \r
1383             if ($x->compare($zero) < 0) {\r
1384                 $temp->value = array_merge($adjust, $y->value);\r
1385                 $x = $x->add($temp);\r
1386 \r
1387                 $quotient->value[$q_index]--;\r
1388             }\r
1389 \r
1390             $x_max = count($x->value) - 1;\r
1391         }\r
1392 \r
1393         // unnormalize the remainder\r
1394         $x->_rshift($shift);\r
1395 \r
1396         $quotient->is_negative = $x_sign != $y_sign;\r
1397 \r
1398         // calculate the "common residue", if appropriate\r
1399         if ( $x_sign ) {\r
1400             $y->_rshift($shift);\r
1401             $x = $y->subtract($x);\r
1402         }\r
1403 \r
1404         return array($this->_normalize($quotient), $this->_normalize($x));\r
1405     }\r
1406 \r
1407     /**\r
1408      * Divides a BigInteger by a regular integer\r
1409      *\r
1410      * abc / x = a00 / x + b0 / x + c / x\r
1411      *\r
1412      * @param Math_BigInteger $divisor\r
1413      * @return Array\r
1414      * @access public\r
1415      */\r
1416     function _divide_digit($divisor)\r
1417     {\r
1418         $carry = 0;\r
1419         $result = new Math_BigInteger();\r
1420 \r
1421         for ($i = count($this->value) - 1; $i >= 0; $i--) {\r
1422             $temp = 0x4000000 * $carry + $this->value[$i];\r
1423             $result->value[$i] = floor($temp / $divisor);\r
1424             $carry = fmod($temp, $divisor);\r
1425         }\r
1426 \r
1427         $remainder = new Math_BigInteger();\r
1428         $remainder->value = array($carry);\r
1429 \r
1430         return array($result, $remainder);\r
1431     }\r
1432 \r
1433     /**\r
1434      * Performs modular exponentiation.\r
1435      *\r
1436      * Here's an example:\r
1437      * <code>\r
1438      * <?php\r
1439      *    include('Math/BigInteger.php');\r
1440      *\r
1441      *    $a = new Math_BigInteger('10');\r
1442      *    $b = new Math_BigInteger('20');\r
1443      *    $c = new Math_BigInteger('30');\r
1444      *\r
1445      *    $c = $a->modPow($b, $c);\r
1446      *\r
1447      *    echo $c->toString(); // outputs 10\r
1448      * ?>\r
1449      * </code>\r
1450      *\r
1451      * @param Math_BigInteger $e\r
1452      * @param Math_BigInteger $n\r
1453      * @return Math_BigInteger\r
1454      * @access public\r
1455      * @internal The most naive approach to modular exponentiation has very unreasonable requirements, and\r
1456      *    and although the approach involving repeated squaring does vastly better, it, too, is impractical\r
1457      *    for our purposes.  The reason being that division - by far the most complicated and time-consuming\r
1458      *    of the basic operations (eg. +,-,*,/) - occurs multiple times within it.\r
1459      *\r
1460      *    Modular reductions resolve this issue.  Although an individual modular reduction takes more time\r
1461      *    then an individual division, when performed in succession (with the same modulo), they're a lot faster.\r
1462      *\r
1463      *    The two most commonly used modular reductions are Barrett and Montgomery reduction.  Montgomery reduction,\r
1464      *    although faster, only works when the gcd of the modulo and of the base being used is 1.  In RSA, when the\r
1465      *    base is a power of two, the modulo - a product of two primes - is always going to have a gcd of 1 (because\r
1466      *    the product of two odd numbers is odd), but what about when RSA isn't used?\r
1467      *\r
1468      *    In contrast, Barrett reduction has no such constraint.  As such, some bigint implementations perform a\r
1469      *    Barrett reduction after every operation in the modpow function.  Others perform Barrett reductions when the\r
1470      *    modulo is even and Montgomery reductions when the modulo is odd.  BigInteger.java's modPow method, however,\r
1471      *    uses a trick involving the Chinese Remainder Theorem to factor the even modulo into two numbers - one odd and\r
1472      *    the other, a power of two - and recombine them, later.  This is the method that this modPow function uses.\r
1473      *    {@link http://islab.oregonstate.edu/papers/j34monex.pdf Montgomery Reduction with Even Modulus} elaborates.\r
1474      */\r
1475     function modPow($e, $n)\r
1476     {\r
1477         $n = $this->bitmask !== false && $this->bitmask->compare($n) < 0 ? $this->bitmask : $n->abs();\r
1478 \r
1479         if ($e->compare(new Math_BigInteger()) < 0) {\r
1480             $e = $e->abs();\r
1481 \r
1482             $temp = $this->modInverse($n);\r
1483             if ($temp === false) {\r
1484                 return false;\r
1485             }\r
1486 \r
1487             return $this->_normalize($temp->modPow($e, $n));\r
1488         }\r
1489 \r
1490         switch ( MATH_BIGINTEGER_MODE ) {\r
1491             case MATH_BIGINTEGER_MODE_GMP:\r
1492                 $temp = new Math_BigInteger();\r
1493                 $temp->value = gmp_powm($this->value, $e->value, $n->value);\r
1494 \r
1495                 return $this->_normalize($temp);\r
1496             case MATH_BIGINTEGER_MODE_BCMATH:\r
1497                 $temp = new Math_BigInteger();\r
1498                 $temp->value = bcpowmod($this->value, $e->value, $n->value);\r
1499 \r
1500                 return $this->_normalize($temp);\r
1501         }\r
1502 \r
1503         if ( empty($e->value) ) {\r
1504             $temp = new Math_BigInteger();\r
1505             $temp->value = array(1);\r
1506             return $this->_normalize($temp);\r
1507         }\r
1508 \r
1509         if ( $e->value == array(1) ) {\r
1510             list(, $temp) = $this->divide($n);\r
1511             return $this->_normalize($temp);\r
1512         }\r
1513 \r
1514         if ( $e->value == array(2) ) {\r
1515             $temp = $this->_square();\r
1516             list(, $temp) = $temp->divide($n);\r
1517             return $this->_normalize($temp);\r
1518         }\r
1519 \r
1520         return $this->_normalize($this->_slidingWindow($e, $n, MATH_BIGINTEGER_BARRETT));\r
1521 \r
1522         // is the modulo odd?\r
1523         if ( $n->value[0] & 1 ) {\r
1524             return $this->_normalize($this->_slidingWindow($e, $n, MATH_BIGINTEGER_MONTGOMERY));\r
1525         }\r
1526         // if it's not, it's even\r
1527 \r
1528         // find the lowest set bit (eg. the max pow of 2 that divides $n)\r
1529         for ($i = 0; $i < count($n->value); $i++) {\r
1530             if ( $n->value[$i] ) {\r
1531                 $temp = decbin($n->value[$i]);\r
1532                 $j = strlen($temp) - strrpos($temp, '1') - 1;\r
1533                 $j+= 26 * $i;\r
1534                 break;\r
1535             }\r
1536         }\r
1537         // at this point, 2^$j * $n/(2^$j) == $n\r
1538 \r
1539         $mod1 = $n->copy();\r
1540         $mod1->_rshift($j);\r
1541         $mod2 = new Math_BigInteger();\r
1542         $mod2->value = array(1);\r
1543         $mod2->_lshift($j);\r
1544 \r
1545         $part1 = ( $mod1->value != array(1) ) ? $this->_slidingWindow($e, $mod1, MATH_BIGINTEGER_MONTGOMERY) : new Math_BigInteger();\r
1546         $part2 = $this->_slidingWindow($e, $mod2, MATH_BIGINTEGER_POWEROF2);\r
1547 \r
1548         $y1 = $mod2->modInverse($mod1);\r
1549         $y2 = $mod1->modInverse($mod2);\r
1550 \r
1551         $result = $part1->multiply($mod2);\r
1552         $result = $result->multiply($y1);\r
1553 \r
1554         $temp = $part2->multiply($mod1);\r
1555         $temp = $temp->multiply($y2);\r
1556 \r
1557         $result = $result->add($temp);\r
1558         list(, $result) = $result->divide($n);\r
1559 \r
1560         return $this->_normalize($result);\r
1561     }\r
1562 \r
1563     /**\r
1564      * Performs modular exponentiation.\r
1565      *\r
1566      * Alias for Math_BigInteger::modPow()\r
1567      *\r
1568      * @param Math_BigInteger $e\r
1569      * @param Math_BigInteger $n\r
1570      * @return Math_BigInteger\r
1571      * @access public\r
1572      */\r
1573     function powMod($e, $n)\r
1574     {\r
1575         return $this->modPow($e, $n);\r
1576     }\r
1577 \r
1578     /**\r
1579      * Sliding Window k-ary Modular Exponentiation\r
1580      *\r
1581      * Based on {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=27 HAC 14.85} /\r
1582      * {@link http://math.libtomcrypt.com/files/tommath.pdf#page=210 MPM 7.7}.  In a departure from those algorithims,\r
1583      * however, this function performs a modular reduction after every multiplication and squaring operation.\r
1584      * As such, this function has the same preconditions that the reductions being used do.\r
1585      *\r
1586      * @param Math_BigInteger $e\r
1587      * @param Math_BigInteger $n\r
1588      * @param Integer $mode\r
1589      * @return Math_BigInteger\r
1590      * @access private\r
1591      */\r
1592     function _slidingWindow($e, $n, $mode)\r
1593     {\r
1594         static $window_ranges = array(7, 25, 81, 241, 673, 1793); // from BigInteger.java's oddModPow function\r
1595         //static $window_ranges = array(0, 7, 36, 140, 450, 1303, 3529); // from MPM 7.3.1\r
1596 \r
1597         $e_length = count($e->value) - 1;\r
1598         $e_bits = decbin($e->value[$e_length]);\r
1599         for ($i = $e_length - 1; $i >= 0; $i--) {\r
1600             $e_bits.= str_pad(decbin($e->value[$i]), 26, '0', STR_PAD_LEFT);\r
1601         }\r
1602 \r
1603         $e_length = strlen($e_bits);\r
1604 \r
1605         // calculate the appropriate window size.\r
1606         // $window_size == 3 if $window_ranges is between 25 and 81, for example.\r
1607         for ($i = 0, $window_size = 1; $e_length > $window_ranges[$i] && $i < count($window_ranges); $window_size++, $i++);\r
1608         switch ($mode) {\r
1609             case MATH_BIGINTEGER_MONTGOMERY:\r
1610                 $reduce = '_montgomery';\r
1611                 $prep = '_prepMontgomery';\r
1612                 break;\r
1613             case MATH_BIGINTEGER_BARRETT:\r
1614                 $reduce = '_barrett';\r
1615                 $prep = '_barrett';\r
1616                 break;\r
1617             case MATH_BIGINTEGER_POWEROF2:\r
1618                 $reduce = '_mod2';\r
1619                 $prep = '_mod2';\r
1620                 break;\r
1621             case MATH_BIGINTEGER_CLASSIC:\r
1622                 $reduce = '_remainder';\r
1623                 $prep = '_remainder';\r
1624                 break;\r
1625             case MATH_BIGINTEGER_NONE:\r
1626                 // ie. do no modular reduction.  useful if you want to just do pow as opposed to modPow.\r
1627                 $reduce = 'copy';\r
1628                 $prep = 'copy';\r
1629                 break;\r
1630             default:\r
1631                 // an invalid $mode was provided\r
1632         }\r
1633 \r
1634         // precompute $this^0 through $this^$window_size\r
1635         $powers = array();\r
1636         $powers[1] = $this->$prep($n);\r
1637         $powers[2] = $powers[1]->_square();\r
1638         $powers[2] = $powers[2]->$reduce($n);\r
1639 \r
1640         // we do every other number since substr($e_bits, $i, $j+1) (see below) is supposed to end\r
1641         // in a 1.  ie. it's supposed to be odd.\r
1642         $temp = 1 << ($window_size - 1);\r
1643         for ($i = 1; $i < $temp; $i++) {\r
1644             $powers[2 * $i + 1] = $powers[2 * $i - 1]->multiply($powers[2]);\r
1645             $powers[2 * $i + 1] = $powers[2 * $i + 1]->$reduce($n);\r
1646         }\r
1647 \r
1648         $result = new Math_BigInteger();\r
1649         $result->value = array(1);\r
1650         $result = $result->$prep($n);\r
1651 \r
1652         for ($i = 0; $i < $e_length; ) {\r
1653             if ( !$e_bits[$i] ) {\r
1654                 $result = $result->_square();\r
1655                 $result = $result->$reduce($n);\r
1656                 $i++;\r
1657             } else {\r
1658                 for ($j = $window_size - 1; $j > 0; $j--) {\r
1659                     if ( !empty($e_bits[$i + $j]) ) {\r
1660                         break;\r
1661                     }\r
1662                 }\r
1663 \r
1664                 for ($k = 0; $k <= $j; $k++) {// eg. the length of substr($e_bits, $i, $j+1)\r
1665                     $result = $result->_square();\r
1666                     $result = $result->$reduce($n);\r
1667                 }\r
1668 \r
1669                 $result = $result->multiply($powers[bindec(substr($e_bits, $i, $j + 1))]);\r
1670                 $result = $result->$reduce($n);\r
1671 \r
1672                 $i+=$j + 1;\r
1673             }\r
1674         }\r
1675 \r
1676         $result = $result->$reduce($n);\r
1677 \r
1678         return $result;\r
1679     }\r
1680 \r
1681     /**\r
1682      * Remainder\r
1683      *\r
1684      * A wrapper for the divide function.\r
1685      *\r
1686      * @see divide()\r
1687      * @see _slidingWindow()\r
1688      * @access private\r
1689      * @param Math_BigInteger\r
1690      * @return Math_BigInteger\r
1691      */\r
1692     function _remainder($n)\r
1693     {\r
1694         list(, $temp) = $this->divide($n);\r
1695         return $temp;\r
1696     }\r
1697 \r
1698     /**\r
1699      * Modulos for Powers of Two\r
1700      *\r
1701      * Calculates $x%$n, where $n = 2**$e, for some $e.  Since this is basically the same as doing $x & ($n-1),\r
1702      * we'll just use this function as a wrapper for doing that.\r
1703      *\r
1704      * @see _slidingWindow()\r
1705      * @access private\r
1706      * @param Math_BigInteger\r
1707      * @return Math_BigInteger\r
1708      */\r
1709     function _mod2($n)\r
1710     {\r
1711         $temp = new Math_BigInteger();\r
1712         $temp->value = array(1);\r
1713         return $this->bitwise_and($n->subtract($temp));\r
1714     }\r
1715 \r
1716     /**\r
1717      * Barrett Modular Reduction\r
1718      *\r
1719      * See {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=14 HAC 14.3.3} /\r
1720      * {@link http://math.libtomcrypt.com/files/tommath.pdf#page=165 MPM 6.2.5} for more information.  Modified slightly,\r
1721      * so as not to require negative numbers (initially, this script didn't support negative numbers).\r
1722      *\r
1723      * @see _slidingWindow()\r
1724      * @access private\r
1725      * @param Math_BigInteger\r
1726      * @return Math_BigInteger\r
1727      */\r
1728     function _barrett($n)\r
1729     {\r
1730         static $cache = array(\r
1731             MATH_BIGINTEGER_VARIABLE => array(),\r
1732             MATH_BIGINTEGER_DATA => array()\r
1733         );\r
1734 \r
1735         $n_length = count($n->value);\r
1736 \r
1737         if (count($this->value) > 2 * $n_length) {\r
1738             list(, $temp) = $this->divide($n);\r
1739             return $temp;\r
1740         }\r
1741 \r
1742         if ( ($key = array_search($n->value, $cache[MATH_BIGINTEGER_VARIABLE])) === false ) {\r
1743             $key = count($cache[MATH_BIGINTEGER_VARIABLE]);\r
1744             $cache[MATH_BIGINTEGER_VARIABLE][] = $n->value;\r
1745             $temp = new Math_BigInteger();\r
1746             $temp->value = $this->_array_repeat(0, 2 * $n_length);\r
1747             $temp->value[] = 1;\r
1748             list($cache[MATH_BIGINTEGER_DATA][], ) = $temp->divide($n);\r
1749         }\r
1750 \r
1751         $temp = new Math_BigInteger();\r
1752         $temp->value = array_slice($this->value, $n_length - 1);\r
1753         $temp = $temp->multiply($cache[MATH_BIGINTEGER_DATA][$key]);\r
1754         $temp->value = array_slice($temp->value, $n_length + 1);\r
1755 \r
1756         $result = new Math_BigInteger();\r
1757         $result->value = array_slice($this->value, 0, $n_length + 1);\r
1758         $temp = $temp->_multiplyLower($n, $n_length + 1);\r
1759         // $temp->value == array_slice($temp->multiply($n)->value, 0, $n_length + 1)\r
1760 \r
1761         if ($result->compare($temp) < 0) {\r
1762             $corrector = new Math_BigInteger();\r
1763             $corrector->value = $this->_array_repeat(0, $n_length + 1);\r
1764             $corrector->value[] = 1;\r
1765             $result = $result->add($corrector);\r
1766         }\r
1767 \r
1768         $result = $result->subtract($temp);\r
1769         while ($result->compare($n) > 0) {\r
1770             $result = $result->subtract($n);\r
1771         }\r
1772 \r
1773         return $result;\r
1774     }\r
1775 \r
1776     /**\r
1777      * Montgomery Modular Reduction\r
1778      *\r
1779      * ($this->_prepMontgomery($n))->_montgomery($n) yields $x%$n.\r
1780      * {@link http://math.libtomcrypt.com/files/tommath.pdf#page=170 MPM 6.3} provides insights on how this can be\r
1781      * improved upon (basically, by using the comba method).  gcd($n, 2) must be equal to one for this function\r
1782      * to work correctly.\r
1783      *\r
1784      * @see _prepMontgomery()\r
1785      * @see _slidingWindow()\r
1786      * @access private\r
1787      * @param Math_BigInteger\r
1788      * @return Math_BigInteger\r
1789      */\r
1790     function _montgomery($n)\r
1791     {\r
1792         static $cache = array(\r
1793             MATH_BIGINTEGER_VARIABLE => array(),\r
1794             MATH_BIGINTEGER_DATA => array()\r
1795         );\r
1796 \r
1797         if ( ($key = array_search($n->value, $cache[MATH_BIGINTEGER_VARIABLE])) === false ) {\r
1798             $key = count($cache[MATH_BIGINTEGER_VARIABLE]);\r
1799             $cache[MATH_BIGINTEGER_VARIABLE][] = $n->value;\r
1800             $cache[MATH_BIGINTEGER_DATA][] = $n->_modInverse67108864();\r
1801         }\r
1802 \r
1803         $k = count($n->value);\r
1804 \r
1805         $result = $this->copy();\r
1806 \r
1807         for ($i = 0; $i < $k; $i++) {\r
1808             $temp = new Math_BigInteger();\r
1809             $temp->value = array(\r
1810                 ($result->value[$i] * $cache[MATH_BIGINTEGER_DATA][$key]) & 0x3FFFFFF\r
1811             );\r
1812 \r
1813             $temp = $temp->multiply($n);\r
1814             $temp->value = array_merge($this->_array_repeat(0, $i), $temp->value);\r
1815             $result = $result->add($temp);\r
1816         }\r
1817 \r
1818         $result->value = array_slice($result->value, $k);\r
1819 \r
1820         if ($result->compare($n) >= 0) {\r
1821             $result = $result->subtract($n);\r
1822         }\r
1823 \r
1824         return $result;\r
1825     }\r
1826 \r
1827     /**\r
1828      * Prepare a number for use in Montgomery Modular Reductions\r
1829      *\r
1830      * @see _montgomery()\r
1831      * @see _slidingWindow()\r
1832      * @access private\r
1833      * @param Math_BigInteger\r
1834      * @return Math_BigInteger\r
1835      */\r
1836     function _prepMontgomery($n)\r
1837     {\r
1838         $k = count($n->value);\r
1839 \r
1840         $temp = new Math_BigInteger();\r
1841         $temp->value = array_merge($this->_array_repeat(0, $k), $this->value);\r
1842 \r
1843         list(, $temp) = $temp->divide($n);\r
1844         return $temp;\r
1845     }\r
1846 \r
1847     /**\r
1848      * Modular Inverse of a number mod 2**26 (eg. 67108864)\r
1849      *\r
1850      * Based off of the bnpInvDigit function implemented and justified in the following URL:\r
1851      *\r
1852      * {@link http://www-cs-students.stanford.edu/~tjw/jsbn/jsbn.js}\r
1853      *\r
1854      * The following URL provides more info:\r
1855      *\r
1856      * {@link http://groups.google.com/group/sci.crypt/msg/7a137205c1be7d85}\r
1857      *\r
1858      * As for why we do all the bitmasking...  strange things can happen when converting from floats to ints. For\r
1859      * instance, on some computers, var_dump((int) -4294967297) yields int(-1) and on others, it yields \r
1860      * int(-2147483648).  To avoid problems stemming from this, we use bitmasks to guarantee that ints aren't\r
1861      * auto-converted to floats.  The outermost bitmask is present because without it, there's no guarantee that\r
1862      * the "residue" returned would be the so-called "common residue".  We use fmod, in the last step, because the\r
1863      * maximum possible $x is 26 bits and the maximum $result is 16 bits.  Thus, we have to be able to handle up to\r
1864      * 40 bits, which only 64-bit floating points will support.\r
1865      *\r
1866      * Thanks to Pedro Gimeno Fortea for input!\r
1867      *\r
1868      * @see _montgomery()\r
1869      * @access private\r
1870      * @return Integer\r
1871      */\r
1872     function _modInverse67108864() // 2**26 == 67108864\r
1873     {\r
1874         $x = -$this->value[0];\r
1875         $result = $x & 0x3; // x**-1 mod 2**2\r
1876         $result = ($result * (2 - $x * $result)) & 0xF; // x**-1 mod 2**4\r
1877         $result = ($result * (2 - ($x & 0xFF) * $result))  & 0xFF; // x**-1 mod 2**8\r
1878         $result = ($result * ((2 - ($x & 0xFFFF) * $result) & 0xFFFF)) & 0xFFFF; // x**-1 mod 2**16\r
1879         $result = fmod($result * (2 - fmod($x * $result, 0x4000000)), 0x4000000); // x**-1 mod 2**26\r
1880         return $result & 0x3FFFFFF;\r
1881     }\r
1882 \r
1883     /**\r
1884      * Calculates modular inverses.\r
1885      *\r
1886      * Say you have (30 mod 17 * x mod 17) mod 17 == 1.  x can be found using modular inverses.\r
1887      *\r
1888      * Here's an example:\r
1889      * <code>\r
1890      * <?php\r
1891      *    include('Math/BigInteger.php');\r
1892      *\r
1893      *    $a = new Math_BigInteger(30);\r
1894      *    $b = new Math_BigInteger(17);\r
1895      *\r
1896      *    $c = $a->modInverse($b);\r
1897      *    echo $c->toString(); // outputs 4\r
1898      *\r
1899      *    echo "\r\n";\r
1900      *\r
1901      *    $d = $a->multiply($c);\r
1902      *    list(, $d) = $d->divide($b);\r
1903      *    echo $d; // outputs 1 (as per the definition of modular inverse)\r
1904      * ?>\r
1905      * </code>\r
1906      *\r
1907      * @param Math_BigInteger $n\r
1908      * @return mixed false, if no modular inverse exists, Math_BigInteger, otherwise.\r
1909      * @access public\r
1910      * @internal See {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=21 HAC 14.64} for more information.\r
1911      */\r
1912     function modInverse($n)\r
1913     {\r
1914         switch ( MATH_BIGINTEGER_MODE ) {\r
1915             case MATH_BIGINTEGER_MODE_GMP:\r
1916                 $temp = new Math_BigInteger();\r
1917                 $temp->value = gmp_invert($this->value, $n->value);\r
1918 \r
1919                 return ( $temp->value === false ) ? false : $this->_normalize($temp);\r
1920         }\r
1921 \r
1922         static $zero, $one;\r
1923         if (!isset($zero)) {\r
1924             $zero = new Math_BigInteger();\r
1925             $one = new Math_BigInteger(1);\r
1926         }\r
1927 \r
1928         // $x mod $n == $x mod -$n.\r
1929         $n = $n->abs();\r
1930 \r
1931         if ($this->compare($zero) < 0) {\r
1932             $temp = $this->abs();\r
1933             $temp = $temp->modInverse($n);\r
1934             return $negated === false ? false : $this->_normalize($n->subtract($temp));\r
1935         }\r
1936 \r
1937         extract($this->extendedGCD($n));\r
1938 \r
1939         if (!$gcd->equals($one)) {\r
1940             return false;\r
1941         }\r
1942 \r
1943         $x = $x->compare($zero) < 0 ? $x->add($n) : $x;\r
1944 \r
1945         return $this->compare($zero) < 0 ? $this->_normalize($n->subtract($x)) : $this->_normalize($x);\r
1946     }\r
1947 \r
1948     /**\r
1949      * Calculates the greatest common divisor and Bézout's identity.\r
1950      *\r
1951      * Say you have 693 and 609.  The GCD is 21.  Bézout's identity states that there exist integers x and y such that\r
1952      * 693*x + 609*y == 21.  In point of fact, there are actually an infinite number of x and y combinations and which\r
1953      * combination is returned is dependant upon which mode is in use.  See\r
1954      * {@link http://en.wikipedia.org/wiki/B%C3%A9zout%27s_identity Bézout's identity - Wikipedia} for more information.\r
1955      *\r
1956      * Here's an example:\r
1957      * <code>\r
1958      * <?php\r
1959      *    include('Math/BigInteger.php');\r
1960      *\r
1961      *    $a = new Math_BigInteger(693);\r
1962      *    $b = new Math_BigInteger(609);\r
1963      *\r
1964      *    extract($a->extendedGCD($b));\r
1965      *\r
1966      *    echo $gcd->toString() . "\r\n"; // outputs 21\r
1967      *    echo $a->toString() * $x->toString() + $b->toString() * $y->toString(); // outputs 21\r
1968      * ?>\r
1969      * </code>\r
1970      *\r
1971      * @param Math_BigInteger $n\r
1972      * @return Math_BigInteger\r
1973      * @access public\r
1974      * @internal Calculates the GCD using the binary xGCD algorithim described in\r
1975      *    {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=19 HAC 14.61}.  As the text above 14.61 notes,\r
1976      *    the more traditional algorithim requires "relatively costly multiple-precision divisions".\r
1977      */\r
1978     function extendedGCD($n) {\r
1979         switch ( MATH_BIGINTEGER_MODE ) {\r
1980             case MATH_BIGINTEGER_MODE_GMP:\r
1981                 extract(gmp_gcdext($this->value, $n->value));\r
1982 \r
1983                 return array(\r
1984                     'gcd' => $this->_normalize(new Math_BigInteger($g)),\r
1985                     'x'   => $this->_normalize(new Math_BigInteger($s)),\r
1986                     'y'   => $this->_normalize(new Math_BigInteger($t))\r
1987                 );\r
1988             case MATH_BIGINTEGER_MODE_BCMATH:\r
1989                 // it might be faster to use the binary xGCD algorithim here, as well, but (1) that algorithim works\r
1990                 // best when the base is a power of 2 and (2) i don't think it'd make much difference, anyway.  as is,\r
1991                 // the basic extended euclidean algorithim is what we're using.\r
1992 \r
1993                 $u = $this->value;\r
1994                 $v = $n->value;\r
1995 \r
1996                 $a = '1';\r
1997                 $b = '0';\r
1998                 $c = '0';\r
1999                 $d = '1';\r
2000 \r
2001                 while (bccomp($v, '0') != 0) {\r
2002                     $q = bcdiv($u, $v);\r
2003 \r
2004                     $temp = $u;\r
2005                     $u = $v;\r
2006                     $v = bcsub($temp, bcmul($v, $q));\r
2007 \r
2008                     $temp = $a;\r
2009                     $a = $c;\r
2010                     $c = bcsub($temp, bcmul($a, $q));\r
2011 \r
2012                     $temp = $b;\r
2013                     $b = $d;\r
2014                     $d = bcsub($temp, bcmul($b, $q));\r
2015                 }\r
2016 \r
2017                 return array(\r
2018                     'gcd' => $this->_normalize(new Math_BigInteger($u)),\r
2019                     'x'   => $this->_normalize(new Math_BigInteger($a)),\r
2020                     'y'   => $this->_normalize(new Math_BigInteger($b))\r
2021                 );\r
2022         }\r
2023 \r
2024         $y = $n->copy();\r
2025         $x = $this->copy();\r
2026         $g = new Math_BigInteger();\r
2027         $g->value = array(1);\r
2028 \r
2029         while ( !(($x->value[0] & 1)|| ($y->value[0] & 1)) ) {\r
2030             $x->_rshift(1);\r
2031             $y->_rshift(1);\r
2032             $g->_lshift(1);\r
2033         }\r
2034 \r
2035         $u = $x->copy();\r
2036         $v = $y->copy();\r
2037 \r
2038         $a = new Math_BigInteger();\r
2039         $b = new Math_BigInteger();\r
2040         $c = new Math_BigInteger();\r
2041         $d = new Math_BigInteger();\r
2042 \r
2043         $a->value = $d->value = $g->value = array(1);\r
2044 \r
2045         while ( !empty($u->value) ) {\r
2046             while ( !($u->value[0] & 1) ) {\r
2047                 $u->_rshift(1);\r
2048                 if ( ($a->value[0] & 1) || ($b->value[0] & 1) ) {\r
2049                     $a = $a->add($y);\r
2050                     $b = $b->subtract($x);\r
2051                 }\r
2052                 $a->_rshift(1);\r
2053                 $b->_rshift(1);\r
2054             }\r
2055 \r
2056             while ( !($v->value[0] & 1) ) {\r
2057                 $v->_rshift(1);\r
2058                 if ( ($c->value[0] & 1) || ($d->value[0] & 1) ) {\r
2059                     $c = $c->add($y);\r
2060                     $d = $d->subtract($x);\r
2061                 }\r
2062                 $c->_rshift(1);\r
2063                 $d->_rshift(1);\r
2064             }\r
2065 \r
2066             if ($u->compare($v) >= 0) {\r
2067                 $u = $u->subtract($v);\r
2068                 $a = $a->subtract($c);\r
2069                 $b = $b->subtract($d);\r
2070             } else {\r
2071                 $v = $v->subtract($u);\r
2072                 $c = $c->subtract($a);\r
2073                 $d = $d->subtract($b);\r
2074             }\r
2075         }\r
2076 \r
2077         return array(\r
2078             'gcd' => $this->_normalize($g->multiply($v)),\r
2079             'x'   => $this->_normalize($c),\r
2080             'y'   => $this->_normalize($d)\r
2081         );\r
2082     }\r
2083 \r
2084     /**\r
2085      * Calculates the greatest common divisor\r
2086      *\r
2087      * Say you have 693 and 609.  The GCD is 21.\r
2088      *\r
2089      * Here's an example:\r
2090      * <code>\r
2091      * <?php\r
2092      *    include('Math/BigInteger.php');\r
2093      *\r
2094      *    $a = new Math_BigInteger(693);\r
2095      *    $b = new Math_BigInteger(609);\r
2096      *\r
2097      *    $gcd = a->extendedGCD($b);\r
2098      *\r
2099      *    echo $gcd->toString() . "\r\n"; // outputs 21\r
2100      * ?>\r
2101      * </code>\r
2102      *\r
2103      * @param Math_BigInteger $n\r
2104      * @return Math_BigInteger\r
2105      * @access public\r
2106      */\r
2107     function gcd($n)\r
2108     {\r
2109         extract($this->extendedGCD($n));\r
2110         return $gcd;\r
2111     }\r
2112 \r
2113     /**\r
2114      * Absolute value.\r
2115      *\r
2116      * @return Math_BigInteger\r
2117      * @access public\r
2118      */\r
2119     function abs()\r
2120     {\r
2121         $temp = new Math_BigInteger();\r
2122 \r
2123         switch ( MATH_BIGINTEGER_MODE ) {\r
2124             case MATH_BIGINTEGER_MODE_GMP:\r
2125                 $temp->value = gmp_abs($this->value);\r
2126                 break;\r
2127             case MATH_BIGINTEGER_MODE_BCMATH:\r
2128                 $temp->value = (bccomp($this->value, '0') < 0) ? substr($this->value, 1) : $this->value;\r
2129                 break;\r
2130             default:\r
2131                 $temp->value = $this->value;\r
2132         }\r
2133 \r
2134         return $temp;\r
2135     }\r
2136 \r
2137     /**\r
2138      * Compares two numbers.\r
2139      *\r
2140      * Although one might think !$x->compare($y) means $x != $y, it, in fact, means the opposite.  The reason for this is\r
2141      * demonstrated thusly:\r
2142      *\r
2143      * $x  > $y: $x->compare($y)  > 0\r
2144      * $x  < $y: $x->compare($y)  < 0\r
2145      * $x == $y: $x->compare($y) == 0\r
2146      *\r
2147      * Note how the same comparison operator is used.  If you want to test for equality, use $x->equals($y).\r
2148      *\r
2149      * @param Math_BigInteger $x\r
2150      * @return Integer < 0 if $this is less than $x; > 0 if $this is greater than $x, and 0 if they are equal.\r
2151      * @access public\r
2152      * @see equals()\r
2153      * @internal Could return $this->sub($x), but that's not as fast as what we do do.\r
2154      */\r
2155     function compare($y)\r
2156     {\r
2157         switch ( MATH_BIGINTEGER_MODE ) {\r
2158             case MATH_BIGINTEGER_MODE_GMP:\r
2159                 return gmp_cmp($this->value, $y->value);\r
2160             case MATH_BIGINTEGER_MODE_BCMATH:\r
2161                 return bccomp($this->value, $y->value);\r
2162         }\r
2163 \r
2164         $x = $this->_normalize($this->copy());\r
2165         $y = $this->_normalize($y);\r
2166 \r
2167         if ( $x->is_negative != $y->is_negative ) {\r
2168             return ( !$x->is_negative && $y->is_negative ) ? 1 : -1;\r
2169         }\r
2170 \r
2171         $result = $x->is_negative ? -1 : 1;\r
2172 \r
2173         if ( count($x->value) != count($y->value) ) {\r
2174             return ( count($x->value) > count($y->value) ) ? $result : -$result;\r
2175         }\r
2176 \r
2177         for ($i = count($x->value) - 1; $i >= 0; $i--) {\r
2178             if ($x->value[$i] != $y->value[$i]) {\r
2179                 return ( $x->value[$i] > $y->value[$i] ) ? $result : -$result;\r
2180             }\r
2181         }\r
2182 \r
2183         return 0;\r
2184     }\r
2185 \r
2186     /**\r
2187      * Tests the equality of two numbers.\r
2188      *\r
2189      * If you need to see if one number is greater than or less than another number, use Math_BigInteger::compare()\r
2190      *\r
2191      * @param Math_BigInteger $x\r
2192      * @return Boolean\r
2193      * @access public\r
2194      * @see compare()\r
2195      */\r
2196     function equals($x)\r
2197     {\r
2198         switch ( MATH_BIGINTEGER_MODE ) {\r
2199             case MATH_BIGINTEGER_MODE_GMP:\r
2200                 return gmp_cmp($this->value, $x->value) == 0;\r
2201             default:\r
2202                 return $this->value == $x->value && $this->is_negative == $x->is_negative;\r
2203         }\r
2204     }         \r
2205 \r
2206     /**\r
2207      * Set Precision\r
2208      *\r
2209      * Some bitwise operations give different results depending on the precision being used.  Examples include left\r
2210      * shift, not, and rotates.\r
2211      *\r
2212      * @param Math_BigInteger $x\r
2213      * @access public\r
2214      * @return Math_BigInteger\r
2215      */\r
2216     function setPrecision($bits)\r
2217     {\r
2218         $this->precision = $bits;\r
2219         if ( MATH_BIGINTEGER_MODE != MATH_BIGINTEGER_MODE_BCMATH ) {\r
2220             $this->bitmask = new Math_BigInteger(chr((1 << ($bits & 0x7)) - 1) . str_repeat(chr(0xFF), $bits >> 3), 256);\r
2221         } else {\r
2222             $this->bitmask = new Math_BigInteger(bcpow('2', $bits));\r
2223         }\r
2224     }\r
2225 \r
2226     /**\r
2227      * Logical And\r
2228      *\r
2229      * @param Math_BigInteger $x\r
2230      * @access public\r
2231      * @internal Implemented per a request by Lluis Pamies i Juarez <lluis _a_ pamies.cat>\r
2232      * @return Math_BigInteger\r
2233      */\r
2234     function bitwise_and($x)\r
2235     {\r
2236         switch ( MATH_BIGINTEGER_MODE ) {\r
2237             case MATH_BIGINTEGER_MODE_GMP:\r
2238                 $temp = new Math_BigInteger();\r
2239                 $temp->value = gmp_and($this->value, $x->value);\r
2240 \r
2241                 return $this->_normalize($temp);\r
2242             case MATH_BIGINTEGER_MODE_BCMATH:\r
2243                 $left = $this->toBytes();\r
2244                 $right = $x->toBytes();\r
2245 \r
2246                 $length = max(strlen($left), strlen($right));\r
2247 \r
2248                 $left = str_pad($left, $length, chr(0), STR_PAD_LEFT);\r
2249                 $right = str_pad($right, $length, chr(0), STR_PAD_LEFT);\r
2250 \r
2251                 return $this->_normalize(new Math_BigInteger($left & $right, 256));\r
2252         }\r
2253 \r
2254         $result = $this->copy();\r
2255 \r
2256         $length = min(count($x->value), count($this->value));\r
2257 \r
2258         $result->value = array_slice($result->value, 0, $length);\r
2259 \r
2260         for ($i = 0; $i < $length; $i++) {\r
2261             $result->value[$i] = $result->value[$i] & $x->value[$i];\r
2262         }\r
2263 \r
2264         return $this->_normalize($result);\r
2265     }\r
2266 \r
2267     /**\r
2268      * Logical Or\r
2269      *\r
2270      * @param Math_BigInteger $x\r
2271      * @access public\r
2272      * @internal Implemented per a request by Lluis Pamies i Juarez <lluis _a_ pamies.cat>\r
2273      * @return Math_BigInteger\r
2274      */\r
2275     function bitwise_or($x)\r
2276     {\r
2277         switch ( MATH_BIGINTEGER_MODE ) {\r
2278             case MATH_BIGINTEGER_MODE_GMP:\r
2279                 $temp = new Math_BigInteger();\r
2280                 $temp->value = gmp_or($this->value, $x->value);\r
2281 \r
2282                 return $this->_normalize($temp);\r
2283             case MATH_BIGINTEGER_MODE_BCMATH:\r
2284                 $left = $this->toBytes();\r
2285                 $right = $x->toBytes();\r
2286 \r
2287                 $length = max(strlen($left), strlen($right));\r
2288 \r
2289                 $left = str_pad($left, $length, chr(0), STR_PAD_LEFT);\r
2290                 $right = str_pad($right, $length, chr(0), STR_PAD_LEFT);\r
2291 \r
2292                 return $this->_normalize(new Math_BigInteger($left | $right, 256));\r
2293         }\r
2294 \r
2295         $length = max(count($this->value), count($x->value));\r
2296         $result = $this->copy();\r
2297         $result->value = array_pad($result->value, 0, $length);\r
2298         $x->value = array_pad($x->value, 0, $length);\r
2299 \r
2300         for ($i = 0; $i < $length; $i++) {\r
2301             $result->value[$i] = $this->value[$i] | $x->value[$i];\r
2302         }\r
2303 \r
2304         return $this->_normalize($result);\r
2305     }\r
2306 \r
2307     /**\r
2308      * Logical Exclusive-Or\r
2309      *\r
2310      * @param Math_BigInteger $x\r
2311      * @access public\r
2312      * @internal Implemented per a request by Lluis Pamies i Juarez <lluis _a_ pamies.cat>\r
2313      * @return Math_BigInteger\r
2314      */\r
2315     function bitwise_xor($x)\r
2316     {\r
2317         switch ( MATH_BIGINTEGER_MODE ) {\r
2318             case MATH_BIGINTEGER_MODE_GMP:\r
2319                 $temp = new Math_BigInteger();\r
2320                 $temp->value = gmp_xor($this->value, $x->value);\r
2321 \r
2322                 return $this->_normalize($temp);\r
2323             case MATH_BIGINTEGER_MODE_BCMATH:\r
2324                 $left = $this->toBytes();\r
2325                 $right = $x->toBytes();\r
2326 \r
2327                 $length = max(strlen($left), strlen($right));\r
2328 \r
2329                 $left = str_pad($left, $length, chr(0), STR_PAD_LEFT);\r
2330                 $right = str_pad($right, $length, chr(0), STR_PAD_LEFT);\r
2331 \r
2332                 return $this->_normalize(new Math_BigInteger($left ^ $right, 256));\r
2333         }\r
2334 \r
2335         $length = max(count($this->value), count($x->value));\r
2336         $result = $this->copy();\r
2337         $result->value = array_pad($result->value, 0, $length);\r
2338         $x->value = array_pad($x->value, 0, $length);\r
2339 \r
2340         for ($i = 0; $i < $length; $i++) {\r
2341             $result->value[$i] = $this->value[$i] ^ $x->value[$i];\r
2342         }\r
2343 \r
2344         return $this->_normalize($result);\r
2345     }\r
2346 \r
2347     /**\r
2348      * Logical Not\r
2349      *\r
2350      * @access public\r
2351      * @internal Implemented per a request by Lluis Pamies i Juarez <lluis _a_ pamies.cat>\r
2352      * @return Math_BigInteger\r
2353      */\r
2354     function bitwise_not()\r
2355     {\r
2356         // calculuate "not" without regard to $this->precision\r
2357         // (will always result in a smaller number.  ie. ~1 isn't 1111 1110 - it's 0)\r
2358         $temp = $this->toBytes();\r
2359         $pre_msb = decbin(ord($temp[0]));\r
2360         $temp = ~$temp;\r
2361         $msb = decbin(ord($temp[0]));\r
2362         if (strlen($msb) == 8) {\r
2363             $msb = substr($msb, strpos($msb, '0'));\r
2364         }\r
2365         $temp[0] = chr(bindec($msb));\r
2366 \r
2367         // see if we need to add extra leading 1's\r
2368         $current_bits = strlen($pre_msb) + 8 * strlen($temp) - 8;\r
2369         $new_bits = $this->precision - $current_bits;\r
2370         if ($new_bits <= 0) {\r
2371             return $this->_normalize(new Math_BigInteger($temp, 256));\r
2372         }\r
2373 \r
2374         // generate as many leading 1's as we need to.\r
2375         $leading_ones = chr((1 << ($new_bits & 0x7)) - 1) . str_repeat(chr(0xFF), $new_bits >> 3);\r
2376         $this->_base256_lshift($leading_ones, $current_bits);\r
2377 \r
2378         $temp = str_pad($temp, ceil($this->bits / 8), chr(0), STR_PAD_LEFT);\r
2379 \r
2380         return $this->_normalize(new Math_BigInteger($leading_ones | $temp, 256));\r
2381     }\r
2382 \r
2383     /**\r
2384      * Logical Right Shift\r
2385      *\r
2386      * Shifts BigInteger's by $shift bits, effectively dividing by 2**$shift.\r
2387      *\r
2388      * @param Integer $shift\r
2389      * @return Math_BigInteger\r
2390      * @access public\r
2391      * @internal The only version that yields any speed increases is the internal version.\r
2392      */\r
2393     function bitwise_rightShift($shift)\r
2394     {\r
2395         $temp = new Math_BigInteger();\r
2396 \r
2397         switch ( MATH_BIGINTEGER_MODE ) {\r
2398             case MATH_BIGINTEGER_MODE_GMP:\r
2399                 static $two;\r
2400 \r
2401                 if (empty($two)) {\r
2402                     $two = gmp_init('2');\r
2403                 }\r
2404 \r
2405                 $temp->value = gmp_div_q($this->value, gmp_pow($two, $shift));\r
2406 \r
2407                 break;\r
2408             case MATH_BIGINTEGER_MODE_BCMATH:\r
2409                 $temp->value = bcdiv($this->value, bcpow('2', $shift));\r
2410 \r
2411                 break;\r
2412             default: // could just replace _lshift with this, but then all _lshift() calls would need to be rewritten\r
2413                      // and I don't want to do that...\r
2414                 $temp->value = $this->value;\r
2415                 $temp->_rshift($shift);\r
2416         }\r
2417 \r
2418         return $this->_normalize($temp);\r
2419     }\r
2420 \r
2421     /**\r
2422      * Logical Left Shift\r
2423      *\r
2424      * Shifts BigInteger's by $shift bits, effectively multiplying by 2**$shift.\r
2425      *\r
2426      * @param Integer $shift\r
2427      * @return Math_BigInteger\r
2428      * @access public\r
2429      * @internal The only version that yields any speed increases is the internal version.\r
2430      */\r
2431     function bitwise_leftShift($shift)\r
2432     {\r
2433         $temp = new Math_BigInteger();\r
2434 \r
2435         switch ( MATH_BIGINTEGER_MODE ) {\r
2436             case MATH_BIGINTEGER_MODE_GMP:\r
2437                 static $two;\r
2438 \r
2439                 if (empty($two)) {\r
2440                     $two = gmp_init('2');\r
2441                 }\r
2442 \r
2443                 $temp->value = gmp_mul($this->value, gmp_pow($two, $shift));\r
2444 \r
2445                 break;\r
2446             case MATH_BIGINTEGER_MODE_BCMATH:\r
2447                 $temp->value = bcmul($this->value, bcpow('2', $shift));\r
2448 \r
2449                 break;\r
2450             default: // could just replace _rshift with this, but then all _lshift() calls would need to be rewritten\r
2451                      // and I don't want to do that...\r
2452                 $temp->value = $this->value;\r
2453                 $temp->_lshift($shift);\r
2454         }\r
2455 \r
2456         return $this->_normalize($temp);\r
2457     }\r
2458 \r
2459     /**\r
2460      * Logical Left Rotate\r
2461      *\r
2462      * Instead of the top x bits being dropped they're appended to the shifted bit string.\r
2463      *\r
2464      * @param Integer $shift\r
2465      * @return Math_BigInteger\r
2466      * @access public\r
2467      */\r
2468     function bitwise_leftRotate($shift)\r
2469     {\r
2470         $bits = $this->toBytes();\r
2471 \r
2472         if ($this->precision > 0) {\r
2473             $precision = $this->precision;\r
2474             if ( MATH_BIGINTEGER_MODE == MATH_BIGINTEGER_MODE_BCMATH ) {\r
2475                 $mask = $this->bitmask->subtract(new Math_BigInteger(1));\r
2476                 $mask = $mask->toBytes();\r
2477             } else {\r
2478                 $mask = $this->bitmask->toBytes();\r
2479             }\r
2480         } else {\r
2481             $temp = ord($bits[0]);\r
2482             for ($i = 0; $temp >> $i; $i++);\r
2483             $precision = 8 * strlen($bits) - 8 + $i;\r
2484             $mask = chr((1 << ($precision & 0x7)) - 1) . str_repeat(chr(0xFF), $precision >> 3);\r
2485         }\r
2486 \r
2487         if ($shift < 0) {\r
2488             $shift+= $precision;\r
2489         }\r
2490         $shift%= $precision;\r
2491 \r
2492         if (!$shift) {\r
2493             return $this->copy();\r
2494         }\r
2495 \r
2496         $left = $this->bitwise_leftShift($shift);\r
2497         $left = $left->bitwise_and(new Math_BigInteger($mask, 256));\r
2498         $right = $this->bitwise_rightShift($precision - $shift);\r
2499         $result = MATH_BIGINTEGER_MODE != MATH_BIGINTEGER_MODE_BCMATH ? $left->bitwise_or($right) : $left->add($right);\r
2500         return $this->_normalize($result);\r
2501     }\r
2502 \r
2503     /**\r
2504      * Logical Right Rotate\r
2505      *\r
2506      * Instead of the bottom x bits being dropped they're prepended to the shifted bit string.\r
2507      *\r
2508      * @param Integer $shift\r
2509      * @return Math_BigInteger\r
2510      * @access public\r
2511      */\r
2512     function bitwise_rightRotate($shift)\r
2513     {\r
2514         return $this->bitwise_leftRotate(-$shift);\r
2515     }\r
2516 \r
2517     /**\r
2518      * Set random number generator function\r
2519      *\r
2520      * $generator should be the name of a random generating function whose first parameter is the minimum\r
2521      * value and whose second parameter is the maximum value.  If this function needs to be seeded, it should\r
2522      * be seeded prior to calling Math_BigInteger::random() or Math_BigInteger::randomPrime()\r
2523      *\r
2524      * If the random generating function is not explicitly set, it'll be assumed to be mt_rand().\r
2525      *\r
2526      * @see random()\r
2527      * @see randomPrime()\r
2528      * @param optional String $generator\r
2529      * @access public\r
2530      */\r
2531     function setRandomGenerator($generator)\r
2532     {\r
2533         $this->generator = $generator;\r
2534     }\r
2535 \r
2536     /**\r
2537      * Generate a random number\r
2538      *\r
2539      * @param optional Integer $min\r
2540      * @param optional Integer $max\r
2541      * @return Math_BigInteger\r
2542      * @access public\r
2543      */\r
2544     function random($min = false, $max = false)\r
2545     {\r
2546         if ($min === false) {\r
2547             $min = new Math_BigInteger(0);\r
2548         }\r
2549 \r
2550         if ($max === false) {\r
2551             $max = new Math_BigInteger(0x7FFFFFFF);\r
2552         }\r
2553 \r
2554         $compare = $max->compare($min);\r
2555 \r
2556         if (!$compare) {\r
2557             return $this->_normalize($min);\r
2558         } else if ($compare < 0) {\r
2559             // if $min is bigger then $max, swap $min and $max\r
2560             $temp = $max;\r
2561             $max = $min;\r
2562             $min = $temp;\r
2563         }\r
2564 \r
2565         $generator = $this->generator;\r
2566 \r
2567         $max = $max->subtract($min);\r
2568         $max = ltrim($max->toBytes(), chr(0));\r
2569         $size = strlen($max) - 1;\r
2570         $random = '';\r
2571 \r
2572         $bytes = $size & 1;\r
2573         for ($i = 0; $i < $bytes; $i++) {\r
2574             $random.= chr($generator(0, 255));\r
2575         }\r
2576 \r
2577         $blocks = $size >> 1;\r
2578         for ($i = 0; $i < $blocks; $i++) {\r
2579             // mt_rand(-2147483648, 0x7FFFFFFF) always produces -2147483648 on some systems\r
2580             $random.= pack('n', $generator(0, 0xFFFF));\r
2581         }\r
2582 \r
2583         $temp = new Math_BigInteger($random, 256);\r
2584         if ($temp->compare(new Math_BigInteger(substr($max, 1), 256)) > 0) {\r
2585             $random = chr($generator(0, ord($max[0]) - 1)) . $random;\r
2586         } else {\r
2587             $random = chr($generator(0, ord($max[0])    )) . $random;\r
2588         }\r
2589 \r
2590         $random = new Math_BigInteger($random, 256);\r
2591 \r
2592         return $this->_normalize($random->add($min));\r
2593     }\r
2594 \r
2595     /**\r
2596      * Generate a random prime number.\r
2597      *\r
2598      * If there's not a prime within the given range, false will be returned.  If more than $timeout seconds have elapsed,\r
2599      * give up and return false.\r
2600      *\r
2601      * @param optional Integer $min\r
2602      * @param optional Integer $max\r
2603      * @param optional Integer $timeout\r
2604      * @return Math_BigInteger\r
2605      * @access public\r
2606      * @internal See {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap4.pdf#page=15 HAC 4.44}.\r
2607      */\r
2608     function randomPrime($min = false, $max = false, $timeout = false)\r
2609     {\r
2610         // gmp_nextprime() requires PHP 5 >= 5.2.0 per <http://php.net/gmp-nextprime>.\r
2611         if ( MATH_BIGINTEGER_MODE == MATH_BIGINTEGER_MODE_GMP && function_exists('gmp_nextprime') ) {\r
2612             // we don't rely on Math_BigInteger::random()'s min / max when gmp_nextprime() is being used since this function\r
2613             // does its own checks on $max / $min when gmp_nextprime() is used.  When gmp_nextprime() is not used, however,\r
2614             // the same $max / $min checks are not performed.\r
2615             if ($min === false) {\r
2616                 $min = new Math_BigInteger(0);\r
2617             }\r
2618 \r
2619             if ($max === false) {\r
2620                 $max = new Math_BigInteger(0x7FFFFFFF);\r
2621             }\r
2622 \r
2623             $compare = $max->compare($min);\r
2624 \r
2625             if (!$compare) {\r
2626                 return $min;\r
2627             } else if ($compare < 0) {\r
2628                 // if $min is bigger then $max, swap $min and $max\r
2629                 $temp = $max;\r
2630                 $max = $min;\r
2631                 $min = $temp;\r
2632             }\r
2633 \r
2634             $x = $this->random($min, $max);\r
2635 \r
2636             $x->value = gmp_nextprime($x->value);\r
2637 \r
2638             if ($x->compare($max) <= 0) {\r
2639                 return $x;\r
2640             }\r
2641 \r
2642             $x->value = gmp_nextprime($min->value);\r
2643 \r
2644             if ($x->compare($max) <= 0) {\r
2645                 return $x;\r
2646             }\r
2647 \r
2648             return false;\r
2649         }\r
2650 \r
2651         $repeat1 = $repeat2 = array();\r
2652 \r
2653         $one = new Math_BigInteger(1);\r
2654         $two = new Math_BigInteger(2);\r
2655 \r
2656         $start = time();\r
2657 \r
2658         do {\r
2659             if ($timeout !== false && time() - $start > $timeout) {\r
2660                 return false;\r
2661             }\r
2662 \r
2663             $x = $this->random($min, $max);\r
2664             if ($x->equals($two)) {\r
2665                 return $x;\r
2666             }\r
2667 \r
2668             // make the number odd\r
2669             switch ( MATH_BIGINTEGER_MODE ) {\r
2670                 case MATH_BIGINTEGER_MODE_GMP:\r
2671                     gmp_setbit($x->value, 0);\r
2672                     break;\r
2673                 case MATH_BIGINTEGER_MODE_BCMATH:\r
2674                     if ($x->value[strlen($x->value) - 1] % 2 == 0) {\r
2675                         $x = $x->add($one);\r
2676                     }\r
2677                     break;\r
2678                 default:\r
2679                     $x->value[0] |= 1;\r
2680             }\r
2681 \r
2682             // if we've seen this number twice before, assume there are no prime numbers within the given range\r
2683             if (in_array($x->value, $repeat1)) {\r
2684                 if (in_array($x->value, $repeat2)) {\r
2685                     return false;\r
2686                 } else {\r
2687                     $repeat2[] = $x->value;\r
2688                 }\r
2689             } else {\r
2690                 $repeat1[] = $x->value;\r
2691             }\r
2692         } while (!$x->isPrime());\r
2693 \r
2694         return $x;\r
2695     }\r
2696 \r
2697     /**\r
2698      * Checks a numer to see if it's prime\r
2699      *\r
2700      * Assuming the $t parameter is not set, this functoin has an error rate of 2**-80.  The main motivation for the\r
2701      * $t parameter is distributability.  Math_BigInteger::randomPrime() can be distributed accross multiple pageloads\r
2702      * on a website instead of just one.\r
2703      *\r
2704      * @param optional Integer $t\r
2705      * @return Boolean\r
2706      * @access public\r
2707      * @internal Uses the\r
2708      *     {@link http://en.wikipedia.org/wiki/Miller%E2%80%93Rabin_primality_test Miller\96Rabin primality test}.  See \r
2709      *     {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap4.pdf#page=8 HAC 4.24}.\r
2710      */\r
2711     function isPrime($t = false)\r
2712     {\r
2713         $length = strlen($this->toBytes());\r
2714 \r
2715         if (!$t) {\r
2716             // see HAC 4.49 "Note (controlling the error probability)"\r
2717                  if ($length >= 163) { $t =  2; } // floor(1300 / 8)\r
2718             else if ($length >= 106) { $t =  3; } // floor( 850 / 8)\r
2719             else if ($length >= 81 ) { $t =  4; } // floor( 650 / 8)\r
2720             else if ($length >= 68 ) { $t =  5; } // floor( 550 / 8)\r
2721             else if ($length >= 56 ) { $t =  6; } // floor( 450 / 8)\r
2722             else if ($length >= 50 ) { $t =  7; } // floor( 400 / 8)\r
2723             else if ($length >= 43 ) { $t =  8; } // floor( 350 / 8)\r
2724             else if ($length >= 37 ) { $t =  9; } // floor( 300 / 8)\r
2725             else if ($length >= 31 ) { $t = 12; } // floor( 250 / 8)\r
2726             else if ($length >= 25 ) { $t = 15; } // floor( 200 / 8)\r
2727             else if ($length >= 18 ) { $t = 18; } // floor( 150 / 8)\r
2728             else                     { $t = 27; }\r
2729         }\r
2730 \r
2731         // ie. gmp_testbit($this, 0)\r
2732         // ie. isEven() or !isOdd()\r
2733         switch ( MATH_BIGINTEGER_MODE ) {\r
2734             case MATH_BIGINTEGER_MODE_GMP:\r
2735                 return gmp_prob_prime($this->value, $t) != 0;\r
2736             case MATH_BIGINTEGER_MODE_BCMATH:\r
2737                 if ($this->value == '2') {\r
2738                     return true;\r
2739                 }\r
2740                 if ($this->value[strlen($this->value) - 1] % 2 == 0) {\r
2741                     return false;\r
2742                 }\r
2743                 break;\r
2744             default:\r
2745                 if ($this->value == array(2)) {\r
2746                     return true;\r
2747                 }\r
2748                 if (~$this->value[0] & 1) {\r
2749                     return false;\r
2750                 }\r
2751         }\r
2752 \r
2753         static $primes, $zero, $one, $two;\r
2754 \r
2755         if (!isset($primes)) {\r
2756             $primes = array(\r
2757                 3,    5,    7,    11,   13,   17,   19,   23,   29,   31,   37,   41,   43,   47,   53,   59,   \r
2758                 61,   67,   71,   73,   79,   83,   89,   97,   101,  103,  107,  109,  113,  127,  131,  137,  \r
2759                 139,  149,  151,  157,  163,  167,  173,  179,  181,  191,  193,  197,  199,  211,  223,  227,  \r
2760                 229,  233,  239,  241,  251,  257,  263,  269,  271,  277,  281,  283,  293,  307,  311,  313,  \r
2761                 317,  331,  337,  347,  349,  353,  359,  367,  373,  379,  383,  389,  397,  401,  409,  419,  \r
2762                 421,  431,  433,  439,  443,  449,  457,  461,  463,  467,  479,  487,  491,  499,  503,  509,  \r
2763                 521,  523,  541,  547,  557,  563,  569,  571,  577,  587,  593,  599,  601,  607,  613,  617,  \r
2764                 619,  631,  641,  643,  647,  653,  659,  661,  673,  677,  683,  691,  701,  709,  719,  727,  \r
2765                 733,  739,  743,  751,  757,  761,  769,  773,  787,  797,  809,  811,  821,  823,  827,  829,  \r
2766                 839,  853,  857,  859,  863,  877,  881,  883,  887,  907,  911,  919,  929,  937,  941,  947,  \r
2767                 953,  967,  971,  977,  983,  991,  997\r
2768             );\r
2769 \r
2770             for ($i = 0; $i < count($primes); $i++) {\r
2771                 $primes[$i] = new Math_BigInteger($primes[$i]);\r
2772             }\r
2773 \r
2774             $zero = new Math_BigInteger();\r
2775             $one = new Math_BigInteger(1);\r
2776             $two = new Math_BigInteger(2);\r
2777         }\r
2778 \r
2779         // see HAC 4.4.1 "Random search for probable primes"\r
2780         for ($i = 0; $i < count($primes); $i++) {\r
2781             list(, $r) = $this->divide($primes[$i]);\r
2782             if ($r->equals($zero)) {\r
2783                 return false;\r
2784             }\r
2785         }\r
2786 \r
2787         $n   = $this->copy();\r
2788         $n_1 = $n->subtract($one);\r
2789         $n_2 = $n->subtract($two);\r
2790 \r
2791         $r = $n_1->copy();\r
2792         // ie. $s = gmp_scan1($n, 0) and $r = gmp_div_q($n, gmp_pow(gmp_init('2'), $s));\r
2793         if ( MATH_BIGINTEGER_MODE == MATH_BIGINTEGER_MODE_BCMATH ) {\r
2794             $s = 0;\r
2795             while ($r->value[strlen($r->value) - 1] % 2 == 0) {\r
2796                 $r->value = bcdiv($r->value, 2);\r
2797                 $s++;\r
2798             }\r
2799         } else {\r
2800             for ($i = 0; $i < count($r->value); $i++) {\r
2801                 $temp = ~$r->value[$i] & 0xFFFFFF;\r
2802                 for ($j = 1; ($temp >> $j) & 1; $j++);\r
2803                 if ($j != 25) {\r
2804                     break;\r
2805                 }\r
2806             }\r
2807             $s = 26 * $i + $j - 1;\r
2808             $r->_rshift($s);\r
2809         }\r
2810 \r
2811         for ($i = 0; $i < $t; $i++) {\r
2812             $a = new Math_BigInteger();\r
2813             $a = $a->random($two, $n_2);\r
2814             $y = $a->modPow($r, $n);\r
2815 \r
2816             if (!$y->equals($one) && !$y->equals($n_1)) {\r
2817                 for ($j = 1; $j < $s && !$y->equals($n_1); $j++) {\r
2818                     $y = $y->modPow($two, $n);\r
2819                     if ($y->equals($one)) {\r
2820                         return false;\r
2821                     }\r
2822                 }\r
2823 \r
2824                 if (!$y->equals($n_1)) {\r
2825                     return false;\r
2826                 }\r
2827             }\r
2828         }\r
2829         return true;\r
2830     }\r
2831 \r
2832     /**\r
2833      * Logical Left Shift\r
2834      *\r
2835      * Shifts BigInteger's by $shift bits.\r
2836      *\r
2837      * @param Integer $shift\r
2838      * @access private\r
2839      */\r
2840     function _lshift($shift)\r
2841     {\r
2842         if ( $shift == 0 ) {\r
2843             return;\r
2844         }\r
2845 \r
2846         $num_digits = floor($shift / 26);\r
2847         $shift %= 26;\r
2848         $shift = 1 << $shift;\r
2849 \r
2850         $carry = 0;\r
2851 \r
2852         for ($i = 0; $i < count($this->value); $i++) {\r
2853             $temp = $this->value[$i] * $shift + $carry;\r
2854             $carry = floor($temp / 0x4000000);\r
2855             $this->value[$i] = $temp - $carry * 0x4000000;\r
2856         }\r
2857 \r
2858         if ( $carry ) {\r
2859             $this->value[] = $carry;\r
2860         }\r
2861 \r
2862         while ($num_digits--) {\r
2863             array_unshift($this->value, 0);\r
2864         }\r
2865     }\r
2866 \r
2867     /**\r
2868      * Logical Right Shift\r
2869      *\r
2870      * Shifts BigInteger's by $shift bits.\r
2871      *\r
2872      * @param Integer $shift\r
2873      * @access private\r
2874      */\r
2875     function _rshift($shift)\r
2876     {\r
2877         if ($shift == 0) {\r
2878             return;\r
2879         }\r
2880 \r
2881         $num_digits = floor($shift / 26);\r
2882         $shift %= 26;\r
2883         $carry_shift = 26 - $shift;\r
2884         $carry_mask = (1 << $shift) - 1;\r
2885 \r
2886         if ( $num_digits ) {\r
2887             $this->value = array_slice($this->value, $num_digits);\r
2888         }\r
2889 \r
2890         $carry = 0;\r
2891 \r
2892         for ($i = count($this->value) - 1; $i >= 0; $i--) {\r
2893             $temp = $this->value[$i] >> $shift | $carry;\r
2894             $carry = ($this->value[$i] & $carry_mask) << $carry_shift;\r
2895             $this->value[$i] = $temp;\r
2896         }\r
2897     }\r
2898 \r
2899     /**\r
2900      * Normalize\r
2901      *\r
2902      * Deletes leading zeros and truncates (if necessary) to maintain the appropriate precision\r
2903      *\r
2904      * @return Math_BigInteger\r
2905      * @access private\r
2906      */\r
2907     function _normalize($result)\r
2908     {\r
2909         $result->precision = $this->precision;\r
2910         $result->bitmask = $this->bitmask;\r
2911 \r
2912         switch ( MATH_BIGINTEGER_MODE ) {\r
2913             case MATH_BIGINTEGER_MODE_GMP:\r
2914                 if (!empty($result->bitmask->value)) {\r
2915                     $result->value = gmp_and($result->value, $result->bitmask->value);\r
2916                 }\r
2917 \r
2918                 return $result;\r
2919             case MATH_BIGINTEGER_MODE_BCMATH:\r
2920                 if (!empty($result->bitmask->value)) {\r
2921                     $result->value = bcmod($result->value, $result->bitmask->value);\r
2922                 }\r
2923 \r
2924                 return $result;\r
2925         }\r
2926 \r
2927         if ( !count($result->value) ) {\r
2928             return $result;\r
2929         }\r
2930 \r
2931         for ($i = count($result->value) - 1; $i >= 0; $i--) {\r
2932             if ( $result->value[$i] ) {\r
2933                 break;\r
2934             }\r
2935             unset($result->value[$i]);\r
2936         }\r
2937 \r
2938         if (!empty($result->bitmask->value)) {\r
2939             $length = min(count($result->value), count($this->bitmask->value));\r
2940             $result->value = array_slice($result->value, 0, $length);\r
2941 \r
2942             for ($i = 0; $i < $length; $i++) {\r
2943                 $result->value[$i] = $result->value[$i] & $this->bitmask->value[$i];\r
2944             }\r
2945         }\r
2946 \r
2947         return $result;\r
2948     }\r
2949 \r
2950     /**\r
2951      * Array Repeat\r
2952      *\r
2953      * @param $input Array\r
2954      * @param $multiplier mixed\r
2955      * @return Array\r
2956      * @access private\r
2957      */\r
2958     function _array_repeat($input, $multiplier)\r
2959     {\r
2960         return ($multiplier) ? array_fill(0, $multiplier, $input) : array();\r
2961     }\r
2962 \r
2963     /**\r
2964      * Logical Left Shift\r
2965      *\r
2966      * Shifts binary strings $shift bits, essentially multiplying by 2**$shift.\r
2967      *\r
2968      * @param $x String\r
2969      * @param $shift Integer\r
2970      * @return String\r
2971      * @access private\r
2972      */\r
2973     function _base256_lshift(&$x, $shift)\r
2974     {\r
2975         if ($shift == 0) {\r
2976             return;\r
2977         }\r
2978 \r
2979         $num_bytes = $shift >> 3; // eg. floor($shift/8)\r
2980         $shift &= 7; // eg. $shift % 8\r
2981 \r
2982         $carry = 0;\r
2983         for ($i = strlen($x) - 1; $i >= 0; $i--) {\r
2984             $temp = ord($x[$i]) << $shift | $carry;\r
2985             $x[$i] = chr($temp);\r
2986             $carry = $temp >> 8;\r
2987         }\r
2988         $carry = ($carry != 0) ? chr($carry) : '';\r
2989         $x = $carry . $x . str_repeat(chr(0), $num_bytes);\r
2990     }\r
2991 \r
2992     /**\r
2993      * Logical Right Shift\r
2994      *\r
2995      * Shifts binary strings $shift bits, essentially dividing by 2**$shift and returning the remainder.\r
2996      *\r
2997      * @param $x String\r
2998      * @param $shift Integer\r
2999      * @return String\r
3000      * @access private\r
3001      */\r
3002     function _base256_rshift(&$x, $shift)\r
3003     {\r
3004         if ($shift == 0) {\r
3005             $x = ltrim($x, chr(0));\r
3006             return '';\r
3007         }\r
3008 \r
3009         $num_bytes = $shift >> 3; // eg. floor($shift/8)\r
3010         $shift &= 7; // eg. $shift % 8\r
3011 \r
3012         $remainder = '';\r
3013         if ($num_bytes) {\r
3014             $start = $num_bytes > strlen($x) ? -strlen($x) : -$num_bytes;\r
3015             $remainder = substr($x, $start);\r
3016             $x = substr($x, 0, -$num_bytes);\r
3017         }\r
3018 \r
3019         $carry = 0;\r
3020         $carry_shift = 8 - $shift;\r
3021         for ($i = 0; $i < strlen($x); $i++) {\r
3022             $temp = (ord($x[$i]) >> $shift) | $carry;\r
3023             $carry = (ord($x[$i]) << $carry_shift) & 0xFF;\r
3024             $x[$i] = chr($temp);\r
3025         }\r
3026         $x = ltrim($x, chr(0));\r
3027 \r
3028         $remainder = chr($carry >> $carry_shift) . $remainder;\r
3029 \r
3030         return ltrim($remainder, chr(0));\r
3031     }\r
3032 \r
3033     // one quirk about how the following functions are implemented is that PHP defines N to be an unsigned long\r
3034     // at 32-bits, while java's longs are 64-bits.\r
3035 \r
3036     /**\r
3037      * Converts 32-bit integers to bytes.\r
3038      *\r
3039      * @param Integer $x\r
3040      * @return String\r
3041      * @access private\r
3042      */\r
3043     function _int2bytes($x)\r
3044     {\r
3045         return ltrim(pack('N', $x), chr(0));\r
3046     }\r
3047 \r
3048     /**\r
3049      * Converts bytes to 32-bit integers\r
3050      *\r
3051      * @param String $x\r
3052      * @return Integer\r
3053      * @access private\r
3054      */\r
3055     function _bytes2int($x)\r
3056     {\r
3057         $temp = unpack('Nint', str_pad($x, 4, chr(0), STR_PAD_LEFT));\r
3058         return $temp['int'];\r
3059     }\r
3060 }