//Filename: PollardStrassen_multiprec.cpp //Created by Lillian Zeng //baby steps giant steps algorithm for integer factorization /*This program should be link against gmp library and mpfr library, for example g++ PollardStrassen_multiprec.cpp -lgmp -lgmpxx -lmpfr */ #include #include #include #include #include #include #include using namespace std; mp_rnd_t rnd = GMP_RNDN; void buildup1 (size_t k, size_t r, mpz_t n, mpz_t ***M); //10.3 step 1: building up subproduct tree void buildup2 (mpz_t *u,size_t k, size_t r, mpz_t n, mpz_t ***M);// 10.3 building up subproduct tree for step 2 void multi (mpz_t *a, mpz_t * b, mpz_t * ans, size_t deg, mpz_t n);//naive way for polynomial multiplication void FastMultiplication(mpz_t n,mpz_t*a,mpz_t* b,size_t deg, mpz_t *c); void FFT(size_t num,const size_t length,mpfr_t **f, mpfr_t *w,size_t deg,mpfr_t **ans, size_t index,size_t multiple); void IFFT(size_t num,const size_t length, mpfr_t **alpha, mpfr_t *w,mpfr_t **ans); void rem(mpz_t *a,mpz_t *b,mpz_t *rem,size_t dA,size_t dB,size_t &dR, mpz_t n);//remainder of two polynomials a/b void fastMultiEval(mpz_t *f,size_t k, size_t r,mpz_t * fu,mpz_t ***M, mpz_t n);//10.7 step 2: fast multipoint evaluation void godown(mpz_t *f,mpz_t *u,mpz_t ***M,size_t deg,mpz_t *fu,size_t k,mpz_t n,size_t start); //10.5 going down subproduct tree int main() { size_t precision=200; //may be set differently based on how big the integer to be factored is mpfr_set_default_prec(precision); cout<<"precision:"<0&&mpz_cmp(gcd[i],min)<0) {mpz_set(min,gcd[i]); } } mpz_add_ui(temp,n,1); if(mpz_cmp(min,temp)==0){ gmp_printf("%Zd is a prime number \n",n); return 0;} gmp_printf("The least prime factor of %Zd is %Zd \n",n,min); //clear mpz_clear(n); mpz_clear(temp); mpz_clear(min); for(size_t i=0;ideg){j=k-deg;} for(j;j<=min(deg,k);j++) { mpz_init_set(ANS,ans[k]); mpz_init_set(A,a[j]); mpz_init_set(B,b[k-j]); mpz_mul(ans[k],A,B); mpz_add(ans[k],ans[k],ANS); mpz_mod(ans[k],ans[k],n); } } mpz_clear(A);mpz_clear(B);mpz_clear(ANS); return; } void FastMultiplication(mpz_t n,mpz_t*a,mpz_t* b, size_t deg, mpz_t *c) { mpfr_t PI; mpfr_init(PI); mpfr_const_pi(PI,rnd); mpfr_t temp1; mpfr_init(temp1); // step1: compute primitive dCth root of unity, w size_t dC=2*deg; //length of c-1 mpfr_t theta; mpfr_init(theta); mpfr_t *w; w = new mpfr_t [2]; mpfr_init(w[0]); mpfr_init(w[1]); mpfr_mul_ui(theta,PI,2,rnd); mpfr_div_ui(theta,theta,dC,rnd); mpfr_sin_cos(w[1],w[0],theta,rnd); mpfr_t **a1; mpfr_t **b1; mpfr_t **c1; a1 = new mpfr_t *[dC+1]; b1 = new mpfr_t *[dC+1]; c1 = new mpfr_t *[dC+1]; for(size_t i=0;i<=dC;i++) { a1[i] = new mpfr_t [2];b1[i] = new mpfr_t [2];c1[i]=new mpfr_t [2]; mpfr_init(a1[i][0]); mpfr_init(a1[i][1]); mpfr_init(b1[i][0]); mpfr_init(b1[i][1]); mpfr_init(c1[i][0]); mpfr_init(c1[i][1]); mpfr_set_ui(a1[i][0],0,rnd); mpfr_set_ui(b1[i][0],0,rnd); mpfr_set_ui(a1[i][1],0,rnd); mpfr_set_ui(b1[i][1],0,rnd); if(i<=deg) { mpfr_set_z(a1[i][0],a[i],rnd); mpfr_set_z(b1[i][0],b[i],rnd); } } //step2: find the DFT of a and b mpfr_t **A; mpfr_t **B; mpfr_t **C; A =new mpfr_t *[dC+1]; B =new mpfr_t *[dC+1]; C =new mpfr_t *[dC+1]; for(size_t i=0; i<=dC;i++) { A[i] = new mpfr_t [2]; B[i] = new mpfr_t [2]; C[i] = new mpfr_t [2]; mpfr_init(A[i][0]);mpfr_init(A[i][1]); mpfr_init(B[i][0]);mpfr_init(B[i][1]); mpfr_init(C[i][0]);mpfr_init(C[i][1]); } FFT(dC,dC,a1,w,dC,A,0,1); FFT(dC,dC,b1,w,dC,B,0,1); //step 3: pointwise multiplication for(size_t i=0; i<=dC;i++) { //C=A*B mpfr_mul(C[i][0],A[i][0],B[i][0],rnd); mpfr_mul(temp1,A[i][1],B[i][1],rnd); mpfr_sub(C[i][0],C[i][0],temp1,rnd); mpfr_mul(C[i][1],A[i][0],B[i][1],rnd); mpfr_mul(temp1,A[i][1],B[i][0],rnd); mpfr_add(C[i][1],C[i][1],temp1,rnd); } //step4: inverse of the result IFFT(dC, dC, C,w,c1); mpfr_set_ui(temp1,1,rnd); mpfr_div_ui(temp1,temp1,2,rnd); for(size_t i=0;i=0 &&stay!=0) { if (dR==dB+i && mpz_cmp_ui(r[dR],0)!=0) { mpz_set(q,r[dR]); int stay2=1; size_t j=dR; while(j>=i && stay2!=0) { //r[j]=(r[j]-q*b[j-i])%n; mpz_mul(temp,q,b[j-i]); mpz_sub(temp,r[j],temp); mpz_mod(temp,temp,n); mpz_set(r[j],temp); if(j>0){j--;}else{stay2=0;} } mpz_set_ui(r[dR],0); dR=dR-1; } else { dR=dR-1; } if(i>0){ i--;}else{stay=0;} } dr=dR; for(size_t i =0; i<=dr;i++) { mpz_init_set(rem[i],r[i]); mpz_mod(rem[i],rem[i],n); } mpz_clear(temp); return; } void fastMultiEval(mpz_t *f,size_t k, size_t r,mpz_t * fu,mpz_t ***M, mpz_t n) { mpz_t *u; u = new mpz_t [r]; mpz_t temp; for(int i=0;i