4 * An ActionScript 3 implementation of BigInteger (light version)
\r
5 * Copyright (c) 2007 Henri Torgemane
\r
8 * The jsbn library, Copyright (c) 2003-2005 Tom Wu
\r
10 * See LICENSE.txt for full license information.
\r
12 package com.hurlant.math
\r
15 import com.hurlant.crypto.prng.Random;
\r
16 import com.hurlant.util.Hex;
\r
17 import com.hurlant.util.Memory;
\r
19 import flash.utils.ByteArray;
\r
20 use namespace bi_internal;
\r
22 public class BigInteger
\r
24 public static const DB:int = 30; // number of significant bits per chunk
\r
25 public static const DV:int = (1<<DB);
\r
26 public static const DM:int = (DV-1); // Max value in a chunk
\r
28 public static const BI_FP:int = 52;
\r
29 public static const FV:Number = Math.pow(2, BI_FP);
\r
30 public static const F1:int = BI_FP - DB;
\r
31 public static const F2:int = 2*DB - BI_FP;
\r
33 public static const ZERO:BigInteger = nbv(0);
\r
34 public static const ONE:BigInteger = nbv(1);
\r
36 /*bi_internal */public var t:int; // number of chunks.
\r
37 bi_internal var s:int; // sign
\r
38 bi_internal var a:Array; // chunks
\r
43 * @param radix WARNING: If value is ByteArray, this holds the number of bytes to use.
\r
47 public function BigInteger(value:* = null, radix:int = 0, unsigned:Boolean = false) {
\r
49 if (value is String) {
\r
50 if (radix&&radix!=16) throw new Error("BigInteger construction with radix!=16 is not supported.");
\r
51 value = Hex.toArray(value);
\r
54 if (value is ByteArray) {
\r
55 var array:ByteArray = value as ByteArray;
\r
56 var length:int = radix || (array.length - array.position);
\r
57 fromArray(array, length, unsigned);
\r
60 public function dispose():void {
\r
61 var r:Random = new Random;
\r
62 for (var i:uint=0;i<a.length;i++) {
\r
63 a[i] = r.nextByte();
\r
72 public function toString(radix:Number=16):String {
\r
73 if (s<0) return "-"+negate().toString(radix);
\r
79 case 16: k=4; break;
\r
80 case 32: k=5; break;
\r
82 // return toRadix(radix);
\r
84 var km:int = (1<<k)-1;
\r
86 var m:Boolean = false;
\r
89 var p:int = DB-(i*DB)%k;
\r
91 if (p<DB && (d=a[i]>>p)>0) {
\r
97 d = (a[i]&((1<<p)-1))<<(k-p);
\r
98 d|= a[--i]>>(p+=DB-k);
\r
100 d = (a[i]>>(p-=k))&km;
\r
110 r += d.toString(36);
\r
116 public function toArray(array:ByteArray):uint {
\r
118 const km:int = (1<<8)-1;
\r
121 var p:int = DB-(i*DB)%k;
\r
122 var m:Boolean = false;
\r
125 if (p<DB && (d=a[i]>>p)>0) {
\r
127 array.writeByte(d);
\r
132 d = (a[i]&((1<<p)-1))<<(k-p);
\r
133 d|= a[--i]>>(p+=DB-k);
\r
135 d = (a[i]>>(p-=k))&km;
\r
145 array.writeByte(d);
\r
153 * best-effort attempt to fit into a Number.
\r
154 * precision can be lost if it just can't fit.
\r
156 public function valueOf():Number {
\r
158 return -negate().valueOf();
\r
160 var coef:Number = 1;
\r
161 var value:Number = 0;
\r
162 for (var i:uint=0;i<t;i++) {
\r
163 value += a[i]*coef;
\r
171 public function negate():BigInteger {
\r
172 var r:BigInteger = nbi();
\r
173 ZERO.subTo(this, r);
\r
179 public function abs():BigInteger {
\r
180 return (s<0)?negate():this;
\r
183 * return + if this > v, - if this < v, 0 if equal
\r
185 public function compareTo(v:BigInteger):int {
\r
186 var r:int = s - v.s;
\r
197 if (r != 0) return r;
\r
202 * returns bit length of the integer x
\r
204 bi_internal function nbits(x:int):int {
\r
207 if ((t=x>>>16) != 0) { x = t; r += 16; }
\r
208 if ((t=x>>8) != 0) { x = t; r += 8; }
\r
209 if ((t=x>>4) != 0) { x = t; r += 4; }
\r
210 if ((t=x>>2) != 0) { x = t; r += 2; }
\r
211 if ((t=x>>1) != 0) { x = t; r += 1; }
\r
215 * returns the number of bits in this
\r
217 public function bitLength():int {
\r
218 if (t<=0) return 0;
\r
219 return DB*(t-1)+nbits(a[t-1]^(s&DM));
\r
227 public function mod(v:BigInteger):BigInteger {
\r
228 var r:BigInteger = nbi();
\r
229 abs().divRemTo(v,null,r);
\r
230 if (s<0 && r.compareTo(ZERO)>0) {
\r
236 * this^e % m, 0 <= e < 2^32
\r
238 public function modPowInt(e:int, m:BigInteger):BigInteger {
\r
240 if (e<256 || m.isEven()) {
\r
241 z = new ClassicReduction(m);
\r
243 z = new MontgomeryReduction(m);
\r
251 bi_internal function copyTo(r:BigInteger):void {
\r
252 for (var i:int = t-1; i>=0; --i) {
\r
259 * set from integer value "value", -DV <= value < DV
\r
261 bi_internal function fromInt(value:int):void {
\r
263 s = (value<0)?-1:0;
\r
266 } else if (value<-1) {
\r
273 * set from ByteArray and length,
\r
274 * starting a current position
\r
275 * If length goes beyond the array, pad with zeroes.
\r
277 bi_internal function fromArray(value:ByteArray, length:int, unsigned:Boolean = false):void {
\r
278 var p:int = value.position;
\r
279 var i:int = p+length;
\r
285 var x:int = i<value.length?value[i]:0;
\r
288 } else if (sh+k > DB) {
\r
289 a[t-1] |= (x&((1<<(DB-sh))-1))<<sh;
\r
290 a[t++] = x>>(DB-sh);
\r
295 if (sh >= DB) sh -= DB;
\r
297 if (!unsigned && (value[0]&0x80)==0x80) {
\r
300 a[t-1] |= ((1<<(DB-sh))-1)<<sh;
\r
304 value.position = Math.min(p+length,value.length);
\r
307 * clamp off excess high words
\r
309 bi_internal function clamp():void {
\r
311 while (t>0 && a[t-1]==c) {
\r
318 bi_internal function dlShiftTo(n:int, r:BigInteger):void {
\r
320 for (i=t-1; i>=0; --i) {
\r
323 for (i=n-1; i>=0; --i) {
\r
332 bi_internal function drShiftTo(n:int, r:BigInteger):void {
\r
334 for (i=n; i<t; ++i) {
\r
337 r.t = Math.max(t-n,0);
\r
343 bi_internal function lShiftTo(n:int, r:BigInteger):void {
\r
345 var cbs:int = DB-bs;
\r
346 var bm:int = (1<<cbs)-1;
\r
348 var c:int = (s<<bs)&DM;
\r
350 for (i=t-1; i>=0; --i) {
\r
351 r.a[i+ds+1] = (a[i]>>cbs)|c;
\r
354 for (i=ds-1; i>=0; --i) {
\r
365 bi_internal function rShiftTo(n:int, r:BigInteger):void {
\r
373 var cbs:int = DB-bs;
\r
374 var bm:int = (1<<bs)-1;
\r
375 r.a[0] = a[ds]>>bs;
\r
377 for (i=ds+1; i<t; ++i) {
\r
378 r.a[i-ds-1] |= (a[i]&bm)<<cbs;
\r
379 r.a[i-ds] = a[i]>>bs;
\r
382 r.a[t-ds-1] |= (s&bm)<<cbs;
\r
390 bi_internal function subTo(v:BigInteger, r:BigInteger):void {
\r
393 var m:int = Math.min(v.t, t);
\r
395 c += a[i] - v.a[i];
\r
426 * am: Compute w_j += (x*this_i), propagates carries,
\r
427 * c is initial carry, returns final carry.
\r
428 * c < 3*dvalue, x < 2*dvalue, this_i < dvalue
\r
430 bi_internal function am(i:int,x:int,w:BigInteger,j:int,c:int,n:int):int {
\r
431 var xl:int = x&0x7fff;
\r
432 var xh:int = x>>15;
\r
434 var l:int = a[i]&0x7fff;
\r
435 var h:int = a[i++]>>15;
\r
436 var m:int = xh*l + h*xl;
\r
437 l = xl*l + ((m&0x7fff)<<15)+w.a[j]+(c&0x3fffffff);
\r
438 c = (l>>>30)+(m>>>15)+xh*h+(c>>>30);
\r
439 w.a[j++] = l&0x3fffffff;
\r
444 * r = this * v, r != this,a (HAC 14.12)
\r
445 * "this" should be the larger one if appropriate
\r
447 bi_internal function multiplyTo(v:BigInteger, r:BigInteger):void {
\r
448 var x:BigInteger = abs();
\r
449 var y:BigInteger = v.abs();
\r
455 for (i=0; i<y.t; ++i) {
\r
456 r.a[i+x.t] = x.am(0, y.a[i], r, i, 0, x.t);
\r
465 * r = this^2, r != this (HAC 14.16)
\r
467 bi_internal function squareTo(r:BigInteger):void {
\r
468 var x:BigInteger = abs();
\r
469 var i:int = r.t = 2*x.t;
\r
470 while (--i>=0) r.a[i] = 0;
\r
471 for (i=0; i<x.t-1; ++i) {
\r
472 var c:int = x.am(i, x.a[i], r, 2*i, 0, 1);
\r
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) {
\r
479 r.a[r.t-1] += x.am(i, x.a[i], r, 2*i, 0, 1);
\r
485 * divide this by m, quotient and remainder to q, r (HAC 14.20)
\r
486 * r != q, this != m. q or r may be null.
\r
488 bi_internal function divRemTo(m:BigInteger, q:BigInteger = null, r:BigInteger = null):void {
\r
489 var pm:BigInteger = m.abs();
\r
490 if (pm.t <= 0) return;
\r
491 var pt:BigInteger = abs();
\r
493 if (q!=null) q.fromInt(0);
\r
494 if (r!=null) copyTo(r);
\r
497 if (r==null) r = nbi();
\r
498 var y:BigInteger = nbi();
\r
501 var nsh:int = DB-nbits(pm.a[pm.t-1]); // normalize modulus
\r
503 pm.lShiftTo(nsh, y);
\r
504 pt.lShiftTo(nsh, r);
\r
510 var y0:int = y.a[ys-1];
\r
512 var yt:Number = y0*(1<<F1)+((ys>1)?y.a[ys-2]>>F2:0);
\r
513 var d1:Number = FV/yt;
\r
514 var d2:Number = (1<<F1)/yt;
\r
515 var e:Number = 1<<F2;
\r
518 var t:BigInteger = (q==null)?nbi():q;
\r
520 if (r.compareTo(t)>=0) {
\r
524 ONE.dlShiftTo(ys,t);
\r
525 t.subTo(y,y); // "negative" y so we can replace sub with am later.
\r
526 while(y.t<ys) y.(y.t++, 0);
\r
528 // Estimate quotient digit
\r
529 var qd:int = (r.a[--i]==y0)?DM:Number(r.a[i])*d1+(Number(r.a[i-1])+e)*d2;
\r
530 if ((r.a[i]+= y.am(0, qd, r, j, 0, ys))<qd) { // Try it out
\r
533 while (r.a[i]<--qd) {
\r
547 r.rShiftTo(nsh, r); // Denormalize remainder
\r
554 * return "-1/this % 2^DB"; useful for Mont. reduction
\r
558 * xy(2-xy) = (1+km)(1-km)
\r
559 * x[y(2-xy)] = 1-k^2.m^2
\r
560 * x[y(2-xy)] == 1 (mod m^2)
\r
561 * if y is 1/x mod m, then y(2-xy) is 1/x mod m^2
\r
562 * should reduce x and y(2-xy) by m^2 at each step to keep size bounded
\r
563 * [XXX unit test the living shit out of this.]
\r
565 bi_internal function invDigit():int {
\r
568 if ((x&1)==0) return 0;
\r
569 var y:int = x&3; // y == 1/x mod 2^2
\r
570 y = (y*(2-(x&0xf )*y)) &0xf; // y == 1/x mod 2^4
\r
571 y = (y*(2-(x&0xff)*y)) &0xff; // y == 1/x mod 2^8
\r
572 y = (y*(2-(((x&0xffff)*y)&0xffff)))&0xffff; // y == 1/x mod 2^16
\r
573 // last step - calculate inverse mod DV directly;
\r
574 // assumes 16 < DB <= 32 and assumes ability to handle 48-bit ints
\r
575 // XXX 48 bit ints? Whaaaa? is there an implicit float conversion in here?
\r
576 y = (y*(2-x*y%DV))%DV; // y == 1/x mod 2^dbits
\r
577 // we really want the negative inverse, and -DV < y < DV
\r
578 return (y>0)?DV-y:-y;
\r
581 * true iff this is even
\r
583 bi_internal function isEven():Boolean {
\r
584 return ((t>0)?(a[0]&1):s) == 0;
\r
587 * this^e, e < 2^32, doing sqr and mul with "r" (HAC 14.79)
\r
589 bi_internal function exp(e:int, z:IReduction):BigInteger {
\r
590 if (e > 0xffffffff || e < 1) return ONE;
\r
591 var r:BigInteger = nbi();
\r
592 var r2:BigInteger = nbi();
\r
593 var g:BigInteger = z.convert(this);
\r
594 var i:int = nbits(e)-1;
\r
598 if ((e&(1<<i))>0) {
\r
601 var t:BigInteger = r;
\r
607 return z.revert(r);
\r
609 bi_internal function intAt(str:String, index:int):int {
\r
610 return parseInt(str.charAt(index), 36);
\r
614 protected function nbi():* {
\r
615 return new BigInteger;
\r
618 * return bigint initialized to value
\r
620 public static function nbv(value:int):BigInteger {
\r
621 var bn:BigInteger = new BigInteger;
\r
627 // Functions above are sufficient for RSA encryption.
\r
628 // The stuff below is useful for decryption and key generation
\r
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];
\r
631 public static const lplim:int = (1<<26)/lowprimes[lowprimes.length-1];
\r
634 public function clone():BigInteger {
\r
635 var r:BigInteger = new BigInteger;
\r
642 * @return value as integer
\r
645 public function intValue():int {
\r
657 // assumes 16 < DB < 32
\r
658 return ((a[1]&((1<<(32-DB))-1))<<DB)|a[0];
\r
663 * @return value as byte
\r
666 public function byteValue():int {
\r
667 return (t==0)?s:(a[0]<<24)>>24;
\r
672 * @return value as short (assumes DB>=16)
\r
675 public function shortValue():int {
\r
676 return (t==0)?s:(a[0]<<16)>>16;
\r
682 * @return x s.t. r^x < DV
\r
685 protected function chunkSize(r:Number):int {
\r
686 return Math.floor(Math.LN2*DB/Math.log(r));
\r
691 * @return 0 if this ==0, 1 if this >0
\r
694 public function sigNum():int {
\r
697 } else if (t<=0 || (t==1 && a[0]<=0)) {
\r
706 * @param b: radix to use
\r
707 * @return a string representing the integer converted to the radix.
\r
710 protected function toRadix(b:uint=10):String {
\r
711 if (sigNum()==0 || b<2 || b>32) return "0";
\r
712 var cs:int = chunkSize(b);
\r
713 var a:Number = Math.pow(b, cs);
\r
714 var d:BigInteger = nbv(a);
\r
715 var y:BigInteger = nbi();
\r
716 var z:BigInteger = nbi();
\r
719 while (y.sigNum()>0) {
\r
720 r = (a+z.intValue()).toString(b).substr(1) + r;
\r
723 return z.intValue().toString(b) + r;
\r
728 * @param s a string to convert from using radix.
\r
732 protected function fromRadix(s:String, b:int = 10):void {
\r
734 var cs:int = chunkSize(b);
\r
735 var d:Number = Math.pow(b, cs);
\r
736 var mi:Boolean = false;
\r
739 for (var i:int=0;i<s.length;++i) {
\r
740 var x:int = intAt(s, i);
\r
742 if (s.charAt(i) == "-" && sigNum() == 0) {
\r
756 dMultiply(Math.pow(b,j));
\r
760 BigInteger.ZERO.subTo(this, this);
\r
764 // XXX function fromNumber not written yet.
\r
768 * @return a byte array.
\r
771 public function toByteArray():ByteArray {
\r
773 var r:ByteArray = new ByteArray;
\r
775 var p:int = DB-(i*DB)%8;
\r
779 if (p<DB && (d=a[i]>>p)!=(s&DM)>>p) {
\r
780 r[k++] = d|(s<<(DB-p));
\r
784 d = (a[i]&((1<<p)-1))<<(8-p);
\r
785 d|= a[--i]>>(p+=DB-8);
\r
787 d = (a[i]>>(p-=8))&0xff;
\r
793 if ((d&0x80)!=0) d|=-256;
\r
794 if (k==0 && (s&0x80)!=(d&0x80)) ++k;
\r
795 if (k>0 || d!=s) r[k++] = d;
\r
801 public function equals(a:BigInteger):Boolean {
\r
802 return compareTo(a)==0;
\r
804 public function min(a:BigInteger):BigInteger {
\r
805 return (compareTo(a)<0)?this:a;
\r
807 public function max(a:BigInteger):BigInteger {
\r
808 return (compareTo(a)>0)?this:a;
\r
813 * @param a a BigInteger to perform the operation with
\r
814 * @param op a Function implementing the operation
\r
815 * @param r a BigInteger to store the result of the operation
\r
818 protected function bitwiseTo(a:BigInteger, op:Function, r:BigInteger):void {
\r
821 var m:int = Math.min(a.t, t);
\r
822 for (i=0; i<m; ++i) {
\r
823 r.a[i] = op(this.a[i],a.a[i]);
\r
827 for (i=m;i<t;++i) {
\r
828 r.a[i] = op(this.a[i],f);
\r
833 for (i=m;i<a.t;++i) {
\r
834 r.a[i] = op(f,a.a[i]);
\r
842 private function op_and(x:int, y:int):int {return x&y;}
\r
843 public function and(a:BigInteger):BigInteger {
\r
844 var r:BigInteger = new BigInteger;
\r
845 bitwiseTo(a, op_and, r);
\r
849 private function op_or(x:int, y:int):int {return x|y;}
\r
850 public function or(a:BigInteger):BigInteger {
\r
851 var r:BigInteger = new BigInteger;
\r
852 bitwiseTo(a, op_or, r);
\r
856 private function op_xor(x:int, y:int):int {return x^y;}
\r
857 public function xor(a:BigInteger):BigInteger {
\r
858 var r:BigInteger = new BigInteger;
\r
859 bitwiseTo(a, op_xor, r);
\r
863 private function op_andnot(x:int, y:int):int { return x&~y;}
\r
864 public function andNot(a:BigInteger):BigInteger {
\r
865 var r:BigInteger = new BigInteger;
\r
866 bitwiseTo(a, op_andnot, r);
\r
870 public function not():BigInteger {
\r
871 var r:BigInteger = new BigInteger;
\r
872 for (var i:int=0;i<t;++i) {
\r
880 public function shiftLeft(n:int):BigInteger {
\r
881 var r:BigInteger = new BigInteger;
\r
889 public function shiftRight(n:int):BigInteger {
\r
890 var r:BigInteger = new BigInteger;
\r
902 * @return index of lowet 1-bit in x, x < 2^31
\r
905 private function lbit(x:int):int {
\r
906 if (x==0) return -1;
\r
908 if ((x&0xffff)==0) { x>>= 16; r += 16; }
\r
909 if ((x&0xff) == 0) { x>>= 8; r += 8; }
\r
910 if ((x&0xf) == 0) { x>>= 4; r += 4; }
\r
911 if ((x&0x3) == 0) { x>>= 2; r += 2; }
\r
912 if ((x&0x1) == 0) ++r;
\r
918 * @return index of lowest 1-bit (or -1 if none)
\r
921 public function getLowestSetBit():int {
\r
922 for (var i:int=0;i<t;++i) {
\r
923 if (a[i]!=0) return i*DB+lbit(a[i]);
\r
925 if (s<0) return t*DB;
\r
932 * @return number of 1 bits in x
\r
935 private function cbit(x:int):int {
\r
937 while (x!=0) { x &= x-1; ++r }
\r
943 * @return number of set bits
\r
946 public function bitCount():int {
\r
949 for (var i:int=0;i<t;++i) {
\r
958 * @return true iff nth bit is set
\r
961 public function testBit(n:int):Boolean {
\r
962 var j:int = Math.floor(n/DB);
\r
966 return ((a[j]&(1<<(n%DB)))!=0);
\r
973 * @return this op (1<<n)
\r
976 protected function changeBit(n:int,op:Function):BigInteger {
\r
977 var r:BigInteger = BigInteger.ONE.shiftLeft(n);
\r
978 bitwiseTo(r, op, r);
\r
985 * @return this | (1<<n)
\r
988 public function setBit(n:int):BigInteger { return changeBit(n, op_or); }
\r
993 * @return this & ~(1<<n)
\r
996 public function clearBit(n:int):BigInteger { return changeBit(n, op_andnot); }
\r
1001 * @return this ^ (1<<n)
\r
1004 public function flipBit(n:int):BigInteger { return changeBit(n, op_xor); }
\r
1009 * @param r = this + a
\r
1012 protected function addTo(a:BigInteger, r:BigInteger):void {
\r
1015 var m:int = Math.min(a.t, t);
\r
1017 c += this.a[i] + a.a[i];
\r
1041 } else if (c<-1) {
\r
1051 * @return this + a
\r
1054 public function add(a:BigInteger):BigInteger {
\r
1055 var r:BigInteger = new BigInteger;
\r
1063 * @return this - a
\r
1066 public function subtract(a:BigInteger):BigInteger {
\r
1067 var r:BigInteger = new BigInteger;
\r
1075 * @return this * a
\r
1078 public function multiply(a:BigInteger):BigInteger {
\r
1079 var r:BigInteger = new BigInteger;
\r
1087 * @return this / a
\r
1090 public function divide(a:BigInteger):BigInteger {
\r
1091 var r:BigInteger = new BigInteger;
\r
1092 divRemTo(a, r, null);
\r
1096 public function remainder(a:BigInteger):BigInteger {
\r
1097 var r:BigInteger = new BigInteger;
\r
1098 divRemTo(a, null, r);
\r
1105 * @return [this/a, this%a]
\r
1108 public function divideAndRemainder(a:BigInteger):Array {
\r
1109 var q:BigInteger = new BigInteger;
\r
1110 var r:BigInteger = new BigInteger;
\r
1111 divRemTo(a, q, r);
\r
1117 * this *= n, this >=0, 1 < n < DV
\r
1122 bi_internal function dMultiply(n:int):void {
\r
1123 a[t] = am(0, n-1, this, 0, 0, t);
\r
1130 * this += n << w words, this >= 0
\r
1136 bi_internal function dAddOffset(n:int, w:int):void {
\r
1141 while (a[w] >= DV) {
\r
1156 public function pow(e:int):BigInteger {
\r
1157 return exp(e, new NullReduction);
\r
1164 * @param r = lower n words of "this * a", a.t <= n
\r
1167 bi_internal function multiplyLowerTo(a:BigInteger, n:int, r:BigInteger):void {
\r
1168 var i:int = Math.min(t+a.t, n);
\r
1169 r.s = 0; // assumes a, this >= 0
\r
1175 for (j=r.t-t;i<j;++i) {
\r
1176 r.a[i+t] = am(0, a.a[i], r, i, 0, t);
\r
1178 for (j=Math.min(a.t,n);i<j;++i) {
\r
1179 am(0, a.a[i], r, i, 0, n-i);
\r
1188 * @param r = "this * a" without lower n words, n > 0
\r
1191 bi_internal function multiplyUpperTo(a:BigInteger, n:int, r:BigInteger):void {
\r
1193 var i:int = r.t = t+a.t-n;
\r
1194 r.s = 0; // assumes a,this >= 0
\r
1198 for (i=Math.max(n-t,0);i<a.t;++i) {
\r
1199 r.a[t+i-n] = am(n-i, a.a[i], r, 0, 0, t+i-n);
\r
1209 * @return this^e % m (HAC 14.85)
\r
1212 public function modPow(e:BigInteger, m:BigInteger):BigInteger {
\r
1213 var i:int = e.bitLength();
\r
1215 var r:BigInteger = nbv(1);
\r
1220 } else if (i<18) {
\r
1222 } else if (i<48) {
\r
1224 } else if (i<144) {
\r
1226 } else if (i<768) {
\r
1232 z = new ClassicReduction(m);
\r
1233 } else if (m.isEven()) {
\r
1234 z = new BarrettReduction(m);
\r
1236 z = new MontgomeryReduction(m);
\r
1242 var km:int = (1<<k)-1;
\r
1243 g[1] = z.convert(this);
\r
1245 var g2:BigInteger = new BigInteger;
\r
1246 z.sqrTo(g[1], g2);
\r
1248 g[n] = new BigInteger;
\r
1249 z.mulTo(g2, g[n-2], g[n]);
\r
1254 var j:int = e.t-1;
\r
1256 var is1:Boolean = true;
\r
1257 var r2:BigInteger = new BigInteger;
\r
1259 i = nbits(e.a[j])-1;
\r
1262 w = (e.a[j]>>(i-k1))&km;
\r
1264 w = (e.a[j]&((1<<(i+1))-1))<<(k1-i);
\r
1266 w |= e.a[j-1]>>(DB+i-k1);
\r
1270 while ((w&1)==0) {
\r
1274 if ((i -= n) <0) {
\r
1278 if (is1) { // ret == 1, don't bother squaring or multiplying it
\r
1294 z.mulTo(r2, g[w], r);
\r
1296 while (j>=0 && (e.a[j]&(1<<i)) == 0) {
\r
1308 return z.revert(r);
\r
1314 * @return gcd(this, a) (HAC 14.54)
\r
1317 public function gcd(a:BigInteger):BigInteger {
\r
1318 var x:BigInteger = (s<0)?negate():clone();
\r
1319 var y:BigInteger = (a.s<0)?a.negate():a.clone();
\r
1320 if (x.compareTo(y)<0) {
\r
1321 var t:BigInteger=x;
\r
1325 var i:int = x.getLowestSetBit();
\r
1326 var g:int = y.getLowestSetBit();
\r
1327 if (g<0) return x;
\r
1333 while (x.sigNum()>0) {
\r
1334 if ((i = x.getLowestSetBit()) >0) {
\r
1337 if ((i = y.getLowestSetBit()) >0) {
\r
1340 if (x.compareTo(y) >= 0) {
\r
1357 * @return this % n, n < 2^DB
\r
1360 protected function modInt(n:int):int {
\r
1361 if (n<=0) return 0;
\r
1363 var r:int = (s<0)?n-1:0;
\r
1368 for (var i:int=t-1;i>=0;--i) {
\r
1379 * @return 1/this %m (HAC 14.61)
\r
1382 public function modInverse(m:BigInteger):BigInteger {
\r
1383 var ac:Boolean = m.isEven();
\r
1384 if ((isEven()&&ac) || m.sigNum()==0) {
\r
1385 return BigInteger.ZERO;
\r
1387 var u:BigInteger = m.clone();
\r
1388 var v:BigInteger = clone();
\r
1389 var a:BigInteger = nbv(1);
\r
1390 var b:BigInteger = nbv(0);
\r
1391 var c:BigInteger = nbv(0);
\r
1392 var d:BigInteger = nbv(1);
\r
1393 while (u.sigNum()!=0) {
\r
1394 while (u.isEven()) {
\r
1397 if (!a.isEven() || !b.isEven()) {
\r
1402 } else if (!b.isEven()) {
\r
1407 while (v.isEven()) {
\r
1410 if (!c.isEven() || !d.isEven()) {
\r
1415 } else if (!d.isEven()) {
\r
1420 if (u.compareTo(v)>=0) {
\r
1434 if (v.compareTo(BigInteger.ONE) != 0) {
\r
1435 return BigInteger.ZERO;
\r
1437 if (d.compareTo(m) >= 0) {
\r
1438 return d.subtract(m);
\r
1440 if (d.sigNum()<0) {
\r
1445 if (d.sigNum()<0) {
\r
1455 * @return primality with certainty >= 1-.5^t
\r
1458 public function isProbablePrime(t:int):Boolean {
\r
1460 var x:BigInteger = abs();
\r
1461 if (x.t == 1 && x.a[0]<=lowprimes[lowprimes.length-1]) {
\r
1462 for (i=0;i<lowprimes.length;++i) {
\r
1463 if (x[0]==lowprimes[i]) return true;
\r
1467 if (x.isEven()) return false;
\r
1469 while (i<lowprimes.length) {
\r
1470 var m:int = lowprimes[i];
\r
1472 while (j<lowprimes.length && m<lplim) {
\r
1473 m *= lowprimes[j++];
\r
1477 if (m%lowprimes[i++]==0) {
\r
1482 return x.millerRabin(t);
\r
1488 * @return true if probably prime (HAC 4.24, Miller-Rabin)
\r
1491 protected function millerRabin(t:int):Boolean {
\r
1492 var n1:BigInteger = subtract(BigInteger.ONE);
\r
1493 var k:int = n1.getLowestSetBit();
\r
1497 var r:BigInteger = n1.shiftRight(k);
\r
1499 if (t>lowprimes.length) {
\r
1500 t = lowprimes.length;
\r
1502 var a:BigInteger = new BigInteger;
\r
1503 for (var i:int=0;i<t;++i) {
\r
1504 a.fromInt(lowprimes[i]);
\r
1505 var y:BigInteger = a.modPow(r, this);
\r
1506 if (y.compareTo(BigInteger.ONE)!=0 && y.compareTo(n1)!=0) {
\r
1508 while (j++<k && y.compareTo(n1)!=0) {
\r
1509 y = y.modPowInt(2, this);
\r
1510 if (y.compareTo(BigInteger.ONE)==0) {
\r
1514 if (y.compareTo(n1)!=0) {
\r
1523 * Tweak our BigInteger until it looks prime enough
\r
1529 public function primify(bits:int, t:int):void {
\r
1530 if (!testBit(bits-1)) { // force MSB set
\r
1531 bitwiseTo(BigInteger.ONE.shiftLeft(bits-1), op_or, this);
\r
1534 dAddOffset(1,0); // force odd
\r
1536 while (!isProbablePrime(t)) {
\r
1538 while(bitLength()>bits) subTo(BigInteger.ONE.shiftLeft(bits-1),this);
\r