#### /js/lib/Socket.IO-node/support/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/math/BigInteger.as

http://github.com/onedayitwillmake/RealtimeMultiplayerNodeJs
ActionScript | 1543 lines | 1136 code | 66 blank | 341 comment | 285 complexity | 7eb5efb1c2cc2a19d158053ed8c12e40 MD5 | raw file
```   1/**
2 * BigInteger
3 *
4 * An ActionScript 3 implementation of BigInteger (light version)
5 * Copyright (c) 2007 Henri Torgemane
6 *
7 * Derived from:
8 * 		The jsbn library, Copyright (c) 2003-2005 Tom Wu
9 *
10 * See LICENSE.txt for full license information.
11 */
12package com.hurlant.math
13{
14
15	import com.hurlant.crypto.prng.Random;
16	import com.hurlant.util.Hex;
17	import com.hurlant.util.Memory;
18
19	import flash.utils.ByteArray;
20	use namespace bi_internal;
21
22	public class BigInteger
23	{
24		public static const DB:int = 30; // number of significant bits per chunk
25		public static const DV:int = (1<<DB);
26		public static const DM:int = (DV-1); // Max value in a chunk
27
28		public static const BI_FP:int = 52;
29		public static const FV:Number = Math.pow(2, BI_FP);
30		public static const F1:int = BI_FP - DB;
31		public static const F2:int = 2*DB - BI_FP;
32
33		public static const ZERO:BigInteger = nbv(0);
34		public static const ONE:BigInteger  = nbv(1);
35
36		/*bi_internal */public var t:int; // number of chunks.
37		bi_internal var s:int; // sign
38		bi_internal var a:Array; // chunks
39
40		/**
41		 *
42		 * @param value
43		 * @param radix  WARNING: If value is ByteArray, this holds the number of bytes to use.
44		 * @param unsigned
45		 *
46		 */
47		public function BigInteger(value:* = null, radix:int = 0, unsigned:Boolean = false) {
48			a = new Array;
49			if (value is String) {
50				if (radix&&radix!=16) throw new Error("BigInteger construction with radix!=16 is not supported.");
51				value = Hex.toArray(value);
52				radix=0;
53			}
54			if (value is ByteArray) {
55				var array:ByteArray = value as ByteArray;
56				var length:int = radix || (array.length - array.position);
57				fromArray(array, length, unsigned);
58			}
59		}
60		public function dispose():void {
61			var r:Random = new Random;
62			for (var i:uint=0;i<a.length;i++) {
63				a[i] = r.nextByte();
64				delete a[i];
65			}
66			a=null;
67			t=0;
68			s=0;
69			Memory.gc();
70		}
71
72		public function toString(radix:Number=16):String {
73			if (s<0) return "-"+negate().toString(radix);
74			var k:int;
75			switch (radix) {
76				case 2:   k=1; break;
77				case 4:   k=2; break;
78				case 8:   k=3; break;
79				case 16:  k=4; break;
80				case 32:  k=5; break;
81				default:
82//					return toRadix(radix);
83			}
84			var km:int = (1<<k)-1;
85			var d:int = 0;
86			var m:Boolean = false;
87			var r:String = "";
88			var i:int = t;
89			var p:int = DB-(i*DB)%k;
90			if (i-->0) {
91				if (p<DB && (d=a[i]>>p)>0) {
92					m = true;
93					r = d.toString(36);
94				}
95				while (i >= 0) {
96					if (p<k) {
97						d = (a[i]&((1<<p)-1))<<(k-p);
98						d|= a[--i]>>(p+=DB-k);
99					} else {
100						d = (a[i]>>(p-=k))&km;
101						if (p<=0) {
102							p += DB;
103							--i;
104						}
105					}
106					if (d>0) {
107						m = true;
108					}
109					if (m) {
110						r += d.toString(36);
111					}
112				}
113			}
114			return m?r:"0";
115		}
116		public function toArray(array:ByteArray):uint {
117			const k:int = 8;
118			const km:int = (1<<8)-1;
119			var d:int = 0;
120			var i:int = t;
121			var p:int = DB-(i*DB)%k;
122			var m:Boolean = false;
123			var c:int = 0;
124			if (i-->0) {
125				if (p<DB && (d=a[i]>>p)>0) {
126					m = true;
127					array.writeByte(d);
128					c++;
129				}
130				while (i >= 0) {
131					if (p<k) {
132						d = (a[i]&((1<<p)-1))<<(k-p);
133						d|= a[--i]>>(p+=DB-k);
134					} else {
135						d = (a[i]>>(p-=k))&km;
136						if (p<=0) {
137							p += DB;
138							--i;
139						}
140					}
141					if (d>0) {
142						m = true;
143					}
144					if (m) {
145						array.writeByte(d);
146						c++;
147					}
148				}
149			}
150			return c;
151		}
152		/**
153		 * best-effort attempt to fit into a Number.
154		 * precision can be lost if it just can't fit.
155		 */
156		public function valueOf():Number {
157			if (s==-1) {
158				return -negate().valueOf();
159			}
160			var coef:Number = 1;
161			var value:Number = 0;
162			for (var i:uint=0;i<t;i++) {
163				value += a[i]*coef;
164				coef *= DV;
165			}
166			return value;
167		}
168		/**
169		 * -this
170		 */
171		public function negate():BigInteger {
172			var r:BigInteger = nbi();
173			ZERO.subTo(this, r);
174			return r;
175		}
176		/**
177		 * |this|
178		 */
179		public function abs():BigInteger {
180			return (s<0)?negate():this;
181		}
182		/**
183		 * return + if this > v, - if this < v, 0 if equal
184		 */
185		public function compareTo(v:BigInteger):int {
186			var r:int = s - v.s;
187			if (r!=0) {
188				return r;
189			}
190			var i:int = t;
191			r = i-v.t;
192			if (r!=0) {
193				return r;
194			}
195			while (--i >=0) {
196				r=a[i]-v.a[i];
197				if (r != 0) return r;
198			}
199			return 0;
200		}
201		/**
202		 * returns bit length of the integer x
203		 */
204		bi_internal function nbits(x:int):int {
205			var r:int = 1;
206			var t:int;
207			if ((t=x>>>16) != 0) { x = t; r += 16; }
208			if ((t=x>>8) != 0) { x = t; r += 8; }
209			if ((t=x>>4) != 0) { x = t; r += 4; }
210			if ((t=x>>2) != 0) { x = t; r += 2; }
211			if ((t=x>>1) != 0) { x = t; r += 1; }
212			return r;
213		}
214		/**
215		 * returns the number of bits in this
216		 */
217		public function bitLength():int {
218			if (t<=0) return 0;
219			return DB*(t-1)+nbits(a[t-1]^(s&DM));
220		}
221		/**
222		 *
223		 * @param v
224		 * @return this % v
225		 *
226		 */
227		public function mod(v:BigInteger):BigInteger {
228			var r:BigInteger = nbi();
229			abs().divRemTo(v,null,r);
230			if (s<0 && r.compareTo(ZERO)>0) {
231				v.subTo(r,r);
232			}
233			return r;
234		}
235		/**
236		 * this^e % m, 0 <= e < 2^32
237		 */
238		public function modPowInt(e:int, m:BigInteger):BigInteger {
239			var z:IReduction;
240			if (e<256 || m.isEven()) {
241				z = new ClassicReduction(m);
242			} else {
243				z = new MontgomeryReduction(m);
244			}
245			return exp(e, z);
246		}
247
248		/**
249		 * copy this to r
250		 */
251		bi_internal function copyTo(r:BigInteger):void {
252			for (var i:int = t-1; i>=0; --i) {
253				r.a[i] = a[i];
254			}
255			r.t = t;
256			r.s = s;
257		}
258		/**
259		 * set from integer value "value", -DV <= value < DV
260		 */
261		bi_internal function fromInt(value:int):void {
262			t = 1;
263			s = (value<0)?-1:0;
264			if (value>0) {
265				a[0] = value;
266			} else if (value<-1) {
267				a[0] = value+DV;
268			} else {
269				t = 0;
270			}
271		}
272		/**
273		 * set from ByteArray and length,
274		 * starting a current position
275		 * If length goes beyond the array, pad with zeroes.
276		 */
277		bi_internal function fromArray(value:ByteArray, length:int, unsigned:Boolean = false):void {
278			var p:int = value.position;
279			var i:int = p+length;
280			var sh:int = 0;
281			const k:int = 8;
282			t = 0;
283			s = 0;
284			while (--i >= p) {
285				var x:int = i<value.length?value[i]:0;
286				if (sh == 0) {
287					a[t++] = x;
288				} else if (sh+k > DB) {
289					a[t-1] |= (x&((1<<(DB-sh))-1))<<sh;
290					a[t++] = x>>(DB-sh);
291				} else {
292					a[t-1] |= x<<sh;
293				}
294				sh += k;
295				if (sh >= DB) sh -= DB;
296			}
297			if (!unsigned && (value[0]&0x80)==0x80) {
298				s = -1;
299				if (sh > 0) {
300					a[t-1] |= ((1<<(DB-sh))-1)<<sh;
301				}
302			}
303			clamp();
304			value.position = Math.min(p+length,value.length);
305		}
306		/**
307		 * clamp off excess high words
308		 */
309		bi_internal function clamp():void {
310			var c:int = s&DM;
311			while (t>0 && a[t-1]==c) {
312				--t;
313			}
314		}
315		/**
316		 * r = this << n*DB
317		 */
318		bi_internal function dlShiftTo(n:int, r:BigInteger):void {
319			var i:int;
320			for (i=t-1; i>=0; --i) {
321				r.a[i+n] = a[i];
322			}
323			for (i=n-1; i>=0; --i) {
324				r.a[i] = 0;
325			}
326			r.t = t+n;
327			r.s = s;
328		}
329		/**
330		 * r = this >> n*DB
331		 */
332		bi_internal function drShiftTo(n:int, r:BigInteger):void {
333			var i:int;
334			for (i=n; i<t; ++i) {
335				r.a[i-n] = a[i];
336			}
337			r.t = Math.max(t-n,0);
338			r.s = s;
339		}
340		/**
341		 * r = this << n
342		 */
343		bi_internal function lShiftTo(n:int, r:BigInteger):void {
344			var bs:int = n%DB;
345			var cbs:int = DB-bs;
346			var bm:int = (1<<cbs)-1;
347			var ds:int = n/DB;
348			var c:int = (s<<bs)&DM;
349			var i:int;
350			for (i=t-1; i>=0; --i) {
351				r.a[i+ds+1] = (a[i]>>cbs)|c;
352				c = (a[i]&bm)<<bs;
353			}
354			for (i=ds-1; i>=0; --i) {
355				r.a[i] = 0;
356			}
357			r.a[ds] = c;
358			r.t = t+ds+1;
359			r.s = s;
360			r.clamp();
361		}
362		/**
363		 * r = this >> n
364		 */
365		bi_internal function rShiftTo(n:int, r:BigInteger):void {
366			r.s = s;
367			var ds:int = n/DB;
368			if (ds >= t) {
369				r.t = 0;
370				return;
371			}
372			var bs:int = n%DB;
373			var cbs:int = DB-bs;
374			var bm:int = (1<<bs)-1;
375			r.a[0] = a[ds]>>bs;
376			var i:int;
377			for (i=ds+1; i<t; ++i) {
378				r.a[i-ds-1] |= (a[i]&bm)<<cbs;
379				r.a[i-ds] = a[i]>>bs;
380			}
381			if (bs>0) {
382				r.a[t-ds-1] |= (s&bm)<<cbs;
383			}
384			r.t = t-ds;
385			r.clamp();
386		}
387		/**
388		 * r = this - v
389		 */
390		bi_internal function subTo(v:BigInteger, r:BigInteger):void {
391			var i:int = 0;
392			var c:int = 0;
393			var m:int = Math.min(v.t, t);
394			while (i<m) {
395				c += a[i] - v.a[i];
396				r.a[i++] = c & DM;
397				c >>= DB;
398			}
399			if (v.t < t) {
400				c -= v.s;
401				while (i< t) {
402					c+= a[i];
403					r.a[i++] = c&DM;
404					c >>= DB;
405				}
406				c += s;
407			} else {
408				c += s;
409				while (i < v.t) {
410					c -= v.a[i];
411					r.a[i++] = c&DM;
412					c >>= DB;
413				}
414				c -= v.s;
415			}
416			r.s = (c<0)?-1:0;
417			if (c<-1) {
418				r.a[i++] = DV+c;
419			} else if (c>0) {
420				r.a[i++] = c;
421			}
422			r.t = i;
423			r.clamp();
424		}
425		/**
426		 * am: Compute w_j += (x*this_i), propagates carries,
427		 * c is initial carry, returns final carry.
428		 * c < 3*dvalue, x < 2*dvalue, this_i < dvalue
429		 */
430		bi_internal function am(i:int,x:int,w:BigInteger,j:int,c:int,n:int):int {
431			var xl:int = x&0x7fff;
432			var xh:int = x>>15;
433			while(--n >= 0) {
434				var l:int = a[i]&0x7fff;
435				var h:int = a[i++]>>15;
436				var m:int = xh*l + h*xl;
437				l = xl*l + ((m&0x7fff)<<15)+w.a[j]+(c&0x3fffffff);
438				c = (l>>>30)+(m>>>15)+xh*h+(c>>>30);
439				w.a[j++] = l&0x3fffffff;
440			}
441			return c;
442		}
443		/**
444		 * r = this * v, r != this,a (HAC 14.12)
445		 * "this" should be the larger one if appropriate
446		 */
447		bi_internal function multiplyTo(v:BigInteger, r:BigInteger):void {
448			var x:BigInteger = abs();
449			var y:BigInteger = v.abs();
450			var i:int = x.t;
451			r.t = i+y.t;
452			while (--i >= 0) {
453				r.a[i] = 0;
454			}
455			for (i=0; i<y.t; ++i) {
456				r.a[i+x.t] = x.am(0, y.a[i], r, i, 0, x.t);
457			}
458			r.s = 0;
459			r.clamp();
460			if (s!=v.s) {
461				ZERO.subTo(r, r);
462			}
463		}
464		/**
465		 * r = this^2, r != this (HAC 14.16)
466		 */
467		bi_internal function squareTo(r:BigInteger):void {
468			var x:BigInteger = abs();
469			var i:int = r.t = 2*x.t;
470			while (--i>=0) r.a[i] = 0;
471			for (i=0; i<x.t-1; ++i) {
472				var c:int = x.am(i, x.a[i], r, 2*i, 0, 1);
473				if ((r.a[i+x.t] += x.am(i+1, 2*x.a[i], r, 2*i+1, c, x.t-i-1)) >= DV) {
474					r.a[i+x.t] -= DV;
475					r.a[i+x.t+1] = 1;
476				}
477			}
478			if (r.t>0) {
479				r.a[r.t-1] += x.am(i, x.a[i], r, 2*i, 0, 1);
480			}
481			r.s = 0;
482			r.clamp();
483		}
484		/**
485		 * divide this by m, quotient and remainder to q, r (HAC 14.20)
486		 * r != q, this != m. q or r may be null.
487		 */
488		bi_internal function divRemTo(m:BigInteger, q:BigInteger = null, r:BigInteger = null):void {
489			var pm:BigInteger = m.abs();
490			if (pm.t <= 0) return;
491			var pt:BigInteger = abs();
492			if (pt.t < pm.t) {
493				if (q!=null) q.fromInt(0);
494				if (r!=null) copyTo(r);
495				return;
496			}
497			if (r==null) r = nbi();
498			var y:BigInteger = nbi();
499			var ts:int = s;
500			var ms:int = m.s;
501			var nsh:int = DB-nbits(pm.a[pm.t-1]); // normalize modulus
502			if (nsh>0) {
503				pm.lShiftTo(nsh, y);
504				pt.lShiftTo(nsh, r);
505			} else {
506				pm.copyTo(y);
507				pt.copyTo(r);
508			}
509			var ys:int = y.t;
510			var y0:int = y.a[ys-1];
511			if (y0==0) return;
512			var yt:Number = y0*(1<<F1)+((ys>1)?y.a[ys-2]>>F2:0);
513			var d1:Number = FV/yt;
514			var d2:Number = (1<<F1)/yt;
515			var e:Number = 1<<F2;
516			var i:int = r.t;
517			var j:int = i-ys;
518			var t:BigInteger = (q==null)?nbi():q;
519			y.dlShiftTo(j,t);
520			if (r.compareTo(t)>=0) {
521				r.a[r.t++] = 1;
522				r.subTo(t,r);
523			}
524			ONE.dlShiftTo(ys,t);
525			t.subTo(y,y); // "negative" y so we can replace sub with am later.
526			while(y.t<ys) y.(y.t++, 0);
527			while(--j >= 0) {
528				// Estimate quotient digit
529				var qd:int = (r.a[--i]==y0)?DM:Number(r.a[i])*d1+(Number(r.a[i-1])+e)*d2;
530				if ((r.a[i]+= y.am(0, qd, r, j, 0, ys))<qd) { // Try it out
531					y.dlShiftTo(j, t);
532					r.subTo(t,r);
533					while (r.a[i]<--qd) {
534						r.subTo(t,r);
535					}
536				}
537			}
538			if (q!=null) {
539				r.drShiftTo(ys,q);
540				if (ts!=ms) {
541					ZERO.subTo(q,q);
542				}
543			}
544			r.t = ys;
545			r.clamp();
546			if (nsh>0) {
547				r.rShiftTo(nsh, r); // Denormalize remainder
548			}
549			if (ts<0) {
550				ZERO.subTo(r,r);
551			}
552		}
553		/**
554		 * return "-1/this % 2^DB"; useful for Mont. reduction
555		 * justification:
556		 *         xy == 1 (mod n)
557		 *         xy =  1+km
558		 * 	 xy(2-xy) = (1+km)(1-km)
559		 * x[y(2-xy)] =  1-k^2.m^2
560		 * x[y(2-xy)] == 1 (mod m^2)
561		 * if y is 1/x mod m, then y(2-xy) is 1/x mod m^2
562		 * should reduce x and y(2-xy) by m^2 at each step to keep size bounded
563		 * [XXX unit test the living shit out of this.]
564		 */
565		bi_internal function invDigit():int {
566			if (t<1) return 0;
567			var x:int = a[0];
568			if ((x&1)==0) return 0;
569			var y:int = x&3; 							// y == 1/x mod 2^2
570			y = (y*(2-(x&0xf )*y))             &0xf;	// y == 1/x mod 2^4
571			y = (y*(2-(x&0xff)*y))             &0xff;	// y == 1/x mod 2^8
572			y = (y*(2-(((x&0xffff)*y)&0xffff)))&0xffff;	// y == 1/x mod 2^16
573			// last step - calculate inverse mod DV directly;
574			// assumes 16 < DB <= 32 and assumes ability to handle 48-bit ints
575			// XXX 48 bit ints? Whaaaa? is there an implicit float conversion in here?
576			y = (y*(2-x*y%DV))%DV;	// y == 1/x mod 2^dbits
577			// we really want the negative inverse, and -DV < y < DV
578			return (y>0)?DV-y:-y;
579		}
580		/**
581		 * true iff this is even
582		 */
583		bi_internal function isEven():Boolean {
584			return ((t>0)?(a[0]&1):s) == 0;
585		}
586		/**
587		 * this^e, e < 2^32, doing sqr and mul with "r" (HAC 14.79)
588		 */
589		bi_internal function exp(e:int, z:IReduction):BigInteger {
590			if (e > 0xffffffff || e < 1) return ONE;
591			var r:BigInteger = nbi();
592			var r2:BigInteger = nbi();
593			var g:BigInteger = z.convert(this);
594			var i:int = nbits(e)-1;
595			g.copyTo(r);
596			while(--i>=0) {
597				z.sqrTo(r, r2);
598				if ((e&(1<<i))>0) {
599					z.mulTo(r2,g,r);
600				} else {
601					var t:BigInteger = r;
602					r = r2;
603					r2 = t;
604				}
605
606			}
607			return z.revert(r);
608		}
609		bi_internal function intAt(str:String, index:int):int {
610			return parseInt(str.charAt(index), 36);
611		}
612
613
614		protected function nbi():* {
615			return new BigInteger;
616		}
617		/**
618		 * return bigint initialized to value
619		 */
620		public static function nbv(value:int):BigInteger {
621			var bn:BigInteger = new BigInteger;
622			bn.fromInt(value);
623			return bn;
624		}
625
626
627		// Functions above are sufficient for RSA encryption.
628		// The stuff below is useful for decryption and key generation
629
630		public static const lowprimes:Array = [2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,223,227,229,233,239,241,251,257,263,269,271,277,281,283,293,307,311,313,317,331,337,347,349,353,359,367,373,379,383,389,397,401,409,419,421,431,433,439,443,449,457,461,463,467,479,487,491,499,503,509];
631		public static const lplim:int = (1<<26)/lowprimes[lowprimes.length-1];
632
633
634		public function clone():BigInteger {
635			var r:BigInteger = new BigInteger;
636			this.copyTo(r);
637			return r;
638		}
639
640		/**
641		 *
642		 * @return value as integer
643		 *
644		 */
645		public function intValue():int {
646			if (s<0) {
647				if (t==1) {
648					return a[0]-DV;
649				} else if (t==0) {
650					return -1;
651				}
652			} else if (t==1) {
653				return a[0];
654			} else if (t==0) {
655				return 0;
656			}
657			// assumes 16 < DB < 32
658			return  ((a[1]&((1<<(32-DB))-1))<<DB)|a[0];
659		}
660
661		/**
662		 *
663		 * @return value as byte
664		 *
665		 */
666		public function byteValue():int {
667			return (t==0)?s:(a[0]<<24)>>24;
668		}
669
670		/**
671		 *
672		 * @return value as short (assumes DB>=16)
673		 *
674		 */
675		public function shortValue():int {
676			return (t==0)?s:(a[0]<<16)>>16;
677		}
678
679		/**
680		 *
681		 * @param r
682		 * @return x s.t. r^x < DV
683		 *
684		 */
685		protected function chunkSize(r:Number):int {
686			return Math.floor(Math.LN2*DB/Math.log(r));
687		}
688
689		/**
690		 *
691		 * @return 0 if this ==0, 1 if this >0
692		 *
693		 */
694		public function sigNum():int {
695			if (s<0) {
696				return -1;
697			} else if (t<=0 || (t==1 && a[0]<=0)) {
698				return 0;
699			} else{
700				return 1;
701			}
702		}
703
704		/**
705		 *
706		 * @param b: radix to use
707		 * @return a string representing the integer converted to the radix.
708		 *
709		 */
710		protected function toRadix(b:uint=10):String {
711			if (sigNum()==0 || b<2 || b>32) return "0";
712			var cs:int = chunkSize(b);
713			var a:Number = Math.pow(b, cs);
714			var d:BigInteger = nbv(a);
715			var y:BigInteger = nbi();
716			var z:BigInteger = nbi();
717			var r:String = "";
718			divRemTo(d, y, z);
719			while (y.sigNum()>0) {
720				r = (a+z.intValue()).toString(b).substr(1) + r;
721				y.divRemTo(d,y,z);
722			}
723			return z.intValue().toString(b) + r;
724		}
725
726		/**
727		 *
728		 * @param s a string to convert from using radix.
729		 * @param b a radix
730		 *
731		 */
732		protected function fromRadix(s:String, b:int = 10):void {
733			fromInt(0);
734			var cs:int = chunkSize(b);
735			var d:Number = Math.pow(b, cs);
736			var mi:Boolean = false;
737			var j:int = 0;
738			var w:int = 0;
739			for (var i:int=0;i<s.length;++i) {
740				var x:int = intAt(s, i);
741				if (x<0) {
742					if (s.charAt(i) == "-" && sigNum() == 0) {
743						mi = true;
744					}
745					continue;
746				}
747				w = b*w+x;
748				if (++j >= cs) {
749					dMultiply(d);
750					dAddOffset(w,0);
751					j=0;
752					w=0;
753				}
754			}
755			if (j>0) {
756				dMultiply(Math.pow(b,j));
757				dAddOffset(w,0);
758			}
759			if (mi) {
760				BigInteger.ZERO.subTo(this, this);
761			}
762		}
763
764		// XXX function fromNumber not written yet.
765
766		/**
767		 *
768		 * @return a byte array.
769		 *
770		 */
771		public function toByteArray():ByteArray {
772			var i:int = t;
773			var r:ByteArray = new ByteArray;
774			r[0] = s;
775			var p:int = DB-(i*DB)%8;
776			var d:int;
777			var k:int=0;
778			if (i-->0) {
779				if (p<DB && (d=a[i]>>p)!=(s&DM)>>p) {
780					r[k++] = d|(s<<(DB-p));
781				}
782				while (i>=0) {
783					if(p<8) {
784						d = (a[i]&((1<<p)-1))<<(8-p);
785						d|= a[--i]>>(p+=DB-8);
786					} else {
787						d = (a[i]>>(p-=8))&0xff;
788						if (p<=0) {
789							p += DB;
790							--i;
791						}
792					}
793					if ((d&0x80)!=0) d|=-256;
794					if (k==0 && (s&0x80)!=(d&0x80)) ++k;
795					if (k>0 || d!=s) r[k++] = d;
796				}
797			}
798			return r;
799		}
800
801		public function equals(a:BigInteger):Boolean {
802			return compareTo(a)==0;
803		}
804		public function min(a:BigInteger):BigInteger {
805			return (compareTo(a)<0)?this:a;
806		}
807		public function max(a:BigInteger):BigInteger {
808			return (compareTo(a)>0)?this:a;
809		}
810
811		/**
812		 *
813		 * @param a	a BigInteger to perform the operation with
814		 * @param op a Function implementing the operation
815		 * @param r a BigInteger to store the result of the operation
816		 *
817		 */
818		protected function bitwiseTo(a:BigInteger, op:Function, r:BigInteger):void {
819			var i:int;
820			var f:int;
821			var m:int = Math.min(a.t, t);
822			for (i=0; i<m; ++i) {
823				r.a[i] = op(this.a[i],a.a[i]);
824			}
825			if (a.t<t) {
826				f = a.s&DM;
827				for (i=m;i<t;++i) {
828					r.a[i] = op(this.a[i],f);
829				}
830				r.t = t;
831			} else {
832				f = s&DM;
833				for (i=m;i<a.t;++i) {
834					r.a[i] = op(f,a.a[i]);
835				}
836				r.t = a.t;
837			}
838			r.s = op(s, a.s);
839			r.clamp();
840		}
841
842		private function op_and(x:int, y:int):int {return x&y;}
843		public function and(a:BigInteger):BigInteger {
844			var r:BigInteger = new BigInteger;
845			bitwiseTo(a, op_and, r);
846			return r;
847		}
848
849		private function op_or(x:int, y:int):int {return x|y;}
850		public function or(a:BigInteger):BigInteger {
851			var r:BigInteger = new BigInteger;
852			bitwiseTo(a, op_or, r);
853			return r;
854		}
855
856		private function op_xor(x:int, y:int):int {return x^y;}
857		public function xor(a:BigInteger):BigInteger {
858			var r:BigInteger = new BigInteger;
859			bitwiseTo(a, op_xor, r);
860			return r;
861		}
862
863		private function op_andnot(x:int, y:int):int { return x&~y;}
864		public function andNot(a:BigInteger):BigInteger {
865			var r:BigInteger = new BigInteger;
866			bitwiseTo(a, op_andnot, r);
867			return r;
868		}
869
870		public function not():BigInteger {
871			var r:BigInteger = new BigInteger;
872			for (var i:int=0;i<t;++i) {
873				r[i] = DM&~a[i];
874			}
875			r.t = t;
876			r.s = ~s;
877			return r;
878		}
879
880		public function shiftLeft(n:int):BigInteger {
881			var r:BigInteger = new BigInteger;
882			if (n<0) {
883				rShiftTo(-n, r);
884			} else {
885				lShiftTo(n, r);
886			}
887			return r;
888		}
889		public function shiftRight(n:int):BigInteger {
890			var r:BigInteger = new BigInteger;
891			if (n<0) {
892				lShiftTo(-n, r);
893			} else {
894				rShiftTo(n, r);
895			}
896			return r;
897		}
898
899		/**
900		 *
901		 * @param x
902		 * @return index of lowet 1-bit in x, x < 2^31
903		 *
904		 */
905		private function lbit(x:int):int {
906			if (x==0) return -1;
907			var r:int = 0;
908			if ((x&0xffff)==0) { x>>= 16; r += 16; }
909			if ((x&0xff) == 0) { x>>=  8; r +=  8; }
910			if ((x&0xf)  == 0) { x>>=  4; r +=  4; }
911			if ((x&0x3)  == 0) { x>>=  2; r +=  2; }
912			if ((x&0x1)  == 0) ++r;
913			return r;
914		}
915
916		/**
917		 *
918		 * @return index of lowest 1-bit (or -1 if none)
919		 *
920		 */
921		public function getLowestSetBit():int {
922			for (var i:int=0;i<t;++i) {
923				if (a[i]!=0) return i*DB+lbit(a[i]);
924			}
925			if (s<0) return t*DB;
926			return -1;
927		}
928
929		/**
930		 *
931		 * @param x
932		 * @return number of 1 bits in x
933		 *
934		 */
935		private function cbit(x:int):int {
936			var r:uint =0;
937			while (x!=0) { x &= x-1; ++r }
938			return r;
939		}
940
941		/**
942		 *
943		 * @return number of set bits
944		 *
945		 */
946		public function bitCount():int {
947			var r:int=0;
948			var x:int = s&DM;
949			for (var i:int=0;i<t;++i) {
950				r += cbit(a[i]^x);
951			}
952			return r;
953		}
954
955		/**
956		 *
957		 * @param n
958		 * @return true iff nth bit is set
959		 *
960		 */
961		public function testBit(n:int):Boolean {
962			var j:int = Math.floor(n/DB);
963			if (j>=t) {
964				return s!=0;
965			}
966			return ((a[j]&(1<<(n%DB)))!=0);
967		}
968
969		/**
970		 *
971		 * @param n
972		 * @param op
973		 * @return this op (1<<n)
974		 *
975		 */
976		protected function changeBit(n:int,op:Function):BigInteger {
977			var r:BigInteger = BigInteger.ONE.shiftLeft(n);
978			bitwiseTo(r, op, r);
979			return r;
980		}
981
982		/**
983		 *
984		 * @param n
985		 * @return this | (1<<n)
986		 *
987		 */
988		public function setBit(n:int):BigInteger { return changeBit(n, op_or); }
989
990		/**
991		 *
992		 * @param n
993		 * @return this & ~(1<<n)
994		 *
995		 */
996		public function clearBit(n:int):BigInteger { return changeBit(n, op_andnot); }
997
998		/**
999		 *
1000		 * @param n
1001		 * @return this ^ (1<<n)
1002		 *
1003		 */
1004		public function flipBit(n:int):BigInteger { return changeBit(n, op_xor); }
1005
1006		/**
1007		 *
1008		 * @param a
1009		 * @param r = this + a
1010		 *
1011		 */
1012		protected function addTo(a:BigInteger, r:BigInteger):void {
1013			var i:int = 0;
1014			var c:int = 0;
1015			var m:int = Math.min(a.t, t);
1016			while (i<m) {
1017				c += this.a[i] + a.a[i];
1018				r.a[i++] = c&DM;
1019				c>>=DB;
1020			}
1021			if (a.t < t) {
1022				c += a.s;
1023				while (i<t) {
1024					c += this.a[i];
1025					r.a[i++] = c&DM;
1026					c >>= DB;
1027				}
1028				c += s;
1029			} else {
1030				c += s;
1031				while (i<a.t) {
1032					c += a.a[i];
1033					r.a[i++] = c&DM;
1034					c >>= DB;
1035				}
1036				c += a.s;
1037			}
1038			r.s = (c<0)?-1:0;
1039			if (c>0) {
1040				r.a[i++] = c;
1041			} else if (c<-1) {
1042				r.a[i++] = DV+c;
1043			}
1044			r.t = i;
1045			r.clamp();
1046		}
1047
1048		/**
1049		 *
1050		 * @param a
1051		 * @return this + a
1052		 *
1053		 */
1054		public function add(a:BigInteger):BigInteger {
1055			var r:BigInteger = new BigInteger;
1056			addTo(a,r);
1057			return r;
1058		}
1059
1060		/**
1061		 *
1062		 * @param a
1063		 * @return this - a
1064		 *
1065		 */
1066		public function subtract(a:BigInteger):BigInteger {
1067			var r:BigInteger = new BigInteger;
1068			subTo(a,r);
1069			return r;
1070		}
1071
1072		/**
1073		 *
1074		 * @param a
1075		 * @return this * a
1076		 *
1077		 */
1078		public function multiply(a:BigInteger):BigInteger {
1079			var r:BigInteger = new BigInteger;
1080			multiplyTo(a,r);
1081			return r;
1082		}
1083
1084		/**
1085		 *
1086		 * @param a
1087		 * @return this / a
1088		 *
1089		 */
1090		public function divide(a:BigInteger):BigInteger {
1091			var r:BigInteger = new BigInteger;
1092			divRemTo(a, r, null);
1093			return r;
1094		}
1095
1096		public function remainder(a:BigInteger):BigInteger {
1097			var r:BigInteger = new BigInteger;
1098			divRemTo(a, null, r);
1099			return r;
1100		}
1101
1102		/**
1103		 *
1104		 * @param a
1105		 * @return [this/a, this%a]
1106		 *
1107		 */
1108		public function divideAndRemainder(a:BigInteger):Array {
1109			var q:BigInteger = new BigInteger;
1110			var r:BigInteger = new BigInteger;
1111			divRemTo(a, q, r);
1112			return [q,r];
1113		}
1114
1115		/**
1116		 *
1117		 * this *= n, this >=0, 1 < n < DV
1118		 *
1119		 * @param n
1120		 *
1121		 */
1122		bi_internal function dMultiply(n:int):void {
1123			a[t] = am(0, n-1, this, 0, 0, t);
1124			++t;
1125			clamp();
1126		}
1127
1128		/**
1129		 *
1130		 * this += n << w words, this >= 0
1131		 *
1132		 * @param n
1133		 * @param w
1134		 *
1135		 */
1136		bi_internal function dAddOffset(n:int, w:int):void {
1137			while (t<=w) {
1138				a[t++] = 0;
1139			}
1140			a[w] += n;
1141			while (a[w] >= DV) {
1142				a[w] -= DV;
1143				if (++w >= t) {
1144					a[t++] = 0;
1145				}
1146				++a[w];
1147			}
1148		}
1149
1150		/**
1151		 *
1152		 * @param e
1153		 * @return this^e
1154		 *
1155		 */
1156		public function pow(e:int):BigInteger {
1157			return exp(e, new NullReduction);
1158		}
1159
1160		/**
1161		 *
1162		 * @param a
1163		 * @param n
1164		 * @param r = lower n words of "this * a", a.t <= n
1165		 *
1166		 */
1167		bi_internal function multiplyLowerTo(a:BigInteger, n:int, r:BigInteger):void {
1168			var i:int = Math.min(t+a.t, n);
1169			r.s = 0; // assumes a, this >= 0
1170			r.t = i;
1171			while (i>0) {
1172				r.a[--i]=0;
1173			}
1174			var j:int;
1175			for (j=r.t-t;i<j;++i) {
1176				r.a[i+t] = am(0, a.a[i], r, i, 0, t);
1177			}
1178			for (j=Math.min(a.t,n);i<j;++i) {
1179				am(0, a.a[i], r, i, 0, n-i);
1180			}
1181			r.clamp();
1182		}
1183
1184		/**
1185		 *
1186		 * @param a
1187		 * @param n
1188		 * @param r = "this * a" without lower n words, n > 0
1189		 *
1190		 */
1191		bi_internal function multiplyUpperTo(a:BigInteger, n:int, r:BigInteger):void {
1192			--n;
1193			var i:int = r.t = t+a.t-n;
1194			r.s = 0; // assumes a,this >= 0
1195			while (--i>=0) {
1196				r.a[i] = 0;
1197			}
1198			for (i=Math.max(n-t,0);i<a.t;++i) {
1199				r.a[t+i-n] = am(n-i, a.a[i], r, 0, 0, t+i-n);
1200			}
1201			r.clamp();
1202			r.drShiftTo(1,r);
1203		}
1204
1205		/**
1206		 *
1207		 * @param e
1208		 * @param m
1209		 * @return this^e % m (HAC 14.85)
1210		 *
1211		 */
1212		public function modPow(e:BigInteger, m:BigInteger):BigInteger {
1213			var i:int = e.bitLength();
1214			var k:int;
1215			var r:BigInteger = nbv(1);
1216			var z:IReduction;
1217
1218			if (i<=0) {
1219				return r;
1220			} else if (i<18) {
1221				k=1;
1222			} else if (i<48) {
1223				k=3;
1224			} else if (i<144) {
1225				k=4;
1226			} else if (i<768) {
1227				k=5;
1228			} else {
1229				k=6;
1230			}
1231			if (i<8) {
1232				z = new ClassicReduction(m);
1233			} else if (m.isEven()) {
1234				z = new BarrettReduction(m);
1235			} else {
1236				z = new MontgomeryReduction(m);
1237			}
1238			// precomputation
1239			var g:Array = [];
1240			var n:int = 3;
1241			var k1:int = k-1;
1242			var km:int = (1<<k)-1;
1243			g[1] = z.convert(this);
1244			if (k > 1) {
1245				var g2:BigInteger = new BigInteger;
1246				z.sqrTo(g[1], g2);
1247				while (n<=km) {
1248					g[n] = new BigInteger;
1249					z.mulTo(g2, g[n-2], g[n]);
1250					n += 2;
1251				}
1252			}
1253
1254			var j:int = e.t-1;
1255			var w:int;
1256			var is1:Boolean = true;
1257			var r2:BigInteger = new BigInteger;
1258			var t:BigInteger;
1259			i = nbits(e.a[j])-1;
1260			while (j>=0) {
1261				if (i>=k1) {
1262					w = (e.a[j]>>(i-k1))&km;
1263				} else {
1264					w = (e.a[j]&((1<<(i+1))-1))<<(k1-i);
1265					if (j>0) {
1266						w |= e.a[j-1]>>(DB+i-k1);
1267					}
1268				}
1269				n = k;
1270				while ((w&1)==0) {
1271					w >>= 1;
1272					--n;
1273				}
1274				if ((i -= n) <0) {
1275					i += DB;
1276					--j;
1277				}
1278				if (is1) { // ret == 1, don't bother squaring or multiplying it
1279					g[w].copyTo(r);
1280					is1 = false;
1281				} else {
1282					while (n>1) {
1283						z.sqrTo(r, r2);
1284						z.sqrTo(r2, r);
1285						n -= 2;
1286					}
1287					if (n>0) {
1288						z.sqrTo(r, r2);
1289					} else {
1290						t = r;
1291						r = r2;
1292						r2 = t;
1293					}
1294					z.mulTo(r2, g[w], r);
1295				}
1296				while (j>=0 && (e.a[j]&(1<<i)) == 0) {
1297					z.sqrTo(r, r2);
1298					t = r;
1299					r = r2;
1300					r2 = t;
1301					if (--i<0) {
1302						i = DB-1;
1303						--j;
1304					}
1305
1306				}
1307			}
1308			return z.revert(r);
1309		}
1310
1311		/**
1312		 *
1313		 * @param a
1314		 * @return gcd(this, a) (HAC 14.54)
1315		 *
1316		 */
1317		public function gcd(a:BigInteger):BigInteger {
1318			var x:BigInteger = (s<0)?negate():clone();
1319			var y:BigInteger = (a.s<0)?a.negate():a.clone();
1320			if (x.compareTo(y)<0) {
1321				var t:BigInteger=x;
1322				x=y;
1323				y=t;
1324			}
1325			var i:int = x.getLowestSetBit();
1326			var g:int = y.getLowestSetBit();
1327			if (g<0) return x;
1328			if (i<g) g= i;
1329			if (g>0) {
1330				x.rShiftTo(g, x);
1331				y.rShiftTo(g, y);
1332			}
1333			while (x.sigNum()>0) {
1334				if ((i = x.getLowestSetBit()) >0) {
1335					x.rShiftTo(i, x);
1336				}
1337				if ((i = y.getLowestSetBit()) >0) {
1338					y.rShiftTo(i, y);
1339				}
1340				if (x.compareTo(y) >= 0) {
1341					x.subTo(y, x);
1342					x.rShiftTo(1, x);
1343				} else {
1344					y.subTo(x, y);
1345					y.rShiftTo(1, y);
1346				}
1347			}
1348			if (g>0) {
1349				y.lShiftTo(g, y);
1350			}
1351			return y;
1352		}
1353
1354		/**
1355		 *
1356		 * @param n
1357		 * @return this % n, n < 2^DB
1358		 *
1359		 */
1360		protected function modInt(n:int):int {
1361			if (n<=0) return 0;
1362			var d:int = DV%n;
1363			var r:int = (s<0)?n-1:0;
1364			if (t>0) {
1365				if (d==0) {
1366					r = a[0]%n;
1367				} else {
1368					for (var i:int=t-1;i>=0;--i) {
1369						r = (d*r+a[i])%n;
1370					}
1371				}
1372			}
1373			return r;
1374		}
1375
1376		/**
1377		 *
1378		 * @param m
1379		 * @return 1/this %m (HAC 14.61)
1380		 *
1381		 */
1382		public function modInverse(m:BigInteger):BigInteger {
1383			var ac:Boolean = m.isEven();
1384			if ((isEven()&&ac) || m.sigNum()==0) {
1385				return BigInteger.ZERO;
1386			}
1387			var u:BigInteger = m.clone();
1388			var v:BigInteger = clone();
1389			var a:BigInteger = nbv(1);
1390			var b:BigInteger = nbv(0);
1391			var c:BigInteger = nbv(0);
1392			var d:BigInteger = nbv(1);
1393			while (u.sigNum()!=0) {
1394				while (u.isEven()) {
1395					u.rShiftTo(1,u);
1396					if (ac) {
1397						if (!a.isEven() || !b.isEven()) {
1398							a.addTo(this,a);
1399							b.subTo(m,b);
1400						}
1401						a.rShiftTo(1,a);
1402					} else if (!b.isEven()) {
1403						b.subTo(m,b);
1404					}
1405					b.rShiftTo(1,b);
1406				}
1407				while (v.isEven()) {
1408					v.rShiftTo(1,v);
1409					if (ac) {
1410						if (!c.isEven() || !d.isEven()) {
1411							c.addTo(this,c);
1412							d.subTo(m,d);
1413						}
1414						c.rShiftTo(1,c);
1415					} else if (!d.isEven()) {
1416						d.subTo(m,d);
1417					}
1418					d.rShiftTo(1,d);
1419				}
1420				if (u.compareTo(v)>=0) {
1421					u.subTo(v,u);
1422					if (ac) {
1423						a.subTo(c,a);
1424					}
1425					b.subTo(d,b);
1426				} else {
1427					v.subTo(u,v);
1428					if (ac) {
1429						c.subTo(a,c);
1430					}
1431					d.subTo(b,d);
1432				}
1433			}
1434			if (v.compareTo(BigInteger.ONE) != 0) {
1435				return BigInteger.ZERO;
1436			}
1437			if (d.compareTo(m) >= 0) {
1438				return d.subtract(m);
1439			}
1440			if (d.sigNum()<0) {
1441				d.addTo(m,d);
1442			} else {
1443				return d;
1444			}
1445			if (d.sigNum()<0) {
1446				return d.add(m);
1447			} else {
1448				return d;
1449			}
1450		}
1451
1452		/**
1453		 *
1454		 * @param t
1455		 * @return primality with certainty >= 1-.5^t
1456		 *
1457		 */
1458		public function isProbablePrime(t:int):Boolean {
1459			var i:int;
1460			var x:BigInteger = abs();
1461			if (x.t == 1 && x.a[0]<=lowprimes[lowprimes.length-1]) {
1462				for (i=0;i<lowprimes.length;++i) {
1463					if (x[0]==lowprimes[i]) return true;
1464				}
1465				return false;
1466			}
1467			if (x.isEven()) return false;
1468			i = 1;
1469			while (i<lowprimes.length) {
1470				var m:int = lowprimes[i];
1471				var j:int = i+1;
1472				while (j<lowprimes.length && m<lplim) {
1473					m *= lowprimes[j++];
1474				}
1475				m = x.modInt(m);
1476				while (i<j) {
1477					if (m%lowprimes[i++]==0) {
1478						return false;
1479					}
1480				}
1481			}
1482			return x.millerRabin(t);
1483		}
1484
1485		/**
1486		 *
1487		 * @param t
1488		 * @return true if probably prime (HAC 4.24, Miller-Rabin)
1489		 *
1490		 */
1491		protected function millerRabin(t:int):Boolean {
1492			var n1:BigInteger = subtract(BigInteger.ONE);
1493			var k:int = n1.getLowestSetBit();
1494			if (k<=0) {
1495				return false;
1496			}
1497			var r:BigInteger = n1.shiftRight(k);
1498			t = (t+1)>>1;
1499			if (t>lowprimes.length) {
1500				t = lowprimes.length;
1501			}
1502			var a:BigInteger = new BigInteger;
1503			for (var i:int=0;i<t;++i) {
1504				a.fromInt(lowprimes[i]);
1505				var y:BigInteger = a.modPow(r, this);
1506				if (y.compareTo(BigInteger.ONE)!=0 && y.compareTo(n1)!=0) {
1507					var j:int = 1;
1508					while (j++<k && y.compareTo(n1)!=0) {
1509						y = y.modPowInt(2, this);
1510						if (y.compareTo(BigInteger.ONE)==0) {
1511							return false;
1512						}
1513					}
1514					if (y.compareTo(n1)!=0) {
1515						return false;
1516					}
1517				}
1518			}
1519			return true;
1520		}
1521
1522		/**
1523		 * Tweak our BigInteger until it looks prime enough
1524		 *
1525		 * @param bits
1526		 * @param t
1527		 *
1528		 */
1529		public function primify(bits:int, t:int):void {
1530			if (!testBit(bits-1)) {	// force MSB set
1531				bitwiseTo(BigInteger.ONE.shiftLeft(bits-1), op_or, this);
1532			}
1533			if (isEven()) {
1534				dAddOffset(1,0);	// force odd
1535			}
1536			while (!isProbablePrime(t)) {
1537				dAddOffset(2,0);
1538				while(bitLength()>bits) subTo(BigInteger.ONE.shiftLeft(bits-1),this);
1539			}
1540		}
1541
1542	}
1543}
```