import java.io.*; import java.math.*; //==========================================================C // OS(Quadratic Sieve) Function Program C // 2次ふるい法javaプログラム ふるい改良3(改良2+(4)追加) C // + 行列改良2(行列をbitで表示) C //  (1) ふるいは倍精度浮動小数点を使用し、本来のふるい処理 C // (2) 素数基底に-1を追加 C // (3) 素数基底のh倍の素数も2個存在すればふるいで採用 C // (4) f(x)=x^2-Nの基底での分解方法の改良(ふるいを応用) C //----------------------------------------------------------C // 1. M = (int)sqrt(N) C // using Bsqrt C // 2. Seting the Factor Base C // Prime Table: PTB[NP] C // Factor Base: FTB[NB] C // 3. Sieving by QS C // (1) Setting sieving base value C // Sieving base value: SBV[NS][3] C // (2) Siving for over factor base C // Sparase sieving Matrix: SQS[NT][NG] C // (3) Sieving C // Sieved Sparse Matrix: MQS[ND][spM][2] C //----------------------------------------------------------C // Written by Yasunori Ushiro , 2008/11/23 C // ( Tokyo Kougei University ) C // 後 保範: 東京工芸大学 C //==========================================================C public class QS5{ //==========================================================C // Global data (Constant and Work area) C //==========================================================C // テーブル(素数、基底、ふるい) public final static int bno=32, sbM=250; public final static int spM=41, szM=7900, szN=8300, szwk=1000010; public final static int szNP=150010, szNB=75010, szdt=300010; public static int PTB[] = new int[szNP]; // 素数テーブル public static int FTB[] = new int[szNB]; // 分解基底テーブル(-1は含まず) public static int TTB[] = new int[szNB]; // 分解基底の利用数テーブル(同上) public static int UTB[] = new int[szM]; // 利用基底テーブル(-1を含む) public static int SBV[][] = new int[szNB][3]; // ふるいテーブル(P,Q,S) // f(x)=x^2-N分解テーブル (Add 2008.11.23) public int SBF[][] = new int[szN][2]; // 基底分解テーブル(S1,S2),なし:-1 public int FCT[] = new int[spM]; // 分解基底要因、先頭は要因数 public int FCN[][] = new int[spM][2]; // 同上+ベキ数、先頭は要因数 // ふるい実行テーブル、STB[*][0]は|X*X-N|, STB[*][1]はふるい累積値 public static double STB[][] = new double[2][szwk]; // 基本基底+利用基底で分解されたふるい行列 public static int MQS[][][] = new int[szN][spM][2]; // *[0]: 基底番号, *[1]: 基底のベキ数 public static int MNO[] = new int[szN]; // ふるい行列の各行の数 public static BigInteger MX[] = new BigInteger[szN]; // 対応する値X=M+x // 基本基底以外の分解基底で分解されたふるいデータ public static int MSN[][] = new int[szdt][2]; // L:分解基底の番号(>=NBS) (Change 2008.11.23) public static BigInteger MSV[] = new BigInteger[szdt]; // 対応する値X=M+x // 行列計算用 public static int VC[] = new int[szN]; // 軸交換ベクトル public static int VP[] = new int[szM]; // 枢軸ベクトル public static int AM[][] = new int[szN][sbM]; // 0-1行列(ビット圧縮) public static int BAM[][] = new int[szN][bno]; // ビット展開ワーク public static int BWK[] = new int[szN]; // ビット圧縮ワーク // 因数分解用 public static int LN[] = new int[szM]; // 従属する行番号 public static int PW[] = new int[szM]; // 利用基底のベキ数 public static int PK[] = new int[szNB]; // 分解ワーク public static BigInteger FactV[][] = new BigInteger[700][4]; // X*X-Y*Y=0 mod N // [0]:X, [1]:Y; [2]:P=GCD(X+Y,N), [3];N/P public int NOS = 0, NH = 0; // ふるいの総数、分解基底ふるいで得たデータ数 public int NSD, NBU; // 利用基底で得たデータ数、利用基底の数 public int NNZ=0; // 分解基底ふるいで取得に失敗したデータ数 public long tims=0; //==========================================================C public BigInteger QS(BigInteger N, int NP, int LP, int h, int NV[]) //==========================================================C // OS(Quadratic Sieve) Program C // 2次ふるい法javaプログラム ふるい改良1  C //----------------------------------------------------------C // N Bint, In, Input Value for Factorizing C // NP int, In, Size of Prime Table C // LP int, In, Size of one sieve deta C // h int, In, NBS=NB/h C // NV[5] int, Out, NV[0]=NB, NV[1]=NDD, NV[2]=NS C // NV[3]=NBS, NV[4]=ND C // return Bint, Out, M=sqrt(N) C //----------------------------------------------------------C // NP : 素数基底の総数 C // NB : 分解基底の総数(-1は含まず) C // NBS : ふるいに使用する基本基底の数(=NB/h) C // NBU : 利用基底の数(利用した分解基底で-1を含む) C // NS : ふるいテーブルの数 C // ND : 基本基底だけで得られたデータの数 C // NDD : ふるいで得られたデータの総数 C // NH : 全分解基底のふるいで得られたデータの数 C //----------------------------------------------------------C // Written by Yasunori Ushiro , 2008/09/15 C // Ver.1 2008.11.23 Change from Bfact to Divide C // ( Tokyo Kougei University ) C // 後 保範: 東京工芸大学 C //==========================================================C { int IWK[] = new int[100000]; int NIWK = 100000, BV; int NBS, NBU=0; long t1, t2; int Debug = 0; // M = (int)sqrt(N) t1 = System.currentTimeMillis(); BigInteger M = Bsqrt(N); if(Debug==1) { System.out.println("M="+M.toString()); } // Seting the Factor Base TPRIM(NP); int NB = BASE(N, NP); NBS = NP/(2*h); if(h == 1) NBS = NB; BV = 11*FTB[NBS-1] + 1 ; int NS = SBASE(N, M, NBS, BV); t2 = System.currentTimeMillis(); double T1 = (t2 - t1)*1.0e-3; // System.out.println("基底計算時間="+T1); if(Debug == 1) { for (int k=0; k NB ) C //----------------------------------------------------------C // Written by Yasunori Ushiro , 2008/09/15 C // Ver.1 2008.11.23 Change from Bfact to Divide C // ( Tokyo Kougei University ) C //==========================================================C { int k, SV, ID, NTD, NTS, ND=0; int out=0; double DV[] = new double[3]; double cpu, TL = 5.0; BigInteger MS, BLP, M2N; String s1; long t1, t2, tt1, tt2, tt3, Tim1, Tim2, Tim3; int Debug = 0; // Initial set s1 = Integer.toString(LP); BLP = new BigInteger(s1); s1 = N.toString(); DV[0] = Double.parseDouble(s1); s1 = M.toString(); DV[1] = Double.parseDouble(s1); M2N = M.multiply(M); M2N = M2N.subtract(N); s1 = M2N.toString(); DV[2] = Double.parseDouble(s1); // Clear TTB for (k=0; k 0) System.out.println(ND+" "+NSD+" "+NBS+" "+NBU); // Sieving by QS Dsieve(DV, NS, SV*ID, LP); // Select and set matrix s1 = Integer.toString(SV*ID); MS = new BigInteger(s1); MS = M.add(MS); tt2 = System.currentTimeMillis(); Tim1 += tt2 - tt1; // Seving by QS ND = Ssieve(LP, ND, N, MS, NB, NBS, SV*ID); tt3 = System.currentTimeMillis(); Tim2 += tt3 - tt2; if(Debug > 0) { for (int i=0; i= 2) { NBU ++; NSD += TTB[k]; } } if(ID > 0) SV += LP; ID = -ID; NOS += LP; t2 = System.currentTimeMillis(); cpu = (t2 - t1)*1.0e-3; if(cpu > TL) { NTD = ND + NSD; NTS = NBS + NBU; System.out.println("途中経過: 取得="+ NTD+", 基底="+NTS); t1 = t2; } Tim3 += t2 - tt3; } if(out > 0) { float CPU1 = (float)(Tim1*1.0e-3); float CPU2 = (float)(Tim2*1.0e-3); float CPU3 = (float)(Tim3*1.0e-3); float CPU4 = (float)(tims*1.0e-3); System.out.println("Sive Time="+CPU1+" "+CPU2+" "+CPU3); System.out.println("Ssive Time="+CPU4); } return ND;} //==========================================================C public int Ssieve(int LP, int NO, BigInteger N, BigInteger MS, int NB, int NBS, int IVI) //==========================================================C // Sieving by QS C // select STB and set MQS(sieved sparce matrix) C // STB[0][*] = X*X - N C // STB[1][*] = multiply for base factor C //----------------------------------------------------------C // LP int, In, Size of one sieve deta C // NO int, In, Number of old selected sieve data C // N Bint, In, Number for Factorizing C // MS Bint, In, Start value (M+SV) C // NB int, In, Size of Factor Base (FTB[NB]) C // NBS int, In, Size of basic Factor Base C // IVI int, In, Start value (M+SV) C // return int, out, Number of new selected sieve data C //----------------------------------------------------------C // Written by Yasunori Ushiro , 2008/09/21 C // Ver.1 2008.11.23 Change from Bfact to Divide C // ( Tokyo Kougei University ) C //==========================================================C { int k, j, NN, IP, IV, VB, NZ, IVP; String s1; BigInteger Zero = new BigInteger("0"); BigInteger One = new BigInteger("1"); BigInteger X, X2, NF; long t1, t2; // Initial set t1 = System.currentTimeMillis(); X = MS; NN = NO; VB = FTB[NB-1]; // Main Loop for (k=0; k 0) { // MQS[NN][NOM][0] = j + 1; // MQS[NN][NOM][1] = PK[j]; // NOM++; } // } MX[NN] = X; MNO[NN] = NEN + NOM; NN++; } else // Set MSN, MSV and TTB vector { s1 = NF.toString(); IV = Integer.parseInt(s1); // double sd = Double.parseDouble(s1); if(IV <= VB) { NZ = Search(IV, NB, FTB); if(NZ != -1) { MSN[NH][0] = NZ; MSN[NH][1] = IVP; MSV[NH] = X; TTB[NZ] += 1; NH ++; } else { NNZ++; } } else { NNZ++; } } } X = X.add(One); } t2 = System.currentTimeMillis(); tims += t2 - t1; return NN; } //==========================================================C public void Dsieve(double DV[], int NS, int SV, int LP) //==========================================================C // Sieving by QS C // set STB(Sieving table) using C // STB[0][*] = X*X - N C // STB[1][*] = multiply for base factor C //----------------------------------------------------------C // DV[3] dbl, In, DV[0]=N, DV[1]=M, DV[2]=M^2-N C // NS int, In, Size of SBV(Sieving base value) C // SV int, In, Start Value for sieving C // LP int, In, Size of one sieve deta C //----------------------------------------------------------C // Written by Yasunori Ushiro , 2008/09/15 C // ( Tokyo Kougei University ) C //==========================================================C { int k, j, Q, ST; double DN, DM, DM2N, X, P; // Initial set DN = DV[0]; DM = DV[1]; DM2N = DV[2]; X = SV; for (j=0; j= 2) { UTB[NBU] = FTB[k]; NBU++; } } // Set MQX, MX // Set for (k=0; k= 2) { int NOM = 0; X = MSV[k]; X2 = X.multiply(X); X2 = X2.subtract(N); if(X2.compareTo(Zero) < 0) { MQS[NDD][NOM][0] = 0; MQS[NDD][NOM][1] = 1; NOM ++; } X2 = X2.abs(); // BigInteger NF = BFact(X2, NBS); BigInteger NF = Divide(X2, NBS, IVP); if(Bmodi(NF, LV) == 0) { int NZ = Search(LV, NBU, UTB); int NEN = FCN[0][0]; for (j=0; j 0) { // MQS[NDD][NOM][0] = j + 1; // MQS[NDD][NOM][1] = PK[j]; // NOM++; } } NOM = NEN + NOM; MQS[NDD][NOM][0] = NZ; MQS[NDD][NOM][1] = 1; NOM++; MX[NDD] = X; MNO[NDD] = NOM; NDD++; } } } return NDD; } //==========================================================C public int Search(int V, int N, int TBL[]) //==========================================================C // Table search C // V = TBL[L], L is a output C //----------------------------------------------------------C // V int, in, Searching Value C // N int, in, Size of TBL[] C // TBL[N] int, in, Searching Table C // return int, out, Searched Number C //----------------------------------------------------------C // Written by Yasunori Ushiro , 2008/08/30 C // ( Tokyo Kougei University ) C //==========================================================C { int l, m, h; int L = -1; // Search l = 0; h = N; m = h/2; while (h - l > 0) { if(h-l == 1) { if(V == TBL[l]) L = l; if(V == TBL[h]) L = h; break; } if(V == TBL[m] ) { L = m; break; } if(V > TBL[m] ) { l = m; m = (h+m)/2; } else { h = m; m = (l+m)/2; } } return L; } //==========================================================C public void TPRIM(int NP) //==========================================================C // Setting the Table of Prime Numbers C // PTB(k) = k's Prime Number C // k=0,1,...,NP-1, PTB(1)=2, PTB(2)=3, PTB(3)=5,... C //----------------------------------------------------------C // NP int, In, Size of Prime Table C //----------------------------------------------------------C // Written by Yasunori Ushiro , 2008/01/12 C // ( Tokyo Kougei University ) C //==========================================================C { int i, j, j1,k; int IWK[] = new int[10000]; int NIWK=10000; int NO, LPM, NE, NH, NS, NS1; int NIT[] = {2,3,5,7,11,13,17,19,23,29,31,37,41,43}; // Initial Set NO = 14; LPM = 43; for (i=0; i NH) { break; } NS1 = j - (LPM+2)%j; if(NS1 == j) { NS1 = 0; } NS = (j*(NS1%2) + NS1)/2; for (i=NS; i= NP) { break; } } } } //==========================================================C public BigInteger Divide(BigInteger X, int NB, int IV) //==========================================================C // Factorization with Primes by SBF C // X=FTB[FCN[1][0]]^FCN[1][1]*...*FTB[FCN[N-1][0]]^ C // FCN[N-1][1]*Y C // N=FCN[0][0] C //----------------------------------------------------------C // X Big, In, Target value C // NB int, In, Size of Factor Base C // IV int, In, Relative value; x=M+IV C // FCN[][] int, Out, Power of Factor Base C // return Big, Out, No factorized value (Y) C //----------------------------------------------------------C // Written by Yasunori Ushiro , 2008/11/23 C // ( Tokyo Kougei University ) C //==========================================================C { BigInteger Y, T, S; int k, IW, NO; String s1; BigInteger Zero = new BigInteger("0"); Y = X; // set FCT[k]; X=x^2-Nが分解される基底番号、FCT[0]は個数 NO = 0; for (k=0; k set SBV C // SBV[*][0] = P in FTB C // SBV[*][1] = Q = P^l (l=1,2,...) C // SBV[*][2] = M-S (mod Q) (0 =< S < Q) C //----------------------------------------------------------C // N Bint, In, Input Value for Factorizing C // M Bint,In, M=sqrt(N) C // NB int, In, Size of Factor Base C // MV int, In, Maximum value for sieving value C // return int, Out, Size of SBV(Sieving base value) C //----------------------------------------------------------C // Written by Yasunori Ushiro , 2008/09/27 C // ( Tokyo Kougei University ) C //==========================================================C { int NS = 0; int k, j, S2, Nin; int P, Q, IM, IP; double D, D2; // main Loop for (k=0; k 0)) { Nin = Bmodi(N, Q); IM = Bmodi(M, Q); for (j=0; j set FTB C //----------------------------------------------------------C // N Bint, In, Input Value for Factorizing C // NP int, In, Size of Prime Table C // return int, Out, Size of Factor Base C //----------------------------------------------------------C // Written by Yasunori Ushiro , 2008/09/12 C // ( Tokyo Kougei University ) C //==========================================================C { int NB = 0; int k, P, P2; String s1, s2; BigInteger BP, BP2, Q; BigInteger One = new BigInteger("1"); // main Loop for (k=0; k set FTB C //----------------------------------------------------------C // N Bint, In, Input Value for Factorizing C // NP int, In, Size of Prime Table C // return int, Out, Size of Factor Base C //----------------------------------------------------------C // Written by Yasunori Ushiro , 2008/01/12 C // ( Tokyo Kougei University ) C //==========================================================C { int NB = 0; int k, j, S2, Nin; // main Loop for (k=0; k=8) m = 6; if(n >=30) m = 8; // BigInteger t = sqrt(x) by Newton Method if(t.compareTo(Zero) != 0) { for (k = 1; k <= m; k++) { w = t.multiply(t); u = w.add(x); w = t.add(t); t = u.divide(w); } } t = t.add(One); return t; } //==========================================================C // Gauss Elimination Program with 0-1 C // Make matrix AM(0-1) from MQS C // Gauss Elimination A with bits C // A=AM[N][M] C //----------------------------------------------------------C // N int, in, Number of rows for AM C // M int, in, Number of columns for AM C // return int, Out, ID >= 1; Number of dependency C // = 0; no-dependency C //----------------------------------------------------------C // Written by Yasunori Ushiro , 2008/09/30 C // ( Tokyo Kougei University ) C //==========================================================C public int Gauss(int N, int M) throws Exception { int ID, IP, IW; int k, kb, kl, j, i, ii, kk, kg; int IO=0; // Setting Output File /* FileOutputStream fo = new FileOutputStream("Gauss.txt"); PrintWriter out = new PrintWriter(fo,true); */ // Make matrix AM(0-1) with bits from MQS int MBT = SetAM(N, M); // Output Matrix /* if(IO >=1) { out.println("Input"); for (i=0; i=1){ out.println("BAM Before"); for (i=0; i= M) { break; } IP = 0; if(BAM[kk][kl] == 0) { // Search Pivot IP = -1; for (i=kk+1; i IP if(IP != -1) { IW = VC[IP]; VC[IP] = VC[kk]; VC[kk] = IW; // Exchange BAM for (j=0; j skip if(IP != -1) { VP[k] = VC[kk]; for (i=kk+1; i=1){ out.println("AM After, i="+i); for (ii=0; ii=1) { out.println("kb="+kb); for (i=kg; i 0) { ID = N - kk; } return ID; } //==========================================================C // Set 0-1 matrix AM with bits C // Make 0-1 matrix AM from MQS C //----------------------------------------------------------C // N int, in, Number of rows for AM C // M int, in, Number of columns for AM C // return int, out, Number of columns/bits C //----------------------------------------------------------C // Written by Yasunori Ushiro , 2008/09/30 C // ( Tokyo Kougei University ) C //==========================================================C public int SetAM(int N, int M) { int i, j, k, jj, MBT, MBB, Bit; MBT = (M + bno - 1)/bno; MBB = MBT*bno; // Main loop for (k=0; k>> js) & One; } } } //==========================================================C // 対象列区間のintをbitに戻す C // Change from BAM[kk:N][*] to AM[kk:N][kb] C //----------------------------------------------------------C // N int, in, Number of rows for AM C // kk int, in, current row for AM, BAM C // kb int, in, current column for AM C //----------------------------------------------------------C // Written by Yasunori Ushiro , 2008/09/24 C // ( Tokyo Kougei University ) C //==========================================================C public void BtoAM(int N, int kk, int kb) { int k, j, js, Bit, One=1; for (k=kk; k= M) { break; } js = bno - i - 1; BWK[k] = (Bit >>> js) & One; k++; } } } //==========================================================C // Factor : Factorizeing by the QS C // using: MQS[N][spM], FTB[M], AM[N][M], VC[N], VP[M] C // output: LN[NO][], PW[NO][M] C //----------------------------------------------------------C // NV Bint, In, Input Value for Factorizing C // MV Bint, In, MV=sqrt(NV), Number of QS starting C // N int, In, Number of rows for MQS, EM C // M int, In, Number of columns for EM C // NO int, In, Number of factorized value C //----------------------------------------------------------C // Written by Yasunori Ushiro , 2008/09/30 C // ( Tokyo Kougei University ) C //==========================================================C public void Factor(BigInteger NV, BigInteger MV, int N, int M, int NO) { int k, j, i, NN, NOP, CN; BigInteger X, Y, XV, YV, YI; BigInteger One = new BigInteger("1"); String s1; // Set to dependet column for (k=0; k= 1) { s1 = Integer.toString(IPW); YI = new BigInteger(s1); s1 = Integer.toString(UTB[i]); YV = new BigInteger(s1); YV = YV.modPow(YI, NV); Y = Y.multiply(YV); Y = Y.mod(NV); } } FactV[k][0] = X; FactV[k][1] = Y; // Comput GCD(X+Y,NV) and GCD(X-Y,NV) XV = X.add(Y); X = XV.gcd(NV); Y = NV.divide(X); FactV[k][2] = X; FactV[k][3] = Y; } } }