📄 bigint.js
字号:
linComb(x,y,A,B); //x=A*x+B*y
linComb(y,T,D,C); //y=D*y+C*T
} else {
mod(x,y);
copy(T,x);
copy(x,y);
copy(y,T);
}
}
if (y[0]==0)
return;
t=modInt(x,y[0]);
copyInt(x,y[0]);
y[0]=t;
while (y[0]) {
x[0]%=y[0];
t=x[0]; x[0]=y[0]; y[0]=t;
}
}
//do x=x**(-1) mod n, for bigInts x and n.
//If no inverse exists, it sets x to zero and returns 0, else it returns 1.
//The x array must be at least as large as the n array.
function inverseMod(x,n) {
var k=1+2*Math.max(x.length,n.length);
if(!(x[0]&1) && !(n[0]&1)) { //if both inputs are even, then inverse doesn't exist
copyInt(x,0);
return 0;
}
if (eg_u.length!=k) {
eg_u=new Array(k);
eg_v=new Array(k);
eg_A=new Array(k);
eg_B=new Array(k);
eg_C=new Array(k);
eg_D=new Array(k);
}
copy(eg_u,x);
copy(eg_v,n);
copyInt(eg_A,1);
copyInt(eg_B,0);
copyInt(eg_C,0);
copyInt(eg_D,1);
for (;;) {
while(!(eg_u[0]&1)) { //while eg_u is even
halve(eg_u);
if (!(eg_A[0]&1) && !(eg_B[0]&1)) { //if eg_A==eg_B==0 mod 2
halve(eg_A);
halve(eg_B);
} else {
add(eg_A,n); halve(eg_A);
sub(eg_B,x); halve(eg_B);
}
}
while (!(eg_v[0]&1)) { //while eg_v is even
halve(eg_v);
if (!(eg_C[0]&1) && !(eg_D[0]&1)) { //if eg_C==eg_D==0 mod 2
halve(eg_C);
halve(eg_D);
} else {
add(eg_C,n); halve(eg_C);
sub(eg_D,x); halve(eg_D);
}
}
if (!greater(eg_v,eg_u)) { //eg_v <= eg_u
sub(eg_u,eg_v);
sub(eg_A,eg_C);
sub(eg_B,eg_D);
} else { //eg_v > eg_u
sub(eg_v,eg_u);
sub(eg_C,eg_A);
sub(eg_D,eg_B);
}
if (equalsInt(eg_u,0)) {
if (negative(eg_C)) //make sure answer is nonnegative
add(eg_C,n);
copy(x,eg_C);
if (!equalsInt(eg_v,1)) { //if GCD(x,n)!=1, then there is no inverse
copyInt(x,0);
return 0;
}
return 1;
}
}
}
//return x**(-1) mod n, for integers x and n. Return 0 if there is no inverse
function inverseModInt(x,n) {
var a=1,b=0,t;
for (;;) {
if (x==1) return a;
if (x==0) return 0;
b-=a*Math.floor(n/x);
n%=x;
if (n==1) return b; //to avoid negatives, change this b to n-b, and each -= to +=
if (n==0) return 0;
a-=b*Math.floor(x/n);
x%=n;
}
}
//Given positive bigInts x and y, change the bigints v, a, and b to positive bigInts such that:
// v = GCD(x,y) = a*x-b*y
//The bigInts v, a, b, must have exactly as many elements as the larger of x and y.
function eGCD(x,y,v,a,b) {
var g=0;
var k=Math.max(x.length,y.length);
if (eg_u.length!=k) {
eg_u=new Array(k);
eg_A=new Array(k);
eg_B=new Array(k);
eg_C=new Array(k);
eg_D=new Array(k);
}
while(!(x[0]&1) && !(y[0]&1)) { //while x and y both even
halve(x);
halve(y);
g++;
}
copy(eg_u,x);
copy(v,y);
copyInt(eg_A,1);
copyInt(eg_B,0);
copyInt(eg_C,0);
copyInt(eg_D,1);
for (;;) {
while(!(eg_u[0]&1)) { //while u is even
halve(eg_u);
if (!(eg_A[0]&1) && !(eg_B[0]&1)) { //if A==B==0 mod 2
halve(eg_A);
halve(eg_B);
} else {
add(eg_A,y); halve(eg_A);
sub(eg_B,x); halve(eg_B);
}
}
while (!(v[0]&1)) { //while v is even
halve(v);
if (!(eg_C[0]&1) && !(eg_D[0]&1)) { //if C==D==0 mod 2
halve(eg_C);
halve(eg_D);
} else {
add(eg_C,y); halve(eg_C);
sub(eg_D,x); halve(eg_D);
}
}
if (!greater(v,eg_u)) { //v<=u
sub(eg_u,v);
sub(eg_A,eg_C);
sub(eg_B,eg_D);
} else { //v>u
sub(v,eg_u);
sub(eg_C,eg_A);
sub(eg_D,eg_B);
}
if (equalsInt(eg_u,0)) {
if (negative(eg_C)) { //make sure a (C)is nonnegative
add(eg_C,y);
sub(eg_D,x);
}
multInt(eg_D,-1); ///make sure b (D) is nonnegative
copy(a,eg_C);
copy(b,eg_D);
leftShift(v,g);
return;
}
}
}
//is bigInt x negative?
function negative(x) {
return ((x[x.length-1]>>(bpe-1))&1);
}
//is (x << (shift*bpe)) > y?
//x and y are nonnegative bigInts
//shift is a nonnegative integer
function greaterShift(x,y,shift) {
var kx=x.length, ky=y.length;
k=((kx+shift)<ky) ? (kx+shift) : ky;
for (i=ky-1-shift; i<kx && i>=0; i++)
if (x[i]>0)
return 1; //if there are nonzeros in x to the left of the first column of y, then x is bigger
for (i=kx-1+shift; i<ky; i++)
if (y[i]>0)
return 0; //if there are nonzeros in y to the left of the first column of x, then x is not bigger
for (i=k-1; i>=shift; i--)
if (x[i-shift]>y[i]) return 1;
else if (x[i-shift]<y[i]) return 0;
return 0;
}
//is x > y? (x and y both nonnegative)
function greater(x,y) {
var i;
var k=(x.length<y.length) ? x.length : y.length;
for (i=x.length;i<y.length;i++)
if (y[i])
return 0; //y has more digits
for (i=y.length;i<x.length;i++)
if (x[i])
return 1; //x has more digits
for (i=k-1;i>=0;i--)
if (x[i]>y[i])
return 1;
else if (x[i]<y[i])
return 0;
return 0;
}
//divide x by y giving quotient q and remainder r. (q=floor(x/y), r=x mod y). All 4 are bigints.
//x must have at least one leading zero element.
//y must be nonzero.
//q and r must be arrays that are exactly the same length as x.
//the x array must have at least as many elements as y.
function divide(x,y,q,r) {
var kx, ky;
var i,j,y1,y2,c,a,b;
copy(r,x);
for (ky=y.length;y[ky-1]==0;ky--); //kx,ky is number of elements in x,y, not including leading zeros
for (kx=r.length;r[kx-1]==0 && kx>ky;kx--);
//normalize: ensure the most significant element of y has its highest bit set
b=y[ky-1];
for (a=0; b; a++)
b>>=1;
a=bpe-a; //a is how many bits to shift so that the high order bit of y is leftmost in its array element
leftShift(y,a); //multiply both by 1<<a now, then divide both by that at the end
leftShift(r,a);
copyInt(q,0); // q=0
while (!greaterShift(y,r,kx-ky)) { // while (leftShift(y,kx-ky) <= r) {
subShift(r,y,kx-ky); // r=r-leftShift(y,kx-ky)
q[kx-ky]++; // q[kx-ky]++;
} // }
for (i=kx-1; i>=ky; i--) {
if (r[i]==y[ky-1])
q[i-ky]=mask;
else
q[i-ky]=Math.floor((r[i]*radix+r[i-1])/y[ky-1]);
//The following for(;;) loop is equivalent to the commented while loop,
//except that the uncommented version avoids overflow.
//The commented loop comes from HAC, which assumes r[-1]==y[-1]==0
// while (q[i-ky]*(y[ky-1]*radix+y[ky-2]) > r[i]*radix*radix+r[i-1]*radix+r[i-2])
// q[i-ky]--;
for (;;) {
y2=(ky>1 ? y[ky-2] : 0)*q[i-ky];
c=y2>>bpe;
y2=y2 & mask;
y1=c+q[i-ky]*y[ky-1];
c=y1>>bpe;
y1=y1 & mask;
if (c==r[i] ? y1==r[i-1] ? y2>(i>1 ? r[i-2] : 0) : y1>r[i-1] : c>r[i])
q[i-ky]--;
else
break;
}
linCombShift(r,y,-q[i-ky],i-ky); //r=r-q[i-ky]*leftShift(y,i-ky)
if (negative(r)) {
addShift(r,y,i-ky); //r=r+leftShift(y,i-ky)
q[i-ky]--;
}
}
rightShift(y,a); //undo the normalization step
rightShift(r,a); //undo the normalization step
}
//do carries and borrows so each element of the bigInt x fits in bpe bits.
function carry(x) {
var i,k,c,b;
k=x.length;
c=0;
for (i=0;i<k;i++) {
c+=x[i];
b=0;
if (c<0) {
b=-(c>>bpe);
c+=b*radix;
}
x[i]=c & mask;
c=(c>>bpe)-b;
}
}
//return x mod n for bigInt x and integer n.
function modInt(x,n) {
var i,c=0;
for (i=x.length-1; i>=0; i--)
c=(c*radix+x[i])%n;
return c;
}
//convert the integer t into a bigInt with at least the given number of bits.
//the returned array stores the bigInt in bpe-bit chunks, little endian (buff[0] is least significant word)
//Pad the array with leading zeros so that it has at least minSize elements.
//There will always be at least one leading 0 element.
function int2bigInt(t,bits,minSize) {
var i,k;
k=Math.ceil(bits/bpe)+1;
k=minSize>k ? minSize : k;
buff=new Array(k);
copyInt(buff,t);
return buff;
}
//return the bigInt given a string representation in a given base.
//Pad the array with leading zeros so that it has at least minSize elements.
//If base=-1, then it reads in a space-separated list of array elements in decimal.
//The array will always have at least one leading zero, unless base=-1.
function str2bigInt(s,base,minSize) {
var d, i, j, x, y, kk;
var k=s.length;
if (base==-1) { //comma-separated list of array elements in decimal
x=new Array(0);
for (;;) {
y=new Array(x.length+1);
for (i=0;i<x.length;i++)
y[i+1]=x[i];
y[0]=parseInt(s,10);
x=y;
d=s.indexOf(',',0);
if (d<1)
break;
s=s.substring(d+1);
if (s.length==0)
break;
}
if (x.length<minSize) {
y=new Array(minSize);
copy(y,x);
return y;
}
return x;
}
x=int2bigInt(0,base*k,0);
for (i=0;i<k;i++) {
d=digitsStr.indexOf(s.substring(i,i+1),0);
if (base<=36 && d>=36) //convert lowercase to uppercase if base<=36
d-=26;
if (d<base && d>=0) { //ignore illegal characters
multInt(x,base);
addInt(x,d);
}
}
for (k=x.length;k>0 && !x[k-1];k--); //strip off leading zeros
k=minSize>k+1 ? minSize : k+1;
y=new Array(k);
kk=k<x.length ? k : x.length;
for (i=0;i<kk;i++)
y[i]=x[i];
for (;i<k;i++)
y[i]=0;
return y;
}
//is bigint x equal to integer y?
//y must have less than bpe bits
function equalsInt(x,y) {
var i;
if (x[0]!=y)
return 0;
for (i=1;i<x.length;i++)
if (x[i])
return 0;
return 1;
}
//are bigints x and y equal?
//this works even if x and y are different lengths and have arbitrarily many leading zeros
function equals(x,y) {
var i;
var k=x.length<y.length ? x.length : y.length;
for (i=0;i<k;i++)
if (x[i]!=y[i])
return 0;
if (x.length>y.length) {
for (;i<x.length;i++)
if (x[i])
return 0;
} else {
for (;i<y.length;i++)
if (y[i])
return 0;
}
return 1;
}
//is the bigInt x equal to zero?
function isZero(x) {
var i;
for (i=0;i<x.length;i++)
if (x[i])
return 0;
return 1;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -