/* See Cohen 1.5.2 */ int cornacchia(mpz_t x, mpz_t y, mpz_t D, mpz_t p) { int result = 0; mpz_t a, b, c, d; if (mpz_jacobi(D, p) < 0) /* No solution */ return 0; mpz_init(a); mpz_init(b); mpz_init(c); mpz_init(d); sqrtmod(x, D, p, a, b, c, d); mpz_set(a, p); mpz_set(b, x); mpz_sqrt(c, p); while (mpz_cmp(b,c) > 0) { mpz_set(d, a); mpz_set(a, b); mpz_mod(b, d, b); } mpz_mul(a, b, b); mpz_sub(a, p, a); /* a = p - b^2 */ mpz_abs(d, D); /* d = |D| */ if (mpz_divisible_p(a, d)) { mpz_divexact(c, a, d); if (mpz_perfect_square_p(c)) { mpz_set(x, b); mpz_sqrt(y, c); result = 1; } } mpz_clear(a); mpz_clear(b); mpz_clear(c); mpz_clear(d); return result; }
int isprime( mpz_t n ) { mpz_t i, n2, tmp; int d, ret; /* 1は素数ではない */ if( mpz_cmp_ui( n, 1 ) == 0 ) return( 0 ); /* 2,3は素数 */ if( mpz_cmp_ui( n, 2 ) == 0 || mpz_cmp_ui( n, 3 ) == 0 ) return( 1 ); /* 2,3で割り切れたら合成数 */ if( mpz_even_p( n ) || mpz_divisible_ui_p( n, 3 ) ) return( 0 ); mpz_init( i ); mpz_init( n2 ); mpz_init( tmp ); /* sqrt(n)+1を求める */ mpz_sqrt( n2, n ); /* n2以下の2,3の倍数以外での剰余が0かどうか調べる */ d = 2; mpz_set_ui( i, 5 ); ret = 1; while( mpz_cmp( i, n2 ) <= 0 ) { if( mpz_divisible_p( n, i ) ) { ret = 0; break; } mpz_add_ui( tmp, i, d ); mpz_set( i, tmp ); d = ( d == 2 ? 4 : 2 ); } mpz_clear( i ); mpz_clear( n2 ); mpz_clear( tmp ); return( ret ); }
unsigned int factorCount(mpz_t number) { mpz_t maxNumber; mpz_t counter; mpz_t q; mpz_t r; unsigned int result = 0; //if (mpz_cmp_ui(number, 1) == 0) // return 1; mpz_init_set(maxNumber, number); mpz_init(r); mpz_init(q); mpz_sqrt(maxNumber, number); for (mpz_init_set_ui(counter, 1); mpz_cmp(counter, maxNumber) <= 0; mpz_add_ui(counter, counter, 1)) if (mpz_divisible_p(number, counter)) result += 2; return result; }
static void find_factors(mpz_t base) { char *str; int res; mpz_t i; mpz_t half; mpz_t two; mpz_init_set_str(two, "2", 10); mpz_init_set_str(i, "2", 10); mpz_init(half); mpz_cdiv_q(half, base, two); str = mpz_to_str(base); if (!str) return; /* * We simply return the prime number itself if the base is prime. * (We use the GMP probabilistic function with 10 repetitions). */ res = mpz_probab_prime_p(base, 10); if (res) { printf("%s is a prime number\n", str); free(str); return; } printf("Trial: prime factors for %s are:", str); free(str); do { if (mpz_divisible_p(base, i) && verify_is_prime(i)) { str = mpz_to_str(i); if (!str) return; printf(" %s", str); free(str); } mpz_nextprime(i, i); } while (mpz_cmp(i, half) <= 0); printf("\n"); }
void *SumThread(void *context) { PSUM_THREAD_CONTEXT tcontext = (PSUM_THREAD_CONTEXT)context; while (mpz_cmp(tcontext->factor, tcontext->end) < 0) { //Check if the number is divisible by the factor if (mpz_divisible_p(tcontext->num, tcontext->factor) != 0) { pthread_mutex_lock(tcontext->termMutex); //Add the factor mpz_add(*tcontext->sum, *tcontext->sum, tcontext->factor); //Add the other factor in the pair mpz_divexact(tcontext->otherfactor, tcontext->num, tcontext->factor); mpz_add(*tcontext->sum, *tcontext->sum, tcontext->otherfactor); //Bail early if we've exceeded our number if (mpz_cmp(*tcontext->sum, tcontext->num) > 0) { pthread_mutex_unlock(tcontext->termMutex); break; } pthread_mutex_unlock(tcontext->termMutex); } //This is a valid cancellation point pthread_testcancel(); mpz_add_ui(tcontext->factor, tcontext->factor, 1); } pthread_mutex_lock(tcontext->termMutex); (*tcontext->termCount)++; pthread_cond_signal(tcontext->termVar); pthread_mutex_unlock(tcontext->termMutex); pthread_exit(NULL); }
static PyObject * GMPy_MPZ_Function_IsDivisible(PyObject *self, PyObject *args) { unsigned long temp; int error, res; MPZ_Object *tempx, *tempd; if (PyTuple_GET_SIZE(args) != 2) { TYPE_ERROR("is_divisible() requires 2 integer arguments"); return NULL; } if (!(tempx = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL))) { return NULL; } temp = GMPy_Integer_AsUnsignedLongAndError(PyTuple_GET_ITEM(args, 1), &error); if (!error) { res = mpz_divisible_ui_p(tempx->z, temp); Py_DECREF((PyObject*)tempx); if (res) Py_RETURN_TRUE; else Py_RETURN_FALSE; } if (!(tempd = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 1), NULL))) { TYPE_ERROR("is_divisible() requires 2 integer arguments"); Py_DECREF((PyObject*)tempx); return NULL; } res = mpz_divisible_p(tempx->z, tempd->z); Py_DECREF((PyObject*)tempx); Py_DECREF((PyObject*)tempd); if (res) Py_RETURN_TRUE; else Py_RETURN_FALSE; }
/*-----------------------------------------------------------------------------*/ void build_tree(tree_t tree) { mpz_t M_tmp; mpz_init(M_tmp); /* si on est appelé et que l'on a le droit à aucune addition, */ /* cela signifie que l'on a déjà trouvé une solution directe */ /* par ailleurs: on rend la main et disant qu'on n'a pas trouvé. */ if(mpz_cmp_ui(tree->max_add, 0) <= 0) { mpz_set_si(tree->max_add,-1); return; } if(!mpz_cmp_ui(tree->M_red, 1)) { mpz_set_ui(tree->max_add,0); } else { char *bin; int len; int k; tree_t node; /* M = M'+1 */ mpz_sub_ui(M_tmp, tree->M_red, 1); tree->node[0] = create_node(M_tmp); mpz_sub_ui(tree->node[0]->max_add, tree->max_add, 1); mpz_set_si(tree->max_add, -1); build_tree(tree->node[0]); if(mpz_cmp_si(tree->node[0]->max_add, -1) != 0) { mpz_set(tree->max_add, tree->node[0]->max_add); mpz_add_ui(tree->max_add, tree->max_add, 1); } /* M = M'-1 */ mpz_add_ui(M_tmp, tree->M_red, 1); tree->node[1] = create_node(M_tmp); mpz_sub_ui(tree->node[1]->max_add, tree->max_add, 1); build_tree(tree->node[1]); if(mpz_cmp_si(tree->node[1]->max_add, -1) != 0) { mpz_set(tree->max_add, tree->node[1]->max_add); mpz_add_ui(tree->max_add, tree->max_add, 1); } bin = mpz_get_str(NULL, 2, tree->M_red); len = strlen(bin); free(bin); /* M = (2^k+1)M' */ tree->node[2] = NULL; for(k=len-1;k>0;k--) { mpz_set_ui(M_tmp, 1); mpz_mul_2exp(M_tmp, M_tmp, k); mpz_add_ui(M_tmp, M_tmp, 1); if(mpz_divisible_p(tree->M_red, M_tmp)) { mpz_cdiv_q(M_tmp, tree->M_red, M_tmp); node = create_node(M_tmp); mpz_sub_ui(node->max_add, tree->max_add, 1); build_tree(node); if(mpz_cmp_si(node->max_add, -1) != 0) { destroy_node(tree->node[2]); tree->node[2] = node; tree->k = k; mpz_set(tree->max_add, tree->node[2]->max_add); mpz_add_ui(tree->max_add, tree->max_add, 1); } else destroy_node(node); } } /* M = (2^k-1)M' */ tree->node[3] = NULL; for(k=len-1;k>0;k--) { mpz_set_ui(M_tmp, 1); mpz_mul_2exp(M_tmp, M_tmp, k); mpz_sub_ui(M_tmp, M_tmp, 1); if(mpz_divisible_p(tree->M_red, M_tmp)) { mpz_cdiv_q(M_tmp, tree->M_red, M_tmp); node = create_node(M_tmp); mpz_sub_ui(node->max_add, tree->max_add, 1); build_tree(node); if(mpz_cmp_si(node->max_add, -1) != 0) { destroy_node(tree->node[3]); tree->node[3] = node; tree->k = k; mpz_set(tree->max_add, tree->node[3]->max_add); mpz_add_ui(tree->max_add, tree->max_add, 1); } else destroy_node(node); } } } mpz_clear(M_tmp); }
/** \brief 整系数多项式最大公因子. \param f,g 整系数本原多项式,且\f$\deg f=n\ge\deg g\ge 1\f$. \param r 最大公因子. \note 小素数模方法. \todo 理论文档此处有误. */ void UniGcdZ_SmallPrime1(poly_z & r,const poly_z & f,const poly_z & g) { poly_z fp,gp,vp,v1; poly_z fstar,gstar; mpz_t c,s,t; mpz_init(c);mpz_init(s);mpz_init(t); mpz_t A,b,B,z_temp,k,p_bound,p,p_low_bound,p1,B2; mpf_t float_temp; mpz_init(A);mpz_init(b);mpz_init(B);mpz_init(z_temp);mpz_init(k);mpz_init(p_bound);mpz_init(p);mpz_init(p1);mpz_init(p_low_bound);mpf_init(float_temp);mpz_init(B2); UniMaxNormZ(A,f);UniMaxNormZ(b,g); int n=f.size()-1,m=g.size()-1; if(mpz_cmp(A,b)<0)mpz_set(A,b); mpz_gcd(b,f[n],g[m]); mpz_ui_pow_ui(B,2,n); mpz_mul(B,B,A); mpz_mul(B,B,b); mpf_sqrt_ui(float_temp,n+1); mpz_set_f(z_temp,float_temp); mpz_mul(B,B,z_temp); mpz_mul_ui(B2,B,2); mpz_set_si(z_temp,n); int tempint; tempint=2*n*mpz_sizeinbase(z_temp,2)+2*mpz_sizeinbase(b,2)+4*n*mpz_sizeinbase(A,2); //tempint=2*n*Modules::NumberTheory::IntegerLength(Z(n),2)+2*Modules::NumberTheory::IntegerLength(b,2)+4*n*Modules::NumberTheory::IntegerLength(A,2); mpz_set_si(k,tempint); mpz_mul_ui(p_bound,k,2); mpz_mul_ui(p_bound,p_bound,mpz_sizeinbase(k,2)); mpz_set_ui(p_low_bound,3); fstar.resize(n+1); for(size_t i=0;i<=n;i++) { mpz_mul(fstar[i],f[i],b); } gstar.resize(m+1); for(size_t i=0;i<=m;i++) { mpz_mul(gstar[i],g[i],b); } while(1) { while(1) { random::randominteger(p,p_low_bound,p_bound); if(mpz_probab_prime_p(p,10)>0&&mpz_divisible_p(b,p)==0)break; } UniPolynomialMod(fp,f,p); UniPolynomialMod(gp,g,p); UniGcdZp(vp,fp,gp,p); if(vp.size()==1) { r.resize(1); mpz_set_si(r[0],1); fp.resize(0);gp.resize(0);vp.resize(0);v1.resize(0); fstar.resize(0);gstar.resize(0); mpz_clear(c);mpz_clear(s);mpz_clear(t); mpz_clear(A);mpz_clear(b);mpz_clear(B);mpz_clear(z_temp);mpz_clear(k);mpz_clear(p_bound);mpz_clear(p);mpz_clear(p1);mpz_clear(p_low_bound);mpf_clear(float_temp); return ; } mpz_set(p1,p); copy_poly_z(v1,vp); while(mpz_cmp(p1,B2)<0) { while(1) { random::randominteger(p,p_low_bound,p_bound); if(mpz_probab_prime_p(p,10)>0&&mpz_divisible_p(b,p)==0)break; } UniPolynomialMod(fp,f,p); UniPolynomialMod(gp,g,p); UniGcdZp(vp,fp,gp,p); if(vp.size()==1) { r.resize(1); mpz_set_si(r[0],1); fp.resize(0);gp.resize(0);vp.resize(0);v1.resize(0); fstar.resize(0);gstar.resize(0); mpz_clear(c);mpz_clear(s);mpz_clear(t); mpz_clear(A);mpz_clear(b);mpz_clear(B);mpz_clear(z_temp);mpz_clear(k);mpz_clear(p_bound);mpz_clear(p);mpz_clear(p1);mpz_clear(p_low_bound);mpf_clear(float_temp); return ; } if(vp.size()<v1.size()) { mpz_set(p1,p); copy_poly_z(v1,vp); continue; } if(vp.size()==v1.size()) { mpz_gcdext(c,s,t,p1,p); mpz_mul(t,p,t); mpz_mul(s,p1,s); mpz_mul(p1,p1,p); for(size_t i=0;i<vp.size();i++) { mpz_mul(c,v1[i],t); mpz_addmul(c,vp[i],s); mpz_set(v1[i],c); } UniPolynomialMod(v1,v1,p1); } } for(size_t i=0;i<v1.size();i++)mpz_mul(v1[i],v1[i],b); UniPolynomialMod(v1,v1,p1); if(poly_z_divisible(fstar,v1)&&poly_z_divisible(gstar,v1)) { UniPPZ(r,v1);break; } } fp.resize(0);gp.resize(0);vp.resize(0);v1.resize(0); fstar.resize(0);gstar.resize(0); mpz_clear(c);mpz_clear(s);mpz_clear(t); mpz_clear(A);mpz_clear(b);mpz_clear(B);mpz_clear(z_temp);mpz_clear(k);mpz_clear(p_bound);mpz_clear(p);mpz_clear(p1);mpz_clear(p_low_bound);mpf_clear(float_temp); return ; }
int main(int argc, char** argv) { int my_rank, procs; MPI_Status status; mpz_t q, p, pq, n, gap, sqn; mpz_t *k; double *timearray; double begin, end; double time_spent; int done = 0, found = 0; MPI_Init(&argc, &argv); MPI_Comm_rank(MPI_COMM_WORLD, &my_rank); MPI_Comm_size(MPI_COMM_WORLD, &procs); begin = MPI_Wtime(); mpz_init(n); mpz_init(q); mpz_init(p); mpz_init(pq); mpz_init(sqn); mpz_init(gap); mpz_set_str(n,argv[1],10); mpz_sqrt(sqn,n); mpz_set(gap, sqn); mpz_set_ui(p,1); mpz_nextprime(q, p); size_t mag = mpz_sizeinbase (gap, 10); mag=mag*procs; k = (mpz_t*)malloc(sizeof(mpz_t)*(mag+1)); mpz_t temp; mpz_init(temp); mpz_tdiv_q_ui(temp,gap,mag); for (int i=0;i<=mag;i++) { mpz_init(k[i]); mpz_mul_ui(k[i],temp,i); } mpz_set(k[mag],sqn); int counter=0; for (int i=my_rank; i<mag; i=i+procs) { mpz_set(q,k[i]); mpz_sub_ui(q,q,1); mpz_nextprime(q,q); while (( mpz_cmp(q,k[i+1]) <= 0 )&&(!done)&&(!found)&&(mpz_cmp(q,sqn)<=0)) {//finding the prime numbers counter++; if (counter%5000==0)MPI_Allreduce(&found, &done, 1, MPI_INT, MPI_MAX, MPI_COMM_WORLD); if (mpz_divisible_p(n,q)==0) {//if n is not divisible by q mpz_nextprime(q,q); continue; } //since it is divisible, try n/q and see if result is prime mpz_divexact(p,n,q); int reps; if (mpz_probab_prime_p(p,reps)!=0) { found = 1; done = 1; } else { mpz_nextprime(q,q); } }//done finding primes if (found || done) break; } end = MPI_Wtime(); if (found) { MPI_Allreduce(&found, &done, 1, MPI_INT, MPI_MAX, MPI_COMM_WORLD); gmp_printf("*************************\nP%d: Finished\np*q=n\np=%Zd q=%Zd n=%Zd\n*************************\n", my_rank,p,q,n); } else if (!done) { while (!done&&!found) MPI_Allreduce(&found, &done, 1, MPI_INT, MPI_MAX, MPI_COMM_WORLD); } time_spent = (double)(end - begin); if (my_rank!=0) { MPI_Send(&time_spent, sizeof(double),MPI_CHAR,0,0,MPI_COMM_WORLD); } else { timearray = (double*)malloc(sizeof(double)*procs); timearray[0] = time_spent; int j; for (j = 1; j<procs;j++) { double *ptr = timearray+j; MPI_Recv(ptr, sizeof(double),MPI_CHAR,j,0,MPI_COMM_WORLD,&status); } writeTime(argv[1],timearray,procs); free(timearray); } free(k); MPI_Finalize(); return 0; }
static int check_for_factor2(mpz_t f, mpz_t inputn, mpz_t fmin, mpz_t n, int stage, mpz_t* sfacs, int* nsfacs, int degree) { int success, sfaci; UV B1; /* Use this so we don't modify their input value */ mpz_set(n, inputn); if (mpz_cmp(n, fmin) <= 0) return 0; #if 0 { /* Straightforward trial division up to 3000. */ PRIME_ITERATOR(iter); UV tf; UV const trial_limit = 3000; for (tf = 2; tf < trial_limit; tf = prime_iterator_next(&iter)) { if (mpz_cmp_ui(n, tf*tf) < 0) break; while (mpz_divisible_ui_p(n, tf)) mpz_divexact_ui(n, n, tf); } prime_iterator_destroy(&iter); } #else /* Utilize GMP's fast gcd algorithms. Trial to 224737 with two gcds. */ mpz_tdiv_q_2exp(n, n, mpz_scan1(n, 0)); while (mpz_divisible_ui_p(n, 3)) mpz_divexact_ui(n, n, 3); while (mpz_divisible_ui_p(n, 5)) mpz_divexact_ui(n, n, 5); if (mpz_cmp(n, fmin) <= 0) return 0; mpz_gcd(f, n, _gcd_small); while (mpz_cmp_ui(f, 1) > 0) { mpz_divexact(n, n, f); mpz_gcd(f, n, _gcd_small); } if (mpz_cmp(n, fmin) <= 0) return 0; mpz_gcd(f, n, _gcd_large); while (mpz_cmp_ui(f, 1) > 0) { mpz_divexact(n, n, f); mpz_gcd(f, n, _gcd_large); } /* Quick stage 1 n-1 using a single big powm + gcd. */ if (stage == 0) { if (mpz_cmp(n, fmin) <= 0) return 0; mpz_set_ui(f, 2); mpz_powm(f, f, _lcm_small, n); mpz_sub_ui(f, f, 1); mpz_gcd(f, f, n); if (mpz_cmp_ui(f, 1) != 0 && mpz_cmp(f, n) != 0) { mpz_divexact(n, n, f); if (mpz_cmp(f, n) > 0) mpz_set(n, f); } } #endif sfaci = 0; success = 1; while (success) { UV nsize = mpz_sizeinbase(n, 2); if (mpz_cmp(n, fmin) <= 0) return 0; if (_GMP_is_prob_prime(n)) { mpz_set(f, n); return (mpz_cmp(f, fmin) > 0); } success = 0; B1 = 300 + 3 * nsize; if (degree <= 2) B1 += nsize; /* D1 & D2 are cheap to prove. Encourage. */ if (degree <= 0) B1 += nsize; /* N-1 and N+1 are really cheap. */ if (degree > 20 && stage <= 1) B1 -= nsize; /* Less time on big polys. */ if (degree > 40) B1 -= nsize/2; /* Less time on big polys. */ if (stage >= 1) { #ifdef USE_LIBECM /* TODO: Tune stage 1 (PM1?) */ /* TODO: LIBECM in other stages */ if (!success) { ecm_params params; ecm_init(params); params->method = ECM_ECM; mpz_set_ui(params->B2, 10*B1); mpz_set_ui(params->sigma, 0); success = ecm_factor(f, n, B1/4, params); ecm_clear(params); if (mpz_cmp(f, n) == 0) success = 0; } #else if (!success) success = _GMP_pminus1_factor(n, f, B1, 6*B1); if (!success) success = _GMP_pplus1_factor(n, f, 0, B1/8, B1/8); if (!success && nsize < 500) success = _GMP_pbrent_factor(n, f, nsize, 1024-nsize); #endif } /* Try any factors found in previous stage 2+ calls */ while (!success && sfaci < *nsfacs) { if (mpz_divisible_p(n, sfacs[sfaci])) { mpz_set(f, sfacs[sfaci]); success = 1; } sfaci++; } if (stage > 1 && !success) { if (stage == 2) { if (!success) success = _GMP_pbrent_factor(n, f, nsize-1, 8192); if (!success) success = _GMP_pminus1_factor(n, f, 6*B1, 60*B1); /* p+1 with different initial point and searching farther */ if (!success) success = _GMP_pplus1_factor(n, f, 1, B1/2, B1/2); if (!success) success = _GMP_ecm_factor_projective(n, f, 250, 3); } else if (stage == 3) { if (!success) success = _GMP_pbrent_factor(n, f, nsize+1, 16384); if (!success) success = _GMP_pminus1_factor(n, f, 60*B1, 600*B1); /* p+1 with a third initial point and searching farther */ if (!success) success = _GMP_pplus1_factor(n, f, 2, 1*B1, 1*B1); if (!success) success = _GMP_ecm_factor_projective(n, f, B1/4, 4); } else if (stage == 4) { if (!success) success = _GMP_pminus1_factor(n, f, 300*B1, 300*20*B1); if (!success) success = _GMP_ecm_factor_projective(n, f, B1/2, 4); } else if (stage >= 5) { UV B = B1 * (stage-4) * (stage-4) * (stage-4); if (!success) success = _GMP_ecm_factor_projective(n, f, B, 8+stage); } } if (success) { if (mpz_cmp_ui(f, 1) == 0 || mpz_cmp(f, n) == 0) { gmp_printf("factoring %Zd resulted in factor %Zd\n", n, f); croak("internal error in ECPP factoring"); } /* Add the factor to the saved factors list */ if (stage > 1 && *nsfacs < MAX_SFACS) { /* gmp_printf(" ***** adding factor %Zd ****\n", f); */ mpz_init_set(sfacs[*nsfacs], f); nsfacs[0]++; } /* Is the factor f what we want? */ if ( mpz_cmp(f, fmin) > 0 && _GMP_is_prob_prime(f) ) return 1; /* Divide out f */ mpz_divexact(n, n, f); } } /* n is larger than fmin and not prime */ mpz_set(f, n); return -1; }
static PyObject * GMPy_MPZ_is_aprcl_prime(PyObject *self, PyObject *other) { mpz_t N; s64_t T, U; int i, j, H, I, J, K, P, Q, W, X; int IV, InvX, LEVELnow, NP, PK, PL, PM, SW, VK, TestedQs, TestingQs; int QQ, T1, T3, U1, U3, V1, V3; int break_this = 0; MPZ_Object *tempx; if (!(tempx = GMPy_MPZ_From_Integer(other, NULL))) { TYPE_ERROR("is_aprcl_prime() requires 'mpz' argument"); return NULL; } mpz_init(N); mpz_set(N, tempx->z); Py_DECREF(tempx); /* make sure the input is >= 2 and odd */ if (mpz_cmp_ui(N, 2) < 0) Py_RETURN_FALSE; if (mpz_divisible_ui_p(N, 2)) { if (mpz_cmp_ui(N, 2) == 0) Py_RETURN_TRUE; else Py_RETURN_FALSE; } /* only three small exceptions for this implementation */ /* with this set of P and Q primes */ if (mpz_cmp_ui(N, 3) == 0) Py_RETURN_TRUE; if (mpz_cmp_ui(N, 7) == 0) Py_RETURN_TRUE; if (mpz_cmp_ui(N, 11) == 0) Py_RETURN_TRUE; /* If the input number is larger than 7000 decimal digits we will just return whether it is a BPSW (probable) prime */ NumberLength = mpz_sizeinbase(N, 10); if (NumberLength > 7000) { VALUE_ERROR("value too large to test"); return NULL; } allocate_vars(); mpz_set(TestNbr, N); mpz_set_si(biS, 0); j = PK = PL = PM = 0; for (J = 0; J < PWmax; J++) { /* aiJX[J] = 0; */ mpz_set_ui(aiJX[J], 0); } break_this = 0; /* GetPrimes2Test : */ for (i = 0; i < LEVELmax; i++) { /* biS[0] = 2; */ mpz_set_ui(biS, 2); for (j = 0; j < aiNQ[i]; j++) { Q = aiQ[j]; if (aiT[i]%(Q-1) != 0) continue; U = aiT[i] * Q; do { U /= Q; /* MultBigNbrByLong(biS, Q, biS, NumberLength); */ mpz_mul_ui(biS, biS, Q); } while (U % Q == 0); // Exit loop if S^2 > N. if (CompareSquare(biS, TestNbr) > 0) { /* break GetPrimes2Test; */ break_this = 1; break; } } /* End for j */ if (break_this) break; } /* End for i */ if (i == LEVELmax) { /* too big */ free_vars(); VALUE_ERROR("value too large to test"); return NULL; } LEVELnow = i; TestingQs = j; T = aiT[LEVELnow]; NP = aiNP[LEVELnow]; MainStart: for (;;) { for (i = 0; i < NP; i++) { P = aiP[i]; if (T%P != 0) continue; SW = TestedQs = 0; /* Q = W = (int) BigNbrModLong(TestNbr, P * P); */ Q = W = mpz_fdiv_ui(TestNbr, P * P); for (J = P - 2; J > 0; J--) { W = (W * Q) % (P * P); } if (P > 2 && W != 1) { SW = 1; } for (;;) { for (j = TestedQs; j <= TestingQs; j++) { Q = aiQ[j] - 1; /* G = aiG[j]; */ K = 0; while (Q % P == 0) { K++; Q /= P; } Q = aiQ[j]; if (K == 0) { continue; } PM = 1; for (I = 1; I < K; I++) { PM = PM * P; } PL = (P - 1) * PM; PK = P * PM; for (I = 0; I < PK; I++) { /* aiJ0[I] = aiJ1[I] = 0; */ mpz_set_ui(aiJ0[I], 0); mpz_set_ui(aiJ1[I], 0); } if (P > 2) { JacobiSum(0, P, PL, Q); } else { if (K != 1) { JacobiSum(0, P, PL, Q); for (I = 0; I < PK; I++) { /* aiJW[I] = 0; */ mpz_set_ui(aiJW[I], 0); } if (K != 2) { for (I = 0; I < PM; I++) { /* aiJW[I] = aiJ0[I]; */ mpz_set(aiJW[I], aiJ0[I]); } JacobiSum(1, P, PL, Q); for (I = 0; I < PM; I++) { /* aiJS[I] = aiJ0[I]; */ mpz_set(aiJS[I], aiJ0[I]); } JS_JW(PK, PL, PM, P); for (I = 0; I < PM; I++) { /* aiJ1[I] = aiJS[I]; */ mpz_set(aiJ1[I], aiJS[I]); } JacobiSum(2, P, PL, Q); for (I = 0; I < PK; I++) { /* aiJW[I] = 0; */ mpz_set_ui(aiJW[I], 0); } for (I = 0; I < PM; I++) { /* aiJS[I] = aiJ0[I]; */ mpz_set(aiJS[I], aiJ0[I]); } JS_2(PK, PL, PM, P); for (I = 0; I < PM; I++) { /* aiJ2[I] = aiJS[I]; */ mpz_set(aiJ2[I], aiJS[I]); } } } } /* aiJ00[0] = aiJ01[0] = 1; */ mpz_set_ui(aiJ00[0], 1); mpz_set_ui(aiJ01[0], 1); for (I = 1; I < PK; I++) { /* aiJ00[I] = aiJ01[I] = 0; */ mpz_set_ui(aiJ00[I], 0); mpz_set_ui(aiJ01[I], 0); } /* VK = (int) BigNbrModLong(TestNbr, PK); */ VK = mpz_fdiv_ui(TestNbr, PK); for (I = 1; I < PK; I++) { if (I % P != 0) { U1 = 1; U3 = I; V1 = 0; V3 = PK; while (V3 != 0) { QQ = U3 / V3; T1 = U1 - V1 * QQ; T3 = U3 - V3 * QQ; U1 = V1; U3 = V3; V1 = T1; V3 = T3; } aiInv[I] = (U1 + PK) % PK; } else { aiInv[I] = 0; } } if (P != 2) { for (IV = 0; IV <= 1; IV++) { for (X = 1; X < PK; X++) { for (I = 0; I < PK; I++) { /* aiJS[I] = aiJ0[I]; */ mpz_set(aiJS[I], aiJ0[I]); } if (X % P == 0) { continue; } if (IV == 0) { /* LongToBigNbr(X, biExp, NumberLength); */ mpz_set_ui(biExp, X); } else { /* LongToBigNbr(VK * X / PK, biExp, NumberLength); */ mpz_set_ui(biExp, (VK * X) / PK); if ((VK * X) / PK == 0) { continue; } } JS_E(PK, PL, PM, P); for (I = 0; I < PK; I++) { /* aiJW[I] = 0; */ mpz_set_ui(aiJW[I], 0); } InvX = aiInv[X]; for (I = 0; I < PK; I++) { J = (I * InvX) % PK; /* AddBigNbrModN(aiJW[J], aiJS[I], aiJW[J], TestNbr, NumberLength); */ mpz_add(aiJW[J], aiJW[J], aiJS[I]); } NormalizeJW(PK, PL, PM, P); if (IV == 0) { for (I = 0; I < PK; I++) { /* aiJS[I] = aiJ00[I]; */ mpz_set(aiJS[I], aiJ00[I]); } } else { for (I = 0; I < PK; I++) { /* aiJS[I] = aiJ01[I]; */ mpz_set(aiJS[I], aiJ01[I]); } } JS_JW(PK, PL, PM, P); if (IV == 0) { for (I = 0; I < PK; I++) { /* aiJ00[I] = aiJS[I]; */ mpz_set(aiJ00[I], aiJS[I]); } } else { for (I = 0; I < PK; I++) { /* aiJ01[I] = aiJS[I]; */ mpz_set(aiJ01[I], aiJS[I]); } } } /* end for X */ } /* end for IV */ } else { if (K == 1) { /* MultBigNbrByLongModN(1, Q, aiJ00[0], TestNbr, NumberLength); */ mpz_set_ui(aiJ00[0], Q); /* aiJ01[0] = 1; */ mpz_set_ui(aiJ01[0], 1); } else { if (K == 2) { if (VK == 1) { /* aiJ01[0] = 1; */ mpz_set_ui(aiJ01[0], 1); } /* aiJS[0] = aiJ0[0]; */ /* aiJS[1] = aiJ0[1]; */ mpz_set(aiJS[0], aiJ0[0]); mpz_set(aiJS[1], aiJ0[1]); JS_2(PK, PL, PM, P); if (VK == 3) { /* aiJ01[0] = aiJS[0]; */ /* aiJ01[1] = aiJS[1]; */ mpz_set(aiJ01[0], aiJS[0]); mpz_set(aiJ01[1], aiJS[1]); } /* MultBigNbrByLongModN(aiJS[0], Q, aiJ00[0], TestNbr, NumberLength); */ mpz_mul_ui(aiJ00[0], aiJS[0], Q); /* MultBigNbrByLongModN(aiJS[1], Q, aiJ00[1], TestNbr, NumberLength); */ mpz_mul_ui(aiJ00[1], aiJS[1], Q); } else { for (IV = 0; IV <= 1; IV++) { for (X = 1; X < PK; X += 2) { for (I = 0; I <= PM; I++) { /* aiJS[I] = aiJ1[I]; */ mpz_set(aiJS[I], aiJ1[I]); } if (X % 8 == 5 || X % 8 == 7) { continue; } if (IV == 0) { /* LongToBigNbr(X, biExp, NumberLength); */ mpz_set_ui(biExp, X); } else { /* LongToBigNbr(VK * X / PK, biExp, NumberLength); */ mpz_set_ui(biExp, VK * X / PK); if (VK * X / PK == 0) { continue; } } JS_E(PK, PL, PM, P); for (I = 0; I < PK; I++) { /* aiJW[I] = 0; */ mpz_set_ui(aiJW[I], 0); } InvX = aiInv[X]; for (I = 0; I < PK; I++) { J = I * InvX % PK; /* AddBigNbrModN(aiJW[J], aiJS[I], aiJW[J], TestNbr, NumberLength); */ mpz_add(aiJW[J], aiJW[J], aiJS[I]); } NormalizeJW(PK, PL, PM, P); if (IV == 0) { for (I = 0; I < PK; I++) { /* aiJS[I] = aiJ00[I]; */ mpz_set(aiJS[I], aiJ00[I]); } } else { for (I = 0; I < PK; I++) { /* aiJS[I] = aiJ01[I]; */ mpz_set(aiJS[I], aiJ01[I]); } } NormalizeJS(PK, PL, PM, P); JS_JW(PK, PL, PM, P); if (IV == 0) { for (I = 0; I < PK; I++) { /* aiJ00[I] = aiJS[I]; */ mpz_set(aiJ00[I], aiJS[I]); } } else { for (I = 0; I < PK; I++) { /* aiJ01[I] = aiJS[I]; */ mpz_set(aiJ01[I], aiJS[I]); } } } /* end for X */ if (IV == 0 || VK % 8 == 1 || VK % 8 == 3) { continue; } for (I = 0; I < PM; I++) { /* aiJW[I] = aiJ2[I]; */ /* aiJS[I] = aiJ01[I]; */ mpz_set(aiJW[I], aiJ2[I]); mpz_set(aiJS[I], aiJ01[I]); } for (; I < PK; I++) { /* aiJW[I] = aiJS[I] = 0; */ mpz_set_ui(aiJW[I], 0); mpz_set_ui(aiJS[I], 0); } JS_JW(PK, PL, PM, P); for (I = 0; I < PM; I++) { /* aiJ01[I] = aiJS[I]; */ mpz_set(aiJ01[I], aiJS[I]); } } /* end for IV */ } } } for (I = 0; I < PL; I++) { /* aiJS[I] = aiJ00[I]; */ mpz_set(aiJS[I], aiJ00[I]); } for (; I < PK; I++) { /* aiJS[I] = 0; */ mpz_set_ui(aiJS[I], 0); } /* DivBigNbrByLong(TestNbr, PK, biExp, NumberLength); */ mpz_fdiv_q_ui(biExp, TestNbr, PK); JS_E(PK, PL, PM, P); for (I = 0; I < PK; I++) { /* aiJW[I] = 0; */ mpz_set_ui(aiJW[I], 0); } for (I = 0; I < PL; I++) { for (J = 0; J < PL; J++) { /* MontgomeryMult(aiJS[I], aiJ01[J], biTmp); */ /* AddBigNbrModN(biTmp, aiJW[(I + J) % PK], aiJW[(I + J) % PK], TestNbr, NumberLength); */ mpz_mul(biTmp, aiJS[I], aiJ01[J]); mpz_add(aiJW[(I + J) % PK], biTmp, aiJW[(I + J) % PK]); } } NormalizeJW(PK, PL, PM, P); /* MatchingRoot : */ do { H = -1; W = 0; for (I = 0; I < PL; I++) { if (mpz_cmp_ui(aiJW[I], 0) != 0)/* (!BigNbrIsZero(aiJW[I])) */ { /* if (H == -1 && BigNbrAreEqual(aiJW[I], 1)) */ if (H == -1 && (mpz_cmp_ui(aiJW[I], 1) == 0)) { H = I; } else { H = -2; /* AddBigNbrModN(aiJW[I], MontgomeryMultR1, biTmp, TestNbr, NumberLength); */ mpz_add_ui(biTmp, aiJW[I], 1); mpz_mod(biTmp, biTmp, TestNbr); if (mpz_cmp_ui(biTmp, 0) == 0) /* (BigNbrIsZero(biTmp)) */ { W++; } } } } if (H >= 0) { /* break MatchingRoot; */ break; } if (W != P - 1) { /* Not prime */ free_vars(); Py_RETURN_FALSE; } for (I = 0; I < PM; I++) { /* AddBigNbrModN(aiJW[I], 1, biTmp, TestNbr, NumberLength); */ mpz_add_ui(biTmp, aiJW[I], 1); mpz_mod(biTmp, biTmp, TestNbr); if (mpz_cmp_ui(biTmp, 0) == 0) /* (BigNbrIsZero(biTmp)) */ { break; } } if (I == PM) { /* Not prime */ free_vars(); Py_RETURN_FALSE; } for (J = 1; J <= P - 2; J++) { /* AddBigNbrModN(aiJW[I + J * PM], 1, biTmp, TestNbr, NumberLength); */ mpz_add_ui(biTmp, aiJW[I + J * PM], 1); mpz_mod(biTmp, biTmp, TestNbr); if (mpz_cmp_ui(biTmp, 0) != 0)/* (!BigNbrIsZero(biTmp)) */ { /* Not prime */ free_vars(); Py_RETURN_FALSE; } } H = I + PL; } while (0); if (SW == 1 || H % P == 0) { continue; } if (P != 2) { SW = 1; continue; } if (K == 1) { if ((mpz_get_ui(TestNbr) & 3) == 1) { SW = 1; } continue; } // if (Q^((N-1)/2) mod N != N-1), N is not prime. /* MultBigNbrByLongModN(1, Q, biTmp, TestNbr, NumberLength); */ mpz_set_ui(biTmp, Q); mpz_mod(biTmp, biTmp, TestNbr); mpz_sub_ui(biT, TestNbr, 1); /* biT = n-1 */ mpz_divexact_ui(biT, biT, 2); /* biT = (n-1)/2 */ mpz_powm(biR, biTmp, biT, TestNbr); /* biR = Q^((n-1)/2) mod n */ mpz_add_ui(biTmp, biR, 1); mpz_mod(biTmp, biTmp, TestNbr); if (mpz_cmp_ui(biTmp, 0) != 0)/* (!BigNbrIsZero(biTmp)) */ { /* Not prime */ free_vars(); Py_RETURN_FALSE; } SW = 1; } /* end for j */ if (SW == 0) { TestedQs = TestingQs + 1; if (TestingQs < aiNQ[LEVELnow] - 1) { TestingQs++; Q = aiQ[TestingQs]; U = T * Q; do { /* MultBigNbrByLong(biS, Q, biS, NumberLength); */ mpz_mul_ui(biS, biS, Q); U /= Q; } while (U % Q == 0); continue; /* Retry */ } LEVELnow++; if (LEVELnow == LEVELmax) { free_vars(); // return mpz_bpsw_prp(N); /* Cannot tell */ VALUE_ERROR("maximum levels reached"); return NULL; } T = aiT[LEVELnow]; NP = aiNP[LEVELnow]; /* biS = 2; */ mpz_set_ui(biS, 2); for (J = 0; J <= aiNQ[LEVELnow]; J++) { Q = aiQ[J]; if (T%(Q-1) != 0) continue; U = T * Q; do { /* MultBigNbrByLong(biS, Q, biS, NumberLength); */ mpz_mul_ui(biS, biS, Q); U /= Q; } while (U % Q == 0); if (CompareSquare(biS, TestNbr) > 0) { TestingQs = J; /* continue MainStart; */ /* Retry from the beginning */ goto MainStart; } } /* end for J */ free_vars(); VALUE_ERROR("internal failure"); return NULL; } /* end if */ break; } /* end for (;;) */ } /* end for i */ // Final Test /* biR = 1 */ mpz_set_ui(biR, 1); /* biN <- TestNbr mod biS */ /* Compute N mod S */ mpz_fdiv_r(biN, TestNbr, biS); for (U = 1; U <= T; U++) { /* biR <- (biN * biR) mod biS */ mpz_mul(biR, biN, biR); mpz_mod(biR, biR, biS); if (mpz_cmp_ui(biR, 1) == 0) /* biR == 1 */ { /* Number is prime */ free_vars(); Py_RETURN_TRUE; } if (mpz_divisible_p(TestNbr, biR) && mpz_cmp(biR, TestNbr) < 0) /* biR < N and biR | TestNbr */ { /* Number is composite */ free_vars(); Py_RETURN_FALSE; } } /* End for U */ /* This should never be reached. */ free_vars(); SYSTEM_ERROR("Internal error: APR-CL error with final test."); return NULL; } }
bool BitcoinMiner(primecoinBlock_t* primecoinBlock, CSieveOfEratosthenes*& psieve, unsigned int threadIndex, unsigned int nonceStep) { if (pctx == NULL) { pctx = BN_CTX_new(); } primecoinBlock->nonce = 1+threadIndex; const unsigned long maxNonce = 0xFFFFFFFF; uint32 nTime = getTimeMilliseconds() + 1000*600; uint32 loopCount = 0; mpz_class mpzHashFactor = 2310; //11 Hash Factor time_t unixTimeStart; time(&unixTimeStart); uint32 nTimeRollStart = primecoinBlock->timestamp - 5; uint32 nLastRollTime = getTimeMilliseconds(); uint32 nCurrentTick = nLastRollTime; while( nCurrentTick < nTime && primecoinBlock->serverData.blockHeight == jhMiner_getCurrentWorkBlockHeight(primecoinBlock->threadIndex) ) { nCurrentTick = getTimeMilliseconds(); // Roll Time stamp every 10 secs. if ((primecoinBlock->xptMode) && (nCurrentTick < nLastRollTime || (nLastRollTime - nCurrentTick >= 10000))) { // when using x.pushthrough, roll time time_t unixTimeCurrent; time(&unixTimeCurrent); uint32 timeDif = unixTimeCurrent - unixTimeStart; uint32 newTimestamp = nTimeRollStart + timeDif; if( newTimestamp != primecoinBlock->timestamp ) { primecoinBlock->timestamp = newTimestamp; primecoinBlock->nonce = 1+threadIndex; } nLastRollTime = nCurrentTick; } primecoinBlock_generateHeaderHash(primecoinBlock, primecoinBlock->blockHeaderHash.begin()); bool fNewBlock = true; unsigned int nTriedMultiplier = 0; // Primecoin: try to find hash divisible by primorial uint256 phash = primecoinBlock->blockHeaderHash; mpz_class mpzHash; mpz_set_uint256(mpzHash.get_mpz_t(), phash); while ((phash < hashBlockHeaderLimit || !mpz_divisible_p(mpzHash.get_mpz_t(), mpzHashFactor.get_mpz_t())) && primecoinBlock->nonce < maxNonce) { primecoinBlock->nonce += nonceStep; if (primecoinBlock->nonce >= maxNonce) { primecoinBlock->nonce = 2+threadIndex; } primecoinBlock_generateHeaderHash(primecoinBlock, primecoinBlock->blockHeaderHash.begin()); phash = primecoinBlock->blockHeaderHash; mpz_set_uint256(mpzHash.get_mpz_t(), phash); } mpz_class mpzPrimorial;mpz_class mpzFixedMultiplier; unsigned int nRoundTests = 0;unsigned int nRoundPrimesHit = 0; unsigned int nTests = 0;unsigned int nPrimesHit = 0; unsigned int nProbableChainLength; if (primeStats.tSplit) { unsigned int nPrimorialMultiplier = primeStats.nPrimorials[threadIndex%primeStats.nPrimorialsSize]; Primorial(nPrimorialMultiplier, mpzPrimorial); mpzFixedMultiplier = mpzPrimorial / mpzHashFactor; MineProbablePrimeChain(psieve, primecoinBlock, mpzFixedMultiplier, fNewBlock, nTriedMultiplier, nProbableChainLength, nTests, nPrimesHit, threadIndex, mpzHash, nPrimorialMultiplier); } else { unsigned int nPrimorialMultiplier = primeStats.nPrimorials[threadSNum]; Primorial(nPrimorialMultiplier, mpzPrimorial); mpzFixedMultiplier = mpzPrimorial / mpzHashFactor; MineProbablePrimeChain(psieve, primecoinBlock, mpzFixedMultiplier, fNewBlock, nTriedMultiplier, nProbableChainLength, nTests, nPrimesHit, threadIndex, mpzHash, nPrimorialMultiplier); threadSNum++;if (threadSNum>=primeStats.nPrimorialsSize) { threadSNum = 0; } #ifdef _WIN32 threadHearthBeat[threadIndex] = getTimeMilliseconds(); #endif if (appQuitSignal) { printf( "Shutting down mining thread %d.\n", threadIndex); return false; } } if (appQuitSignal) { printf( "Shutting down mining thread %d.\n", threadIndex);return false; } nRoundTests += nTests; nRoundPrimesHit += nPrimesHit; primecoinBlock->nonce += nonceStep; loopCount++; } return true; }
static int check_for_factor(mpz_t f, mpz_t inputn, mpz_t fmin, mpz_t n, int stage, mpz_t* sfacs, int* nsfacs, int degree) { int success, sfaci; UV B1; /* Use this so we don't modify their input value */ mpz_set(n, inputn); if (mpz_cmp(n, fmin) <= 0) return 0; #if 0 /* Use this to really encourage n-1 / n+1 proof types */ if (degree <= 0) { if (stage == 1) return -1; if (stage == 0) stage = 1; } #endif /* Utilize GMP's fast gcd algorithms. Trial to 224737+ with two gcds. */ mpz_tdiv_q_2exp(n, n, mpz_scan1(n, 0)); while (mpz_divisible_ui_p(n, 3)) mpz_divexact_ui(n, n, 3); while (mpz_divisible_ui_p(n, 5)) mpz_divexact_ui(n, n, 5); if (mpz_cmp(n, fmin) <= 0) return 0; mpz_gcd(f, n, _gcd_small); while (mpz_cmp_ui(f, 1) > 0) { mpz_divexact(n, n, f); mpz_gcd(f, f, n); } if (mpz_cmp(n, fmin) <= 0) return 0; mpz_gcd(f, n, _gcd_large); while (mpz_cmp_ui(f, 1) > 0) { mpz_divexact(n, n, f); mpz_gcd(f, f, n); } sfaci = 0; success = 1; while (success) { UV nsize = mpz_sizeinbase(n, 2); const int do_pm1 = 1; const int do_pp1 = 1; const int do_pbr = 0; const int do_ecm = 0; if (mpz_cmp(n, fmin) <= 0) return 0; if (is_bpsw_prime(n)) { mpz_set(f, n); return (mpz_cmp(f, fmin) > 0); } success = 0; B1 = 300 + 3 * nsize; if (degree <= 2) B1 += nsize; /* D1 & D2 are cheap to prove. */ if (degree <= 0) B1 += 2*nsize; /* N-1 and N+1 are really cheap. */ if (degree > 20 && stage <= 1) B1 -= nsize; /* Less time on big polys. */ if (degree > 40) B1 -= nsize/2; /* Less time on big polys. */ if (stage == 0) { /* A relatively small performance hit, makes slightly smaller proofs. */ if (nsize < 900 && degree <= 2) B1 *= 1.8; /* We need to try a bit harder for the large sizes :( */ if (nsize > 1400) B1 *= 2; if (nsize > 2000) B1 *= 2; if (!success) success = _GMP_pminus1_factor(n, f, 100+B1/8, 100+B1); } else if (stage >= 1) { /* P-1 */ if ((!success && do_pm1)) success = _GMP_pminus1_factor(n, f, B1, 6*B1); /* Pollard's Rho */ if ((!success && do_pbr && nsize < 500)) success = _GMP_pbrent_factor(n, f, nsize % 53, 1000-nsize); /* P+1 */ if ((!success && do_pp1)) { UV ppB = (nsize < 2000) ? B1/4 : B1/16; success = _GMP_pplus1_factor(n, f, 0, ppB, ppB); } if ((!success && do_ecm)) success = _GMP_ecm_factor_projective(n, f, 400, 2000, 1); #ifdef USE_LIBECM /* TODO: LIBECM in other stages */ /* Note: this will be substantially slower than our code for small sizes * and the small B1/B2 values we're using. */ if (!success && degree <= 2 && nsize > 600) { ecm_params params; ecm_init(params); params->method = ECM_ECM; mpz_set_ui(params->B2, 10*B1); mpz_set_ui(params->sigma, 0); success = ecm_factor(f, n, B1/4, params); ecm_clear(params); if (mpz_cmp(f, n) == 0) success = 0; if (success) { printf("ECM FOUND FACTOR\n"); } } #endif } /* Try any factors found in previous stage 2+ calls */ while (!success && sfaci < *nsfacs) { if (mpz_divisible_p(n, sfacs[sfaci])) { mpz_set(f, sfacs[sfaci]); success = 1; } sfaci++; } if (stage > 1 && !success) { if (stage == 2) { /* if (!success) success = _GMP_pbrent_factor(n, f, nsize-1, 8192); */ if (!success) success = _GMP_pminus1_factor(n, f, 6*B1, 60*B1); /* p+1 with different initial point and searching farther */ if (!success) success = _GMP_pplus1_factor(n, f, 1, B1/2, B1/2); if (!success) success = _GMP_ecm_factor_projective(n, f, 250, 2500, 8); } else if (stage == 3) { if (!success) success = _GMP_pbrent_factor(n, f, nsize+1, 16384); if (!success) success = _GMP_pminus1_factor(n, f, 60*B1, 600*B1); /* p+1 with a third initial point and searching farther */ if (!success) success = _GMP_pplus1_factor(n, f, 2, 1*B1, 1*B1); if (!success) success = _GMP_ecm_factor_projective(n, f, B1/4, B1*4, 5); } else if (stage == 4) { if (!success) success = _GMP_pminus1_factor(n, f, 300*B1, 300*20*B1); if (!success) success = _GMP_ecm_factor_projective(n, f, B1/2, B1*8, 4); } else if (stage >= 5) { UV B = B1 * (stage-4) * (stage-4) * (stage-4); if (!success) success = _GMP_ecm_factor_projective(n, f, B, 10*B, 8+stage); } } if (success) { if (mpz_cmp_ui(f, 1) == 0 || mpz_cmp(f, n) == 0) { gmp_printf("factoring %Zd resulted in factor %Zd\n", n, f); croak("internal error in ECPP factoring"); } /* Add the factor to the saved factors list */ if (stage > 1 && *nsfacs < MAX_SFACS) { /* gmp_printf(" ***** adding factor %Zd ****\n", f); */ mpz_init_set(sfacs[*nsfacs], f); nsfacs[0]++; } /* Is the factor f what we want? */ if ( mpz_cmp(f, fmin) > 0 && is_bpsw_prime(f) ) return 1; /* Divide out f */ mpz_divexact(n, n, f); } } /* n is larger than fmin and not prime */ mpz_set(f, n); return -1; }