usingSystem;publicclassBigInteger{privateuint[]data;publicintdataLength;privateconstintmaxLength=70;publicstaticreadonlyint[]primesBelow2000=newint[]{2,3,5,7,11,13,0x11,0x13,0x17,0x1d,0x1f,0x25,0x29,0x2b,0x2f,0x35,0x3b,0x3d,0x43,0x47,0x49,0x4f,0x53,0x59,0x61,0x65,0x67,0x6b,0x6d,0x71,0x7f,0x83,0x89,0x8b,0x95,0x97,0x9d,0xa3,0xa7,0xad,0xb3,0xb5,0xbf,0xc1,0xc5,0xc7,0xd3,0xdf,0xe3,0xe5,0xe9,0xef,0xf1,0xfb,0x101,0x107,0x10d,0x10f,0x115,0x119,0x11b,0x125,0x133,0x137,0x139,0x13d,0x14b,0x151,0x15b,0x15d,0x161,0x167,0x16f,0x175,0x17b,0x17f,0x185,0x18d,0x191,0x199,0x1a3,0x1a5,0x1af,0x1b1,0x1b7,0x1bb,0x1c1,0x1c9,0x1cd,0x1cf,0x1d3,0x1df,0x1e7,0x1eb,0x1f3,0x1f7,0x1fd,0x209,0x20b,0x21d,0x223,0x22d,0x233,0x239,0x23b,0x241,0x24b,0x251,0x257,0x259,0x25f,0x265,0x269,0x26b,0x277,0x281,0x283,0x287,0x28d,0x293,0x295,0x2a1,0x2a5,0x2ab,0x2b3,0x2bd,0x2c5,0x2cf,0x2d7,0x2dd,0x2e3,0x2e7,0x2ef,0x2f5,0x2f9,0x301,0x305,0x313,0x31d,0x329,0x32b,0x335,0x337,0x33b,0x33d,0x347,0x355,0x359,0x35b,0x35f,0x36d,0x371,0x373,0x377,0x38b,0x38f,0x397,0x3a1,0x3a9,0x3ad,0x3b3,0x3b9,0x3c7,0x3cb,0x3d1,0x3d7,0x3df,0x3e5,0x3f1,0x3f5,0x3fb,0x3fd,0x407,0x409,0x40f,0x419,0x41b,0x425,0x427,0x42d,0x43f,0x443,0x445,0x449,0x44f,0x455,0x45d,0x463,0x469,0x47f,0x481,0x48b,0x493,0x49d,0x4a3,0x4a9,0x4b1,0x4bd,0x4c1,0x4c7,0x4cd,0x4cf,0x4d5,0x4e1,0x4eb,0x4fd,0x4ff,0x503,0x509,0x50b,0x511,0x515,0x517,0x51b,0x527,0x529,0x52f,0x551,0x557,0x55d,0x565,0x577,0x581,0x58f,0x593,0x595,0x599,0x59f,0x5a7,0x5ab,0x5ad,0x5b3,0x5bf,0x5c9,0x5cb,0x5cf,0x5d1,0x5d5,0x5db,0x5e7,0x5f3,0x5fb,0x607,0x60d,0x611,0x617,0x61f,0x623,0x62b,0x62f,0x63d,0x641,0x647,0x649,0x64d,0x653,0x655,0x65b,0x665,0x679,0x67f,0x683,0x685,0x69d,0x6a1,0x6a3,0x6ad,0x6b9,0x6bb,0x6c5,0x6cd,0x6d3,0x6d9,0x6df,0x6f1,0x6f7,0x6fb,0x6fd,0x709,0x713,0x71f,0x727,0x737,0x745,0x74b,0x74f,0x751,0x755,0x757,0x761,0x76d,0x773,0x779,0x78b,0x78d,0x79d,0x79f,0x7b5,0x7bb,0x7c3,0x7c9,0x7cd,0x7cf};publicBigInteger(){this.data=newuint[70];this.dataLength=1;}publicBigInteger(BigIntegerbi){this.data=newuint[70];this.dataLength=bi.dataLength;for(inti=0;i<this.dataLength;i++){this.data[i]=bi.data[i];}}publicBigInteger(longvalue){this.data=newuint[70];longnum=value;this.dataLength=0;while((value!=0L)&&(this.dataLength<70)){this.data[this.dataLength]=(uint)(((ulong)value)&0xffffffffL);value=value>>0x20;this.dataLength++;}if(num>0L){if((value!=0L)||((this.data[0x45]&0x80000000)!=0)){thrownewArithmeticException("Positive overflow in constructor.");}}elseif((num<0L)&&((value!=-1L)||((this.data[this.dataLength-1]&0x80000000)==0))){thrownewArithmeticException("Negative underflow in constructor.");}if(this.dataLength==0){this.dataLength=1;}}publicBigInteger(ulongvalue){this.data=newuint[70];this.dataLength=0;while((value!=0L)&&(this.dataLength<70)){this.data[this.dataLength]=(uint)(value&0xffffffffL);value=value>>0x20;this.dataLength++;}if((value!=0L)||((this.data[0x45]&0x80000000)!=0)){thrownewArithmeticException("Positive overflow in constructor.");}if(this.dataLength==0){this.dataLength=1;}}publicBigInteger(byte[]inData){this.dataLength=inData.Length>>2;intnum=inData.Length&3;if(num!=0){this.dataLength++;}if(this.dataLength>70){thrownewArithmeticException("Byte overflow in constructor.");}this.data=newuint[70];intindex=inData.Length-1;for(inti=0;index>=3;i++){this.data[i]=(uint)((((inData[index-3]<<0x18)+(inData[index-2]<<0x10))+(inData[index-1]<<8))+inData[index]);index-=4;}switch(num){case1:this.data[this.dataLength-1]=inData[0];break;case2:this.data[this.dataLength-1]=(uint)((inData[0]<<8)+inData[1]);break;case3:this.data[this.dataLength-1]=(uint)(((inData[0]<<0x10)+(inData[1]<<8))+inData[2]);break;}while((this.dataLength>1)&&(this.data[this.dataLength-1]==0)){this.dataLength--;}}publicBigInteger(uint[]inData){this.dataLength=inData.Length;if(this.dataLength>70){thrownewArithmeticException("Byte overflow in constructor.");}this.data=newuint[70];intindex=this.dataLength-1;for(inti=0;index>=0;i++){this.data[i]=inData[index];index--;}while((this.dataLength>1)&&(this.data[this.dataLength-1]==0)){this.dataLength--;}}publicBigInteger(byte[]inData,intinLen){this.dataLength=inLen>>2;intnum=inLen&3;if(num!=0){this.dataLength++;}if((this.dataLength>70)||(inLen>inData.Length)){thrownewArithmeticException("Byte overflow in constructor.");}this.data=newuint[70];intindex=inLen-1;for(inti=0;index>=3;i++){this.data[i]=(uint)((((inData[index-3]<<0x18)+(inData[index-2]<<0x10))+(inData[index-1]<<8))+inData[index]);index-=4;}switch(num){case1:this.data[this.dataLength-1]=inData[0];break;case2:this.data[this.dataLength-1]=(uint)((inData[0]<<8)+inData[1]);break;case3:this.data[this.dataLength-1]=(uint)(((inData[0]<<0x10)+(inData[1]<<8))+inData[2]);break;}if(this.dataLength==0){this.dataLength=1;}while((this.dataLength>1)&&(this.data[this.dataLength-1]==0)){this.dataLength--;}}publicBigInteger(stringvalue,intradix){BigIntegerinteger=newBigInteger(1L);BigIntegerinteger2=newBigInteger();value=value.ToUpper().Trim();intnum=0;if(value[0]=='-'){num=1;}for(inti=value.Length-1;i>=num;i--){intnum3=value[i];if((num3>=0x30)&&(num3<=0x39)){num3-=0x30;}elseif((num3>=0x41)&&(num3<=90)){num3=(num3-0x41)+10;}else{num3=0x98967f;}if(num3>=radix){thrownewArithmeticException("Invalid string in constructor.");}if(value[0]=='-'){num3=-num3;}integer2+=integer*num3;if((i-1)>=num){integer*=radix;}}if(value[0]=='-'){if((integer2.data[0x45]&0x80000000)==0){thrownewArithmeticException("Negative underflow in constructor.");}}elseif((integer2.data[0x45]&0x80000000)!=0){thrownewArithmeticException("Positive overflow in constructor.");}this.data=newuint[70];for(intj=0;j<integer2.dataLength;j++){this.data[j]=integer2.data[j];}this.dataLength=integer2.dataLength;}publicBigIntegerabs(){if((this.data[0x45]&0x80000000)!=0){return-this;}returnnewBigInteger(this);}privateBigIntegerBarrettReduction(BigIntegerx,BigIntegern,BigIntegerconstant){intdataLength=n.dataLength;intindex=dataLength+1;intnum3=dataLength-1;BigIntegerinteger=newBigInteger();intnum4=num3;for(inti=0;num4<x.dataLength;i++){integer.data[i]=x.data[num4];num4++;}integer.dataLength=x.dataLength-num3;if(integer.dataLength<=0){integer.dataLength=1;}BigIntegerinteger2=integer*constant;BigIntegerinteger3=newBigInteger();intnum6=index;for(intj=0;num6<integer2.dataLength;j++){integer3.data[j]=integer2.data[num6];num6++;}integer3.dataLength=integer2.dataLength-index;if(integer3.dataLength<=0){integer3.dataLength=1;}BigIntegerinteger4=newBigInteger();intnum8=(x.dataLength>index)?index:x.dataLength;for(intk=0;k<num8;k++){integer4.data[k]=x.data[k];}integer4.dataLength=num8;BigIntegerinteger5=newBigInteger();for(intm=0;m<integer3.dataLength;m++){if(integer3.data[m]!=0){ulongnum11=0L;intnum12=m;intnum13=0;while((num13<n.dataLength)&&(num12<index)){ulongnum14=((integer3.data[m]*n.data[num13])+integer5.data[num12])+num11;integer5.data[num12]=(uint)(num14&0xffffffffL);num11=num14>>0x20;num13++;num12++;}if(num12<index){integer5.data[num12]=(uint)num11;}}}integer5.dataLength=index;while((integer5.dataLength>1)&&(integer5.data[integer5.dataLength-1]==0)){integer5.dataLength--;}integer4-=integer5;if((integer4.data[0x45]&0x80000000)!=0){BigIntegerinteger6=newBigInteger();integer6.data[index]=1;integer6.dataLength=index+1;integer4+=integer6;}while(integer4>=n){integer4-=n;}returninteger4;}publicintbitCount(){while((this.dataLength>1)&&(this.data[this.dataLength-1]==0)){this.dataLength--;}uintnum=this.data[this.dataLength-1];uintnum2=0x80000000;intnum3=0x20;while((num3>0)&&((num&num2)==0)){num3--;num2=num2>>1;}return(num3+((this.dataLength-1)<<5));}publicoverrideboolEquals(objecto){BigIntegerinteger=(BigInteger)o;if(this.dataLength!=integer.dataLength){returnfalse;}for(inti=0;i<this.dataLength;i++){if(this.data[i]!=integer.data[i]){returnfalse;}}returntrue;}publicboolFermatLittleTest(intconfidence){BigIntegerinteger;if((this.data[0x45]&0x80000000)!=0){integer=-this;}else{integer=this;}if(integer.dataLength==1){if((integer.data[0]==0)||(integer.data[0]==1)){returnfalse;}if((integer.data[0]==2)||(integer.data[0]==3)){returntrue;}}if((integer.data[0]&1)==0){returnfalse;}intnum=integer.bitCount();BigIntegerinteger2=newBigInteger();BigIntegerexp=integer-newBigInteger(1L);Randomrand=newRandom();for(inti=0;i<confidence;i++){boolflag=false;while(!flag){intbits=0;while(bits<2){bits=(int)(rand.NextDouble()*num);}integer2.genRandomBits(bits,rand);intnum4=integer2.dataLength;if((num4>1)||((num4==1)&&(integer2.data[0]!=1))){flag=true;}}BigIntegerinteger4=integer2.gcd(integer);if((integer4.dataLength==1)&&(integer4.data[0]!=1)){returnfalse;}BigIntegerinteger5=integer2.modPow(exp,integer);intdataLength=integer5.dataLength;if((dataLength>1)||((dataLength==1)&&(integer5.data[0]!=1))){returnfalse;}}returntrue;}publicBigIntegergcd(BigIntegerbi){BigIntegerinteger;BigIntegerinteger2;if((this.data[0x45]&0x80000000)!=0){integer=-this;}else{integer=this;}if((bi.data[0x45]&0x80000000)!=0){integer2=-bi;}else{integer2=bi;}BigIntegerinteger3=integer2;while((integer.dataLength>1)||((integer.dataLength==1)&&(integer.data[0]!=0))){integer3=integer;integer=integer2%integer;integer2=integer3;}returninteger3;}publicBigIntegergenCoPrime(intbits,Randomrand){boolflag=false;BigIntegerinteger=newBigInteger();while(!flag){integer.genRandomBits(bits,rand);BigIntegerinteger2=integer.gcd(this);if((integer2.dataLength==1)&&(integer2.data[0]==1)){flag=true;}}returninteger;}publicstaticBigIntegergenPseudoPrime(intbits,intconfidence,Randomrand){BigIntegerinteger=newBigInteger();for(boolflag=false;!flag;flag=integer.isProbablePrime(confidence)){integer.genRandomBits(bits,rand);integer.data[0]|=1;}returninteger;}publicvoidgenRandomBits(intbits,Randomrand){intnum=bits>>5;intnum2=bits&0x1f;if(num2!=0){num++;}if(num>70){thrownewArithmeticException("Number of required bits > maxLength.");}for(inti=0;i<num;i++){this.data[i]=(uint)(rand.NextDouble()*4294967296);}for(intj=num;j<70;j++){this.data[j]=0;}if(num2!=0){uintnum5=((uint)1)<<(num2-1);this.data[num-1]|=num5;num5=((uint)(-1))>>(0x20-num2);this.data[num-1]&=num5;}else{this.data[num-1]|=0x80000000;}this.dataLength=num;if(this.dataLength==0){this.dataLength=1;}}publicbyte[]getBytes(){intnum=this.bitCount();intnum2=num>>3;if((num&7)!=0){num2++;}byte[]buffer=newbyte[num2];intindex=0;uintnum5=this.data[this.dataLength-1];uintnum4=(num5>>0x18)&0xff;if(num4!=0){buffer[index++]=(byte)num4;}num4=(num5>>0x10)&0xff;if(num4!=0){buffer[index++]=(byte)num4;}num4=(num5>>8)&0xff;if(num4!=0){buffer[index++]=(byte)num4;}num4=num5&0xff;if(num4!=0){buffer[index++]=(byte)num4;}intnum6=this.dataLength-2;while(num6>=0){num5=this.data[num6];buffer[index+3]=(byte)(num5&0xff);num5=num5>>8;buffer[index+2]=(byte)(num5&0xff);num5=num5>>8;buffer[index+1]=(byte)(num5&0xff);num5=num5>>8;buffer[index]=(byte)(num5&0xff);num6--;index+=4;}returnbuffer;}publicoverrideintGetHashCode(){returnthis.ToString().GetHashCode();}publicintIntValue(){return(int)this.data[0];}publicboolisProbablePrime(){BigIntegerinteger;if((this.data[0x45]&0x80000000)!=0){integer=-this;}else{integer=this;}if(integer.dataLength==1){if((integer.data[0]==0)||(integer.data[0]==1)){returnfalse;}if((integer.data[0]==2)||(integer.data[0]==3)){returntrue;}}if((integer.data[0]&1)==0){returnfalse;}for(inti=0;i<primesBelow2000.Length;i++){BigIntegerinteger2=primesBelow2000[i];if(integer2>=integer){break;}BigIntegerinteger3=integer%integer2;if(integer3.IntValue()==0){returnfalse;}}BigIntegerinteger4=integer-newBigInteger(1L);intnum2=0;for(intj=0;j<integer4.dataLength;j++){uintnum4=1;for(intm=0;m<0x20;m++){if((integer4.data[j]&num4)!=0){j=integer4.dataLength;break;}num4=num4<<1;num2++;}}BigIntegerexp=integer4>>num2;integer.bitCount();BigIntegerinteger7=2.modPow(exp,integer);boolflag=false;if((integer7.dataLength==1)&&(integer7.data[0]==1)){flag=true;}for(intk=0;!flag&&(k<num2);k++){if(integer7==integer4){flag=true;break;}integer7=(integer7*integer7)%integer;}if(flag){flag=this.LucasStrongTestHelper(integer);}returnflag;}publicboolisProbablePrime(intconfidence){BigIntegerinteger;if((this.data[0x45]&0x80000000)!=0){integer=-this;}else{integer=this;}for(inti=0;i<primesBelow2000.Length;i++){BigIntegerinteger2=primesBelow2000[i];if(integer2>=integer){break;}BigIntegerinteger3=integer%integer2;if(integer3.IntValue()==0){returnfalse;}}returninteger.RabinMillerTest(confidence);}publicstaticintJacobi(BigIntegera,BigIntegerb){if((b.data[0]&1)==0){thrownewArgumentException("Jacobi defined only for odd integers.");}if(a>=b){a=a%b;}if((a.dataLength==1)&&(a.data[0]==0)){return0;}if((a.dataLength==1)&&(a.data[0]==1)){return1;}if(a<0){if(((b-1).data[0]&2)==0){returnJacobi(-a,b);}return-Jacobi(-a,b);}intnum=0;for(inti=0;i<a.dataLength;i++){uintnum3=1;for(intj=0;j<0x20;j++){if((a.data[i]&num3)!=0){i=a.dataLength;break;}num3=num3<<1;num++;}}BigIntegerinteger=a>>num;intnum5=1;if(((num&1)!=0)&&(((b.data[0]&7)==3)||((b.data[0]&7)==5))){num5=-1;}if(((b.data[0]&3)==3)&&((integer.data[0]&3)==3)){num5=-num5;}if((integer.dataLength==1)&&(integer.data[0]==1)){returnnum5;}return(num5*Jacobi(b%integer,integer));}publiclongLongValue(){longnum=0L;num=this.data[0];try{num|=this.data[1]<<0x20;}catch(Exception){if((this.data[0]&0x80000000)!=0){num=this.data[0];}}returnnum;}publicstaticBigInteger[]LucasSequence(BigIntegerP,BigIntegerQ,BigIntegerk,BigIntegern){if((k.dataLength==1)&&(k.data[0]==0)){returnnewBigInteger[]{0,(2%n),(1%n)};}BigIntegerconstant=newBigInteger();intindex=n.dataLength<<1;constant.data[index]=1;constant.dataLength=index+1;constant/=n;ints=0;for(inti=0;i<k.dataLength;i++){uintnum4=1;for(intj=0;j<0x20;j++){if((k.data[i]&num4)!=0){i=k.dataLength;break;}num4=num4<<1;s++;}}BigIntegerinteger2=k>>s;returnLucasSequenceHelper(P,Q,integer2,n,constant,s);}privatestaticBigInteger[]LucasSequenceHelper(BigIntegerP,BigIntegerQ,BigIntegerk,BigIntegern,BigIntegerconstant,ints){BigInteger[]integerArray=newBigInteger[3];if((k.data[0]&1)==0){thrownewArgumentException("Argument k must be odd.");}intnum=k.bitCount();uintnum2=((uint)1)<<((num&0x1f)-1);BigIntegerinteger=2%n;BigIntegerinteger2=1%n;BigIntegerinteger3=P%n;BigIntegerinteger4=integer2;boolflag=true;for(inti=k.dataLength-1;i>=0;i--){while(num2!=0){if((i==0)&&(num2==1)){break;}if((k.data[i]&num2)!=0){integer4=(integer4*integer3)%n;integer=((integer*integer3)-(P*integer2))%n;integer3=(n.BarrettReduction(integer3*integer3,n,constant)-((integer2*Q)<<1))%n;if(flag){flag=false;}else{integer2=n.BarrettReduction(integer2*integer2,n,constant);}integer2=(integer2*Q)%n;}else{integer4=((integer4*integer)-integer2)%n;integer3=((integer*integer3)-(P*integer2))%n;integer=(n.BarrettReduction(integer*integer,n,constant)-(integer2<<1))%n;if(flag){integer2=Q%n;flag=false;}else{integer2=n.BarrettReduction(integer2*integer2,n,constant);}}num2=num2>>1;}num2=0x80000000;}integer4=((integer4*integer)-integer2)%n;integer=((integer*integer3)-(P*integer2))%n;if(flag){flag=false;}else{integer2=n.BarrettReduction(integer2*integer2,n,constant);}integer2=(integer2*Q)%n;for(intj=0;j<s;j++){integer4=(integer4*integer)%n;integer=((integer*integer)-(integer2<<1))%n;if(flag){integer2=Q%n;flag=false;}else{integer2=n.BarrettReduction(integer2*integer2,n,constant);}}integerArray[0]=integer4;integerArray[1]=integer;integerArray[2]=integer2;returnintegerArray;}publicboolLucasStrongTest(){BigIntegerinteger;if((this.data[0x45]&0x80000000)!=0){integer=-this;}else{integer=this;}if(integer.dataLength==1){if((integer.data[0]==0)||(integer.data[0]==1)){returnfalse;}if((integer.data[0]==2)||(integer.data[0]==3)){returntrue;}}if((integer.data[0]&1)==0){returnfalse;}returnthis.LucasStrongTestHelper(integer);}privateboolLucasStrongTestHelper(BigIntegerthisVal){longa=5L;longnum2=-1L;longnum3=0L;boolflag=false;while(!flag){intnum4=Jacobi(a,thisVal);if(num4==-1){flag=true;}else{if((num4==0)&&(Math.Abs(a)<thisVal)){returnfalse;}if(num3==20L){BigIntegerinteger=thisVal.sqrt();if((integer*integer)==thisVal){returnfalse;}}a=(Math.Abs(a)+2L)*num2;num2=-num2;}num3+=1L;}longq=(1L-a)>>2;BigIntegerinteger2=thisVal+1;intnum6=0;for(inti=0;i<integer2.dataLength;i++){uintnum8=1;for(intm=0;m<0x20;m++){if((integer2.data[i]&num8)!=0){i=integer2.dataLength;break;}num8=num8<<1;num6++;}}BigIntegerk=integer2>>num6;BigIntegerconstant=newBigInteger();intindex=thisVal.dataLength<<1;constant.data[index]=1;constant.dataLength=index+1;constant/=thisVal;BigInteger[]integerArray=LucasSequenceHelper(1,q,k,thisVal,constant,0);boolflag2=false;if(((integerArray[0].dataLength==1)&&(integerArray[0].data[0]==0))||((integerArray[1].dataLength==1)&&(integerArray[1].data[0]==0))){flag2=true;}for(intj=1;j<num6;j++){if(!flag2){integerArray[1]=thisVal.BarrettReduction(integerArray[1]*integerArray[1],thisVal,constant);integerArray[1]=(integerArray[1]-(integerArray[2]<<1))%thisVal;if((integerArray[1].dataLength==1)&&(integerArray[1].data[0]==0)){flag2=true;}}integerArray[2]=thisVal.BarrettReduction(integerArray[2]*integerArray[2],thisVal,constant);}if(flag2){BigIntegerinteger5=thisVal.gcd(q);if((integer5.dataLength!=1)||(integer5.data[0]!=1)){returnflag2;}if((integerArray[2].data[0x45]&0x80000000)!=0){integerArray[2]+=thisVal;}BigIntegerinteger6=(q*Jacobi(q,thisVal))%thisVal;if((integer6.data[0x45]&0x80000000)!=0){integer6+=thisVal;}if(integerArray[2]!=integer6){flag2=false;}}returnflag2;}publicBigIntegermax(BigIntegerbi){if(this>bi){returnnewBigInteger(this);}returnnewBigInteger(bi);}publicBigIntegermin(BigIntegerbi){if(this<bi){returnnewBigInteger(this);}returnnewBigInteger(bi);}publicBigIntegermodInverse(BigIntegermodulus){BigInteger[]integerArray=newBigInteger[]{0,1};BigInteger[]integerArray2=newBigInteger[2];BigInteger[]integerArray3=newBigInteger[]{0,0};intnum=0;BigIntegerinteger=modulus;BigIntegerinteger2=this;while((integer2.dataLength>1)||((integer2.dataLength==1)&&(integer2.data[0]!=0))){BigIntegeroutQuotient=newBigInteger();BigIntegeroutRemainder=newBigInteger();if(num>1){BigIntegerinteger5=(integerArray[0]-(integerArray[1]*integerArray2[0]))%modulus;integerArray[0]=integerArray[1];integerArray[1]=integer5;}if(integer2.dataLength==1){singleByteDivide(integer,integer2,outQuotient,outRemainder);}else{multiByteDivide(integer,integer2,outQuotient,outRemainder);}integerArray2[0]=integerArray2[1];integerArray3[0]=integerArray3[1];integerArray2[1]=outQuotient;integerArray3[1]=outRemainder;integer=integer2;integer2=outRemainder;num++;}if((integerArray3[0].dataLength>1)||((integerArray3[0].dataLength==1)&&(integerArray3[0].data[0]!=1))){thrownewArithmeticException("No inverse!");}BigIntegerinteger6=(integerArray[0]-(integerArray[1]*integerArray2[0]))%modulus;if((integer6.data[0x45]&0x80000000)!=0){integer6+=modulus;}returninteger6;}publicBigIntegermodPow(BigIntegerexp,BigIntegern){BigIntegerinteger2;if((exp.data[0x45]&0x80000000)!=0){thrownewArithmeticException("Positive exponents only.");}BigIntegerinteger=1;boolflag=false;if((this.data[0x45]&0x80000000)!=0){integer2=-this%n;flag=true;}else{integer2=this%n;}if((n.data[0x45]&0x80000000)!=0){n=-n;}BigIntegerconstant=newBigInteger();intindex=n.dataLength<<1;constant.data[index]=1;constant.dataLength=index+1;constant/=n;intnum2=exp.bitCount();intnum3=0;for(inti=0;i<exp.dataLength;i++){uintnum5=1;for(intj=0;j<0x20;j++){if((exp.data[i]&num5)!=0){integer=this.BarrettReduction(integer*integer2,n,constant);}num5=num5<<1;integer2=this.BarrettReduction(integer2*integer2,n,constant);if((integer2.dataLength==1)&&(integer2.data[0]==1)){if(flag&&((exp.data[0]&1)!=0)){return-integer;}returninteger;}num3++;if(num3==num2){break;}}}if(flag&&((exp.data[0]&1)!=0)){return-integer;}returninteger;}privatestaticvoidmultiByteDivide(BigIntegerbi1,BigIntegerbi2,BigIntegeroutQuotient,BigIntegeroutRemainder){uint[]numArray=newuint[70];intnum=bi1.dataLength+1;uint[]buffer=newuint[num];uintnum2=0x80000000;uintnum3=bi2.data[bi2.dataLength-1];intshiftVal=0;intnum5=0;while((num2!=0)&&((num3&num2)==0)){shiftVal++;num2=num2>>1;}for(inti=0;i<bi1.dataLength;i++){buffer[i]=bi1.data[i];}shiftLeft(buffer,shiftVal);bi2=bi2<<shiftVal;intnum7=num-bi2.dataLength;intindex=num-1;ulongnum9=bi2.data[bi2.dataLength-1];ulongnum10=bi2.data[bi2.dataLength-2];intnum11=bi2.dataLength+1;uint[]inData=newuint[num11];while(num7>0){ulongnum12=(buffer[index]<<0x20)+buffer[index-1];ulongnum13=num12/num9;ulongnum14=num12%num9;boolflag=false;while(!flag){flag=true;if((num13==0x100000000L)||((num13*num10)>((num14<<0x20)+buffer[index-2]))){num13-=(ulong)1L;num14+=num9;if(num14<0x100000000L){flag=false;}}}for(intj=0;j<num11;j++){inData[j]=buffer[index-j];}BigIntegerinteger=newBigInteger(inData);BigIntegerinteger2=bi2*num13;while(integer2>integer){num13-=(ulong)1L;integer2-=bi2;}BigIntegerinteger3=integer-integer2;for(intk=0;k<num11;k++){buffer[index-k]=integer3.data[bi2.dataLength-k];}numArray[num5++]=(uint)num13;index--;num7--;}outQuotient.dataLength=num5;intnum17=0;intnum18=outQuotient.dataLength-1;while(num18>=0){outQuotient.data[num17]=numArray[num18];num18--;num17++;}while(num17<70){outQuotient.data[num17]=0;num17++;}while((outQuotient.dataLength>1)&&(outQuotient.data[outQuotient.dataLength-1]==0)){outQuotient.dataLength--;}if(outQuotient.dataLength==0){outQuotient.dataLength=1;}outRemainder.dataLength=shiftRight(buffer,shiftVal);num17=0;while(num17<outRemainder.dataLength){outRemainder.data[num17]=buffer[num17];num17++;}while(num17<70){outRemainder.data[num17]=0;num17++;}}publicstaticBigIntegeroperator+(BigIntegerbi1,BigIntegerbi2){BigIntegerinteger=newBigInteger{dataLength=(bi1.dataLength>bi2.dataLength)?bi1.dataLength:bi2.dataLength};longnum=0L;for(inti=0;i<integer.dataLength;i++){longnum3=(bi1.data[i]+bi2.data[i])+num;num=num3>>0x20;integer.data[i]=(uint)(((ulong)num3)&0xffffffffL);}if((num!=0L)&&(integer.dataLength<70)){integer.data[integer.dataLength]=(uint)num;integer.dataLength++;}while((integer.dataLength>1)&&(integer.data[integer.dataLength-1]==0)){integer.dataLength--;}intindex=0x45;if(((bi1.data[index]&0x80000000)==(bi2.data[index]&0x80000000))&&((integer.data[index]&0x80000000)!=(bi1.data[index]&0x80000000))){thrownewArithmeticException();}returninteger;}publicstaticBigIntegeroperator&(BigIntegerbi1,BigIntegerbi2){BigIntegerinteger=newBigInteger();intnum=(bi1.dataLength>bi2.dataLength)?bi1.dataLength:bi2.dataLength;for(inti=0;i<num;i++){integer.data[i]=bi1.data[i]&bi2.data[i];}integer.dataLength=70;while((integer.dataLength>1)&&(integer.data[integer.dataLength-1]==0)){integer.dataLength--;}returninteger;}publicstaticBigIntegeroperator|(BigIntegerbi1,BigIntegerbi2){BigIntegerinteger=newBigInteger();intnum=(bi1.dataLength>bi2.dataLength)?bi1.dataLength:bi2.dataLength;for(inti=0;i<num;i++){integer.data[i]=bi1.data[i]|bi2.data[i];}integer.dataLength=70;while((integer.dataLength>1)&&(integer.data[integer.dataLength-1]==0)){integer.dataLength--;}returninteger;}publicstaticBigIntegeroperator--(BigIntegerbi1){BigIntegerinteger=newBigInteger(bi1);boolflag=true;intindex=0;while(flag&&(index<70)){longnum=integer.data[index];num-=1L;integer.data[index]=(uint)(((ulong)num)&0xffffffffL);if(num>=0L){flag=false;}index++;}if(index>integer.dataLength){integer.dataLength=index;}while((integer.dataLength>1)&&(integer.data[integer.dataLength-1]==0)){integer.dataLength--;}intnum3=0x45;if(((bi1.data[num3]&0x80000000)!=0)&&((integer.data[num3]&0x80000000)!=(bi1.data[num3]&0x80000000))){thrownewArithmeticException("Underflow in --.");}returninteger;}publicstaticBigIntegeroperator/(BigIntegerbi1,BigIntegerbi2){BigIntegeroutQuotient=newBigInteger();BigIntegeroutRemainder=newBigInteger();intindex=0x45;boolflag=false;boolflag2=false;if((bi1.data[index]&0x80000000)!=0){bi1=-bi1;flag2=true;}if((bi2.data[index]&0x80000000)!=0){bi2=-bi2;flag=true;}if(bi1>=bi2){if(bi2.dataLength==1){singleByteDivide(bi1,bi2,outQuotient,outRemainder);}else{multiByteDivide(bi1,bi2,outQuotient,outRemainder);}if(flag2!=flag){return-outQuotient;}}returnoutQuotient;}publicstaticbooloperator==(BigIntegerbi1,BigIntegerbi2){returnbi1.Equals(bi2);}publicstaticBigIntegeroperator^(BigIntegerbi1,BigIntegerbi2){BigIntegerinteger=newBigInteger();intnum=(bi1.dataLength>bi2.dataLength)?bi1.dataLength:bi2.dataLength;for(inti=0;i<num;i++){integer.data[i]=bi1.data[i]^bi2.data[i];}integer.dataLength=70;while((integer.dataLength>1)&&(integer.data[integer.dataLength-1]==0)){integer.dataLength--;}returninteger;}publicstaticbooloperator>(BigIntegerbi1,BigIntegerbi2){intindex=0x45;if(((bi1.data[index]&0x80000000)!=0)&&((bi2.data[index]&0x80000000)==0)){returnfalse;}if(((bi1.data[index]&0x80000000)==0)&&((bi2.data[index]&0x80000000)!=0)){returntrue;}intnum2=(bi1.dataLength>bi2.dataLength)?bi1.dataLength:bi2.dataLength;index=num2-1;while((index>=0)&&(bi1.data[index]==bi2.data[index])){index--;}if(index<0){returnfalse;}return(bi1.data[index]>bi2.data[index]);}publicstaticbooloperator>=(BigIntegerbi1,BigIntegerbi2){if(!(bi1==bi2)){return(bi1>bi2);}returntrue;}publicstaticimplicitoperatorBigInteger(intvalue){returnnewBigInteger((long)value);}publicstaticimplicitoperatorBigInteger(longvalue){returnnewBigInteger(value);}publicstaticimplicitoperatorBigInteger(uintvalue){returnnewBigInteger((ulong)value);}publicstaticimplicitoperatorBigInteger(ulongvalue){returnnewBigInteger(value);}publicstaticBigIntegeroperator++(BigIntegerbi1){BigIntegerinteger=newBigInteger(bi1);longnum2=1L;intindex=0;while((num2!=0L)&&(index<70)){longnum=integer.data[index];num+=1L;integer.data[index]=(uint)(((ulong)num)&0xffffffffL);num2=num>>0x20;index++;}if(index<=integer.dataLength){while((integer.dataLength>1)&&(integer.data[integer.dataLength-1]==0)){integer.dataLength--;}}else{integer.dataLength=index;}intnum4=0x45;if(((bi1.data[num4]&0x80000000)==0)&&((integer.data[num4]&0x80000000)!=(bi1.data[num4]&0x80000000))){thrownewArithmeticException("Overflow in ++.");}returninteger;}publicstaticbooloperator!=(BigIntegerbi1,BigIntegerbi2){return!bi1.Equals(bi2);}publicstaticBigIntegeroperator<<(BigIntegerbi1,intshiftVal){BigIntegerinteger;returnnewBigInteger(bi1){dataLength=shiftLeft(integer.data,shiftVal)};}publicstaticbooloperator<(BigIntegerbi1,BigIntegerbi2){intindex=0x45;if(((bi1.data[index]&0x80000000)!=0)&&((bi2.data[index]&0x80000000)==0)){returntrue;}if(((bi1.data[index]&0x80000000)==0)&&((bi2.data[index]&0x80000000)!=0)){returnfalse;}intnum2=(bi1.dataLength>bi2.dataLength)?bi1.dataLength:bi2.dataLength;index=num2-1;while((index>=0)&&(bi1.data[index]==bi2.data[index])){index--;}if(index<0){returnfalse;}return(bi1.data[index]<bi2.data[index]);}publicstaticbooloperator<=(BigIntegerbi1,BigIntegerbi2){if(!(bi1==bi2)){return(bi1<bi2);}returntrue;}publicstaticBigIntegeroperator%(BigIntegerbi1,BigIntegerbi2){BigIntegeroutQuotient=newBigInteger();BigIntegeroutRemainder=newBigInteger(bi1);intindex=0x45;boolflag=false;if((bi1.data[index]&0x80000000)!=0){bi1=-bi1;flag=true;}if((bi2.data[index]&0x80000000)!=0){bi2=-bi2;}if(bi1>=bi2){if(bi2.dataLength==1){singleByteDivide(bi1,bi2,outQuotient,outRemainder);}else{multiByteDivide(bi1,bi2,outQuotient,outRemainder);}if(flag){return-outRemainder;}}returnoutRemainder;}publicstaticBigIntegeroperator*(BigIntegerbi1,BigIntegerbi2){intindex=0x45;boolflag=false;boolflag2=false;try{if((bi1.data[index]&0x80000000)!=0){flag=true;bi1=-bi1;}if((bi2.data[index]&0x80000000)!=0){flag2=true;bi2=-bi2;}}catch(Exception){}BigIntegerinteger=newBigInteger();try{for(inti=0;i<bi1.dataLength;i++){if(bi1.data[i]!=0){ulongnum3=0L;intnum4=0;for(intj=i;num4<bi2.dataLength;j++){ulongnum6=((bi1.data[i]*bi2.data[num4])+integer.data[j])+num3;integer.data[j]=(uint)(num6&0xffffffffL);num3=num6>>0x20;num4++;}if(num3!=0L){integer.data[i+bi2.dataLength]=(uint)num3;}}}}catch(Exception){thrownewArithmeticException("Multiplication overflow.");}integer.dataLength=bi1.dataLength+bi2.dataLength;if(integer.dataLength>70){integer.dataLength=70;}while((integer.dataLength>1)&&(integer.data[integer.dataLength-1]==0)){integer.dataLength--;}if((integer.data[index]&0x80000000)!=0){if((flag!=flag2)&&(integer.data[index]==0x80000000)){if(integer.dataLength==1){returninteger;}boolflag3=true;for(intk=0;(k<(integer.dataLength-1))&&flag3;k++){if(integer.data[k]!=0){flag3=false;}}if(flag3){returninteger;}}thrownewArithmeticException("Multiplication overflow.");}if(flag!=flag2){return-integer;}returninteger;}publicstaticBigIntegeroperator~(BigIntegerbi1){BigIntegerinteger=newBigInteger(bi1);for(inti=0;i<70;i++){integer.data[i]=~bi1.data[i];}integer.dataLength=70;while((integer.dataLength>1)&&(integer.data[integer.dataLength-1]==0)){integer.dataLength--;}returninteger;}publicstaticBigIntegeroperator>>(BigIntegerbi1,intshiftVal){BigIntegerinteger;integer=newBigInteger(bi1){dataLength=shiftRight(integer.data,shiftVal)};if((bi1.data[0x45]&0x80000000)!=0){for(inti=0x45;i>=integer.dataLength;i--){integer.data[i]=uint.MaxValue;}uintnum2=0x80000000;for(intj=0;j<0x20;j++){if((integer.data[integer.dataLength-1]&num2)!=0){break;}integer.data[integer.dataLength-1]|=num2;num2=num2>>1;}integer.dataLength=70;}returninteger;}publicstaticBigIntegeroperator-(BigIntegerbi1,BigIntegerbi2){BigIntegerinteger=newBigInteger{dataLength=(bi1.dataLength>bi2.dataLength)?bi1.dataLength:bi2.dataLength};longnum=0L;for(inti=0;i<integer.dataLength;i++){longnum3=(bi1.data[i]-bi2.data[i])-num;integer.data[i]=(uint)(((ulong)num3)&0xffffffffL);if(num3<0L){num=1L;}else{num=0L;}}if(num!=0L){for(intj=integer.dataLength;j<70;j++){integer.data[j]=uint.MaxValue;}integer.dataLength=70;}while((integer.dataLength>1)&&(integer.data[integer.dataLength-1]==0)){integer.dataLength--;}intindex=0x45;if(((bi1.data[index]&0x80000000)!=(bi2.data[index]&0x80000000))&&((integer.data[index]&0x80000000)!=(bi1.data[index]&0x80000000))){thrownewArithmeticException();}returninteger;}publicstaticBigIntegeroperator-(BigIntegerbi1){if((bi1.dataLength==1)&&(bi1.data[0]==0)){returnnewBigInteger();}BigIntegerinteger=newBigInteger(bi1);for(inti=0;i<70;i++){integer.data[i]=~bi1.data[i];}longnum3=1L;for(intj=0;(num3!=0L)&&(j<70);j++){longnum2=integer.data[j];num2+=1L;integer.data[j]=(uint)(((ulong)num2)&0xffffffffL);num3=num2>>0x20;}if((bi1.data[0x45]&0x80000000)==(integer.data[0x45]&0x80000000)){thrownewArithmeticException("Overflow in negation.\n");}integer.dataLength=70;while((integer.dataLength>1)&&(integer.data[integer.dataLength-1]==0)){integer.dataLength--;}returninteger;}publicboolRabinMillerTest(intconfidence){BigIntegerinteger;if((this.data[0x45]&0x80000000)!=0){integer=-this;}else{integer=this;}if(integer.dataLength==1){if((integer.data[0]==0)||(integer.data[0]==1)){returnfalse;}if((integer.data[0]==2)||(integer.data[0]==3)){returntrue;}}if((integer.data[0]&1)==0){returnfalse;}BigIntegerinteger2=integer-newBigInteger(1L);intnum=0;for(inti=0;i<integer2.dataLength;i++){uintnum3=1;for(intk=0;k<0x20;k++){if((integer2.data[i]&num3)!=0){i=integer2.dataLength;break;}num3=num3<<1;num++;}}BigIntegerexp=integer2>>num;intnum5=integer.bitCount();BigIntegerinteger4=newBigInteger();Randomrand=newRandom();for(intj=0;j<confidence;j++){boolflag=false;while(!flag){intbits=0;while(bits<2){bits=(int)(rand.NextDouble()*num5);}integer4.genRandomBits(bits,rand);intdataLength=integer4.dataLength;if((dataLength>1)||((dataLength==1)&&(integer4.data[0]!=1))){flag=true;}}BigIntegerinteger5=integer4.gcd(integer);if((integer5.dataLength==1)&&(integer5.data[0]!=1)){returnfalse;}BigIntegerinteger6=integer4.modPow(exp,integer);boolflag2=false;if((integer6.dataLength==1)&&(integer6.data[0]==1)){flag2=true;}for(intm=0;!flag2&&(m<num);m++){if(integer6==integer2){flag2=true;break;}integer6=(integer6*integer6)%integer;}if(!flag2){returnfalse;}}returntrue;}publicvoidsetBit(uintbitNum){uintindex=bitNum>>5;bytenum2=(byte)(bitNum&0x1f);uintnum3=((uint)1)<<num2;this.data[index]|=num3;if(index>=this.dataLength){this.dataLength=((int)index)+1;}}privatestaticintshiftLeft(uint[]buffer,intshiftVal){intnum=0x20;intlength=buffer.Length;while((length>1)&&(buffer[length-1]==0)){length--;}for(inti=shiftVal;i>0;i-=num){if(i<num){num=i;}ulongnum4=0L;for(intj=0;j<length;j++){ulongnum6=buffer[j]<<num;num6|=num4;buffer[j]=(uint)(num6&0xffffffffL);num4=num6>>0x20;}if((num4!=0L)&&((length+1)<=buffer.Length)){buffer[length]=(uint)num4;length++;}}returnlength;}privatestaticintshiftRight(uint[]buffer,intshiftVal){intnum=0x20;intnum2=0;intlength=buffer.Length;while((length>1)&&(buffer[length-1]==0)){length--;}for(inti=shiftVal;i>0;i-=num){if(i<num){num=i;num2=0x20-num;}ulongnum5=0L;for(intj=length-1;j>=0;j--){ulongnum7=buffer[j]>>num;num7|=num5;num5=buffer[j]<<num2;buffer[j]=(uint)num7;}}while((length>1)&&(buffer[length-1]==0)){length--;}returnlength;}privatestaticvoidsingleByteDivide(BigIntegerbi1,BigIntegerbi2,BigIntegeroutQuotient,BigIntegeroutRemainder){uint[]numArray=newuint[70];intnum=0;for(inti=0;i<70;i++){outRemainder.data[i]=bi1.data[i];}outRemainder.dataLength=bi1.dataLength;while((outRemainder.dataLength>1)&&(outRemainder.data[outRemainder.dataLength-1]==0)){outRemainder.dataLength--;}ulongnum3=bi2.data[0];intindex=outRemainder.dataLength-1;ulongnum5=outRemainder.data[index];if(num5>=num3){ulongnum6=num5/num3;numArray[num++]=(uint)num6;outRemainder.data[index]=(uint)(num5%num3);}index--;while(index>=0){num5=(outRemainder.data[index+1]<<0x20)+outRemainder.data[index];ulongnum7=num5/num3;numArray[num++]=(uint)num7;outRemainder.data[index+1]=0;outRemainder.data[index--]=(uint)(num5%num3);}outQuotient.dataLength=num;intnum8=0;intnum9=outQuotient.dataLength-1;while(num9>=0){outQuotient.data[num8]=numArray[num9];num9--;num8++;}while(num8<70){outQuotient.data[num8]=0;num8++;}while((outQuotient.dataLength>1)&&(outQuotient.data[outQuotient.dataLength-1]==0)){outQuotient.dataLength--;}if(outQuotient.dataLength==0){outQuotient.dataLength=1;}while((outRemainder.dataLength>1)&&(outRemainder.data[outRemainder.dataLength-1]==0)){outRemainder.dataLength--;}}publicboolSolovayStrassenTest(intconfidence){BigIntegerinteger;if((this.data[0x45]&0x80000000)!=0){integer=-this;}else{integer=this;}if(integer.dataLength==1){if((integer.data[0]==0)||(integer.data[0]==1)){returnfalse;}if((integer.data[0]==2)||(integer.data[0]==3)){returntrue;}}if((integer.data[0]&1)==0){returnfalse;}intnum=integer.bitCount();BigIntegera=newBigInteger();BigIntegerinteger3=integer-1;BigIntegerexp=integer3>>1;Randomrand=newRandom();for(inti=0;i<confidence;i++){boolflag=false;while(!flag){intbits=0;while(bits<2){bits=(int)(rand.NextDouble()*num);}a.genRandomBits(bits,rand);intdataLength=a.dataLength;if((dataLength>1)||((dataLength==1)&&(a.data[0]!=1))){flag=true;}}BigIntegerinteger5=a.gcd(integer);if((integer5.dataLength==1)&&(integer5.data[0]!=1)){returnfalse;}BigIntegerinteger6=a.modPow(exp,integer);if(integer6==integer3){integer6=-1;}BigIntegerinteger7=Jacobi(a,integer);if(integer6!=integer7){returnfalse;}}returntrue;}publicBigIntegersqrt(){uintnum4;uintnum=(uint)this.bitCount();if((num&1)!=0){num=(num>>1)+1;}else{num=num>>1;}uintnum2=num>>5;bytenum3=(byte)(num&0x1f);BigIntegerinteger=newBigInteger();if(num3==0){num4=0x80000000;}else{num4=((uint)1)<<num3;num2++;}integer.dataLength=(int)num2;for(inti=((int)num2)-1;i>=0;i--){while(num4!=0){integer.data[i]^=num4;if((integer*integer)>this){integer.data[i]^=num4;}num4=num4>>1;}num4=0x80000000;}returninteger;}publicstringToHexString(){stringstr=this.data[this.dataLength-1].ToString("X");for(inti=this.dataLength-2;i>=0;i--){str=str+this.data[i].ToString("X8");}returnstr;}publicoverridestringToString(){returnthis.ToString(10);}publicstringToString(intradix){if((radix<2)||(radix>0x24)){thrownewArgumentException("Radix must be >= 2 and <= 36");}stringstr="ABCDEFGHIJKLMNOPQRSTUVWXYZ";stringstr2="";BigIntegerinteger=this;boolflag=false;if((integer.data[0x45]&0x80000000)!=0){flag=true;try{integer=-integer;}catch(Exception){}}BigIntegeroutQuotient=newBigInteger();BigIntegeroutRemainder=newBigInteger();BigIntegerinteger4=newBigInteger((long)radix);if((integer.dataLength!=1)||(integer.data[0]!=0)){while((integer.dataLength>1)||((integer.dataLength==1)&&(integer.data[0]!=0))){singleByteDivide(integer,integer4,outQuotient,outRemainder);if(outRemainder.data[0]<10){str2=outRemainder.data[0]+str2;}else{str2=str[((int)outRemainder.data[0])-10]+str2;}integer=outQuotient;}if(flag){str2="-"+str2;}returnstr2;}return"0";}publicvoidunsetBit(uintbitNum){uintindex=bitNum>>5;if(index<this.dataLength){bytenum2=(byte)(bitNum&0x1f);uintnum3=((uint)1)<<num2;uintnum4=uint.MaxValue^num3;this.data[index]&=num4;if((this.dataLength>1)&&(this.data[this.dataLength-1]==0)){this.dataLength--;}}}}