int checkBl(mpz_t n, uint32 *qli, fb_list *fb, mpz_t *Bl, int s) { //check that Bl^2 == N mod ql and Bl == 0 mod qj for 1<=j<=s, j != l int i,j,p,q; mpz_t t1,t2; mpz_init(t1); mpz_init(t2); for (i=0;i<s;i++) { p = fb->list->prime[qli[i]]; mpz_tdiv_q_2exp(t2, Bl[i], 1); //zShiftRight(&t2,&Bl[i],1); mpz_mul(t1, t2, t2); //zSqr(&t2,&t1); if (mpz_tdiv_ui(t1,p) % mpz_tdiv_ui(n,p) != 0) printf("%s^2 mod %u != N mod %u\n",mpz_conv2str(&gstr1.s, 10, Bl[i]),p,p); for (j=0;j<s;j++) { if (j==i) continue; q = fb->list->prime[qli[j]]; mpz_tdiv_q_2exp(t2, Bl[i], 1); //zShiftRight(&t2,&Bl[i],1); if (mpz_tdiv_ui(t2,q) != 0) printf("%s mod %u != 0\n",mpz_conv2str(&gstr1.s, 10, Bl[i]),q); } } mpz_clear(t1); mpz_clear(t2); return 0; }
int checkpoly_siqs(siqs_poly *poly, mpz_t n) { //check that b^2 == N mod a //and that c == (b*b - n)/a mpz_t t1,t2,t3,t4; mpz_init(t1); mpz_init(t2); mpz_init(t3); mpz_init(t4); mpz_set(t1, n); mpz_tdiv_r(t3, t1, poly->mpz_poly_a); //zDiv(&t1,&poly->poly_a,&t2,&t3); mpz_mul(t2, poly->mpz_poly_b, poly->mpz_poly_b); //zMul(&poly->poly_b,&poly->poly_b,&t2); mpz_tdiv_r(t4, t2, poly->mpz_poly_a); //zDiv(&t2,&poly->poly_a,&t1,&t4); if (mpz_cmp(t3,t4) != 0) { printf("\nError in checkpoly: %s^2 !== N mod %s\n", mpz_conv2str(&gstr1.s, 10, poly->mpz_poly_b), mpz_conv2str(&gstr2.s, 10, poly->mpz_poly_a)); if (mpz_sgn(poly->mpz_poly_b) < 0) printf("b is negative\n"); } if (mpz_kronecker(n, poly->mpz_poly_a) != 1) printf("\nError in checkpoly: (a|N) != 1\n"); mpz_mul(t2, poly->mpz_poly_b, poly->mpz_poly_b); //zMul(&poly->poly_b,&poly->poly_b,&t2); mpz_sub(t2, t2, n); mpz_tdiv_q(t4, t2, poly->mpz_poly_a); //zDiv(&t2,&poly->poly_a,&t1,&t4); if (mpz_cmp(t4,poly->mpz_poly_c) != 0) printf("\nError in checkpoly: c != (b^2 - n)/a\n"); mpz_clear(t1); mpz_clear(t2); mpz_clear(t3); mpz_clear(t4); return 0; }
void brent_loop(fact_obj_t *fobj) { //repeatedly use brent's rho on n //we always use three constants 'c'. //it may be desirable to make the number of different //polynomials, and their values, configurable, but for //now it is hardcoded. mpz_t d,t; FILE *flog; clock_t start, stop; double tt; //check for trivial cases if ((mpz_cmp_ui(fobj->rho_obj.gmp_n, 1) == 0) || (mpz_cmp_ui(fobj->rho_obj.gmp_n, 0) == 0)) return; if (mpz_cmp_ui(fobj->rho_obj.gmp_n, 2) == 0) return; //open the log file flog = fopen(fobj->flogname,"a"); if (flog == NULL) { printf("fopen error: %s\n", strerror(errno)); printf("could not open %s for writing\n",fobj->flogname); return; } //initialize some local args mpz_init(d); mpz_init(t); fobj->rho_obj.curr_poly = 0; while(fobj->rho_obj.curr_poly < 3) { //for each different constant, first check primalty because each //time around the number may be different start = clock(); if (mpz_probab_prime_p(fobj->rho_obj.gmp_n, NUM_WITNESSES)) { logprint(flog,"prp%d = %s\n", gmp_base10(fobj->rho_obj.gmp_n), mpz_conv2str(&gstr1.s, 10, fobj->rho_obj.gmp_n)); add_to_factor_list(fobj, fobj->rho_obj.gmp_n); stop = clock(); tt = (double)(stop - start)/(double)CLOCKS_PER_SEC; mpz_set_ui(fobj->rho_obj.gmp_n, 1); break; } //verbose: print status to screen if (VFLAG >= 0) printf("rho: x^2 + %u, starting %d iterations on C%u ", fobj->rho_obj.polynomials[fobj->rho_obj.curr_poly], fobj->rho_obj.iterations, (int)gmp_base10(fobj->rho_obj.gmp_n)); logprint(flog, "rho: x^2 + %u, starting %d iterations on C%u\n", fobj->rho_obj.polynomials[fobj->rho_obj.curr_poly], fobj->rho_obj.iterations, (int)gmp_base10(fobj->rho_obj.gmp_n)); //call brent's rho algorithm, using montgomery arithmetic. mbrent(fobj); //check to see if 'f' is non-trivial if ((mpz_cmp_ui(fobj->rho_obj.gmp_f, 1) > 0) && (mpz_cmp(fobj->rho_obj.gmp_f, fobj->rho_obj.gmp_n) < 0)) { //non-trivial factor found stop = clock(); tt = (double)(stop - start)/(double)CLOCKS_PER_SEC; //check if the factor is prime if (mpz_probab_prime_p(fobj->rho_obj.gmp_f, NUM_WITNESSES)) { add_to_factor_list(fobj, fobj->rho_obj.gmp_f); if (VFLAG > 0) gmp_printf("rho: found prp%d factor = %Zd\n", gmp_base10(fobj->rho_obj.gmp_f),fobj->rho_obj.gmp_f); logprint(flog,"prp%d = %s\n", gmp_base10(fobj->rho_obj.gmp_f), mpz_conv2str(&gstr1.s, 10, fobj->rho_obj.gmp_f)); } else { add_to_factor_list(fobj, fobj->rho_obj.gmp_f); if (VFLAG > 0) gmp_printf("rho: found c%d factor = %Zd\n", gmp_base10(fobj->rho_obj.gmp_f),fobj->rho_obj.gmp_f); logprint(flog,"c%d = %s\n", gmp_base10(fobj->rho_obj.gmp_f), mpz_conv2str(&gstr1.s, 10, fobj->rho_obj.gmp_f)); } start = clock(); //reduce input mpz_tdiv_q(fobj->rho_obj.gmp_n, fobj->rho_obj.gmp_n, fobj->rho_obj.gmp_f); } else { //no factor found, log the effort we made. stop = clock(); tt = (double)(stop - start)/(double)CLOCKS_PER_SEC; fobj->rho_obj.curr_poly++; //try a different function } } fobj->rho_obj.ttime = tt; fclose(flog); mpz_clear(d); mpz_clear(t); return; }
//----------------------- NFS ENTRY POINT ------------------------------------// void nfs(fact_obj_t *fobj) { //expect the input in fobj->nfs_obj.gmp_n char *input; msieve_obj *obj = NULL; char *nfs_args = NULL; // unused as yet enum cpu_type cpu = yafu_get_cpu_type(); mp_t mpN; factor_list_t factor_list; uint32 flags = 0; nfs_job_t job; uint32 relations_needed = 1; uint32 last_specialq = 0; struct timeval stop; // stop time of this job struct timeval start; // start time of this job struct timeval bstop; // stop time of sieving batch struct timeval bstart; // start time of sieving batch TIME_DIFF * difference; double t_time; uint32 pre_batch_rels = 0; char tmpstr[GSTR_MAXSIZE]; int process_done; enum nfs_state_e nfs_state; // initialize some job parameters memset(&job, 0, sizeof(nfs_job_t)); obj_ptr = NULL; //below a certain amount, revert to SIQS if (gmp_base10(fobj->nfs_obj.gmp_n) < fobj->nfs_obj.min_digits) { mpz_set(fobj->qs_obj.gmp_n, fobj->nfs_obj.gmp_n); SIQS(fobj); mpz_set(fobj->nfs_obj.gmp_n, fobj->qs_obj.gmp_n); return; } if (mpz_probab_prime_p(fobj->nfs_obj.gmp_n, NUM_WITNESSES)) { add_to_factor_list(fobj, fobj->nfs_obj.gmp_n); if (VFLAG >= 0) gmp_printf("PRP%d = %Zd\n", gmp_base10(fobj->nfs_obj.gmp_n), fobj->nfs_obj.gmp_n); logprint_oc(fobj->flogname, "a", "PRP%d = %s\n", gmp_base10(fobj->nfs_obj.gmp_n), mpz_conv2str(&gstr1.s, 10, fobj->nfs_obj.gmp_n)); mpz_set_ui(fobj->nfs_obj.gmp_n, 1); return; } if (mpz_perfect_square_p(fobj->nfs_obj.gmp_n)) { mpz_sqrt(fobj->nfs_obj.gmp_n, fobj->nfs_obj.gmp_n); add_to_factor_list(fobj, fobj->nfs_obj.gmp_n); logprint_oc(fobj->flogname, "a", "prp%d = %s\n", gmp_base10(fobj->nfs_obj.gmp_n), mpz_conv2str(&gstr1.s, 10, fobj->nfs_obj.gmp_n)); add_to_factor_list(fobj, fobj->nfs_obj.gmp_n); logprint_oc(fobj->flogname, "a", "prp%d = %s\n", gmp_base10(fobj->nfs_obj.gmp_n), mpz_conv2str(&gstr1.s, 10, fobj->nfs_obj.gmp_n)); mpz_set_ui(fobj->nfs_obj.gmp_n, 1); return; } if (mpz_perfect_power_p(fobj->nfs_obj.gmp_n)) { FILE *flog; uint32 j; if (VFLAG > 0) printf("input is a perfect power\n"); factor_perfect_power(fobj, fobj->nfs_obj.gmp_n); flog = fopen(fobj->flogname, "a"); if (flog == NULL) { printf("fopen error: %s\n", strerror(errno)); printf("could not open %s for appending\n", fobj->flogname); exit(1); } logprint(flog,"input is a perfect power\n"); for (j=0; j<fobj->num_factors; j++) { uint32 k; for (k=0; k<fobj->fobj_factors[j].count; k++) { logprint(flog,"prp%d = %s\n",gmp_base10(fobj->fobj_factors[j].factor), mpz_conv2str(&gstr1.s, 10, fobj->fobj_factors[j].factor)); } } fclose(flog); return; } if (fobj->nfs_obj.filearg[0] != '\0') { if (VFLAG > 0) printf("test: starting trial sieving\n"); trial_sieve(fobj); return; } //initialize the flag to watch for interrupts, and set the //pointer to the function to call if we see a user interrupt NFS_ABORT = 0; signal(SIGINT,nfsexit); //start a counter for the whole job gettimeofday(&start, NULL); //nfs state machine: input = (char *)malloc(GSTR_MAXSIZE * sizeof(char)); nfs_state = NFS_STATE_INIT; process_done = 0; while (!process_done) { switch (nfs_state) { case NFS_STATE_INIT: // write the input bigint as a string input = mpz_conv2str(&input, 10, fobj->nfs_obj.gmp_n); // create an msieve_obj // this will initialize the savefile to the outputfile name provided obj = msieve_obj_new(input, flags, fobj->nfs_obj.outputfile, fobj->nfs_obj.logfile, fobj->nfs_obj.fbfile, g_rand.low, g_rand.hi, (uint32)0, cpu, (uint32)L1CACHE, (uint32)L2CACHE, (uint32)THREADS, (uint32)0, nfs_args); fobj->nfs_obj.mobj = obj; // initialize these before checking existing files. If poly // select is resumed they will be changed by check_existing_files. job.last_leading_coeff = 0; job.poly_time = 0; job.use_max_rels = 0; job.snfs = NULL; // determine what to do next based on the state of various files. // this will set job.current_rels if it finds any nfs_state = check_existing_files(fobj, &last_specialq, &job); // before we get started, check to make sure we can find ggnfs sievers // if we are going to be doing sieving if (check_for_sievers(fobj, 1) == 1) nfs_state = NFS_STATE_DONE; if (VFLAG >= 0 && nfs_state != NFS_STATE_DONE) gmp_printf("nfs: commencing nfs on c%d: %Zd\n", gmp_base10(fobj->nfs_obj.gmp_n), fobj->nfs_obj.gmp_n); if (nfs_state != NFS_STATE_DONE) logprint_oc(fobj->flogname, "a", "nfs: commencing nfs on c%d: %s\n", gmp_base10(fobj->nfs_obj.gmp_n), mpz_conv2str(&gstr1.s, 10, fobj->nfs_obj.gmp_n)); // convert input to msieve bigint notation and initialize a list of factors gmp2mp_t(fobj->nfs_obj.gmp_n,&mpN); factor_list_init(&factor_list); if (fobj->nfs_obj.rangeq > 0) job.qrange = ceil((double)fobj->nfs_obj.rangeq / (double)THREADS); break; case NFS_STATE_POLY: if ((fobj->nfs_obj.nfs_phases == NFS_DEFAULT_PHASES) || (fobj->nfs_obj.nfs_phases & NFS_PHASE_POLY)) { // always check snfs forms (it is fast) snfs_choose_poly(fobj, &job); if( job.snfs == NULL ) { // either we never were doing snfs, or snfs form detect failed. // if the latter then bail with an error because the user // explicitly wants to run snfs... if (fobj->nfs_obj.snfs) { printf("nfs: failed to find snfs polynomial!\n"); exit(-1); } // init job.poly for gnfs job.poly = (mpz_polys_t*)malloc(sizeof(mpz_polys_t)); if (job.poly == NULL) { printf("nfs: couldn't allocate memory!\n"); exit(-1); } mpz_polys_init(job.poly); job.poly->rat.degree = 1; // maybe way off in the future this isn't true // assume gnfs for now job.poly->side = ALGEBRAIC_SPQ; do_msieve_polyselect(fobj, obj, &job, &mpN, &factor_list); } else { fobj->nfs_obj.snfs = 1; mpz_set(fobj->nfs_obj.gmp_n, job.snfs->n); } } nfs_state = NFS_STATE_SIEVE; break; case NFS_STATE_SIEVE: pre_batch_rels = job.current_rels; gettimeofday(&bstart, NULL); // sieve if the user has requested to (or by default). else, // set the done sieving flag. this will prevent some infinite loops, // for instance if we only want to post-process, but filtering // doesn't produce a matrix. if we don't want to sieve in that case, // then we're done. if (((fobj->nfs_obj.nfs_phases == NFS_DEFAULT_PHASES) || (fobj->nfs_obj.nfs_phases & NFS_PHASE_SIEVE)) && !(fobj->nfs_obj.nfs_phases & NFS_DONE_SIEVING)) do_sieving(fobj, &job); else fobj->nfs_obj.nfs_phases |= NFS_DONE_SIEVING; // if this has been previously marked, then go ahead and exit. if (fobj->nfs_obj.nfs_phases & NFS_DONE_SIEVING) process_done = 1; // if user specified -ns with a fixed start and range, // then mark that we're done sieving. if (fobj->nfs_obj.rangeq > 0) { // we're done sieving the requested range, but there may be // more phases to check, so don't exit yet fobj->nfs_obj.nfs_phases |= NFS_DONE_SIEVING; } // then move on to the next phase nfs_state = NFS_STATE_FILTCHECK; break; case NFS_STATE_FILTER: // if we've flagged not to do filtering, then assume we have // enough relations and move on to linear algebra if ((fobj->nfs_obj.nfs_phases == NFS_DEFAULT_PHASES) || (fobj->nfs_obj.nfs_phases & NFS_PHASE_FILTER)) relations_needed = do_msieve_filtering(fobj, obj, &job); else relations_needed = 0; if (relations_needed == 0) nfs_state = NFS_STATE_LINALG; else { // if we filtered, but didn't produce a matrix, raise the target // min rels by a few percent. this will prevent too frequent // filtering attempts while allowing the q_batch size to remain small. if (job.current_rels > job.min_rels) job.min_rels = job.current_rels * fobj->nfs_obj.filter_min_rels_nudge; else job.min_rels *= fobj->nfs_obj.filter_min_rels_nudge; if (VFLAG > 0) printf("nfs: raising min_rels by %1.2f percent to %u\n", 100*(fobj->nfs_obj.filter_min_rels_nudge-1), job.min_rels); nfs_state = NFS_STATE_SIEVE; } break; case NFS_STATE_LINALG: if ((fobj->nfs_obj.nfs_phases == NFS_DEFAULT_PHASES) || (fobj->nfs_obj.nfs_phases & NFS_PHASE_LA) || (fobj->nfs_obj.nfs_phases & NFS_PHASE_LA_RESUME)) { // msieve: build matrix flags = 0; flags = flags | MSIEVE_FLAG_USE_LOGFILE; if (VFLAG > 0) flags = flags | MSIEVE_FLAG_LOG_TO_STDOUT; flags = flags | MSIEVE_FLAG_NFS_LA; // add restart flag if requested if (fobj->nfs_obj.nfs_phases & NFS_PHASE_LA_RESUME) flags |= MSIEVE_FLAG_NFS_LA_RESTART; obj->flags = flags; if (VFLAG >= 0) printf("nfs: commencing msieve linear algebra\n"); logprint_oc(fobj->flogname, "a", "nfs: commencing msieve linear algebra\n"); // use a different number of threads for the LA, if requested if (LATHREADS > 0) { msieve_obj_free(obj); obj = msieve_obj_new(input, flags, fobj->nfs_obj.outputfile, fobj->nfs_obj.logfile, fobj->nfs_obj.fbfile, g_rand.low, g_rand.hi, (uint32)0, cpu, (uint32)L1CACHE, (uint32)L2CACHE, (uint32)LATHREADS, (uint32)0, nfs_args); } // try this hack - store a pointer to the msieve obj so that // we can change a flag on abort in order to interrupt the LA. obj_ptr = obj; nfs_solve_linear_system(obj, fobj->nfs_obj.gmp_n); if (obj_ptr->flags & MSIEVE_FLAG_STOP_SIEVING) nfs_state = NFS_STATE_DONE; else { // check for a .dat.deps file. if we don't have one, assume // its because the job was way oversieved and only trivial // dependencies were found. try again from filtering with // 20% less relations. FILE *t; sprintf(tmpstr, "%s.dep", fobj->nfs_obj.outputfile); if ((t = fopen(tmpstr, "r")) == NULL) { if (job.use_max_rels > 0) { // we've already tried again with an attempted fix to the trivial // dependencies problem, so either that wasn't the problem or // it didn't work. either way, give up. printf("nfs: no dependency file retry failed\n"); fobj->flags |= FACTOR_INTERRUPT; nfs_state = NFS_STATE_DONE; } else { // this should be sufficient to produce a matrix, but not too much // to trigger the assumed failure mode. if (job.min_rels == 0) { // if min_rels is not set, then we need to parse the .job file to compute it. parse_job_file(fobj, &job); nfs_set_min_rels(&job); } job.use_max_rels = job.min_rels * 1.5; printf("nfs: no dependency file found - trying again with %u relations\n", job.use_max_rels); nfs_state = NFS_STATE_FILTER; } } else { fclose(t); nfs_state = NFS_STATE_SQRT; } } // set the msieve threads back to where it was if we used // a different amount for linalg if (LATHREADS > 0) { msieve_obj_free(obj); obj = msieve_obj_new(input, flags, fobj->nfs_obj.outputfile, fobj->nfs_obj.logfile, fobj->nfs_obj.fbfile, g_rand.low, g_rand.hi, (uint32)0, cpu, (uint32)L1CACHE, (uint32)L2CACHE, (uint32)THREADS, (uint32)0, nfs_args); } obj_ptr = NULL; } else // not doing linalg nfs_state = NFS_STATE_SQRT; break; case NFS_STATE_SQRT: if ((fobj->nfs_obj.nfs_phases == NFS_DEFAULT_PHASES) || (fobj->nfs_obj.nfs_phases & NFS_PHASE_SQRT)) { uint32 retcode; // msieve: find factors flags = 0; flags = flags | MSIEVE_FLAG_USE_LOGFILE; if (VFLAG > 0) flags = flags | MSIEVE_FLAG_LOG_TO_STDOUT; flags = flags | MSIEVE_FLAG_NFS_SQRT; obj->flags = flags; if (VFLAG >= 0) printf("nfs: commencing msieve sqrt\n"); logprint_oc(fobj->flogname, "a", "nfs: commencing msieve sqrt\n"); // try this hack - store a pointer to the msieve obj so that // we can change a flag on abort in order to interrupt the sqrt. obj_ptr = obj; retcode = nfs_find_factors(obj, fobj->nfs_obj.gmp_n, &factor_list); obj_ptr = NULL; if (retcode) { extract_factors(&factor_list,fobj); if (mpz_cmp_ui(fobj->nfs_obj.gmp_n, 1) == 0) nfs_state = NFS_STATE_CLEANUP; //completely factored, clean up everything else nfs_state = NFS_STATE_DONE; //not factored completely, keep files and stop } else { if (VFLAG >= 0) { printf("nfs: failed to find factors... possibly no dependencies found\n"); printf("nfs: continuing with sieving\n"); } logprint_oc(fobj->flogname, "a", "nfs: failed to find factors... " "possibly no dependencies found\n" "nfs: continuing with sieving\n"); nfs_state = NFS_STATE_SIEVE; } } else nfs_state = NFS_STATE_DONE; //not factored completely, keep files and stop break; case NFS_STATE_CLEANUP: remove(fobj->nfs_obj.outputfile); remove(fobj->nfs_obj.fbfile); sprintf(tmpstr, "%s.p",fobj->nfs_obj.outputfile); remove(tmpstr); sprintf(tmpstr, "%s.br",fobj->nfs_obj.outputfile); remove(tmpstr); sprintf(tmpstr, "%s.cyc",fobj->nfs_obj.outputfile); remove(tmpstr); sprintf(tmpstr, "%s.dep",fobj->nfs_obj.outputfile); remove(tmpstr); sprintf(tmpstr, "%s.hc",fobj->nfs_obj.outputfile); remove(tmpstr); sprintf(tmpstr, "%s.mat",fobj->nfs_obj.outputfile); remove(tmpstr); sprintf(tmpstr, "%s.lp",fobj->nfs_obj.outputfile); remove(tmpstr); sprintf(tmpstr, "%s.d",fobj->nfs_obj.outputfile); remove(tmpstr); sprintf(tmpstr, "%s.mat.chk",fobj->nfs_obj.outputfile); remove(tmpstr); gettimeofday(&stop, NULL); difference = my_difftime (&start, &stop); t_time = ((double)difference->secs + (double)difference->usecs / 1000000); free(difference); if (VFLAG >= 0) printf("NFS elapsed time = %6.4f seconds.\n",t_time); logprint_oc(fobj->flogname, "a", "NFS elapsed time = %6.4f seconds.\n",t_time); logprint_oc(fobj->flogname, "a", "\n"); logprint_oc(fobj->flogname, "a", "\n"); // free stuff nfs_state = NFS_STATE_DONE; break; case NFS_STATE_DONE: process_done = 1; break; case NFS_STATE_FILTCHECK: if (job.current_rels >= job.min_rels) { if (VFLAG > 0) printf("nfs: found %u relations, need at least %u, proceeding with filtering ...\n", job.current_rels, job.min_rels); nfs_state = NFS_STATE_FILTER; } else { // compute eta by dividing how many rels we have left to find // by the average time per relation. we have average time // per relation because we've saved the time it took to do // the last batch of sieving and we know how many relations we // found in that batch. uint32 est_time; gettimeofday(&bstop, NULL); difference = my_difftime (&bstart, &bstop); t_time = ((double)difference->secs + (double)difference->usecs / 1000000); free(difference); est_time = (uint32)((job.min_rels - job.current_rels) * (t_time / (job.current_rels - pre_batch_rels))); // if the user doesn't want to sieve, then we can't make progress. if ((fobj->nfs_obj.nfs_phases == NFS_DEFAULT_PHASES) || (fobj->nfs_obj.nfs_phases & NFS_PHASE_SIEVE)) { if (VFLAG > 0) printf("nfs: found %u relations, need at least %u " "(filtering ETA: %uh %um), continuing with sieving ...\n", // uh... um... hmm... idk *shrug* job.current_rels, job.min_rels, est_time / 3600, (est_time % 3600) / 60); nfs_state = NFS_STATE_SIEVE; } else { if (VFLAG > 0) printf("nfs: found %u relations, need at least %u " "(filtering ETA: %uh %um), sieving not selected, finishing ...\n", job.current_rels, job.min_rels, est_time / 3600, (est_time % 3600) / 60); nfs_state = NFS_STATE_DONE; } } break; case NFS_STATE_STARTNEW: nfs_state = NFS_STATE_POLY; // create a new directory for this job //#ifdef _WIN32 // sprintf(tmpstr, "%s\%s", fobj->nfs_obj.ggnfs_dir, // mpz_conv2str(&gstr1.s, 10, fobj->nfs_obj.gmp_n)); // mkdir(tmpstr); //#else // sprintf(tmpstr, "%s/%s", fobj->nfs_obj.ggnfs_dir, // mpz_conv2str(&gstr1.s, 10, fobj->nfs_obj.gmp_n)); // mkdir(tmpstr, S_IRWXU); //#endif // point msieve and ggnfs to the new directory //#ifdef _WIN32 // sprintf(fobj->nfs_obj.outputfile, "%s\%s", // tmpstr, fobj->nfs_obj.outputfile); // sprintf(fobj->nfs_obj.logfile, "%s\%s", // tmpstr, fobj->nfs_obj.logfile); // sprintf(fobj->nfs_obj.fbfile, "%s\%s", // tmpstr, fobj->nfs_obj.fbfile); //#else // sprintf(fobj->nfs_obj.outputfile, "%s%s", // tmpstr, fobj->nfs_obj.outputfile); // sprintf(fobj->nfs_obj.logfile, "%s%s", // tmpstr, fobj->nfs_obj.logfile); // sprintf(fobj->nfs_obj.fbfile, "%s%s", // tmpstr, fobj->nfs_obj.fbfile); // //#endif // // msieve_obj_free(fobj->nfs_obj.mobj); // obj = msieve_obj_new(input, flags, fobj->nfs_obj.outputfile, fobj->nfs_obj.logfile, // fobj->nfs_obj.fbfile, g_rand.low, g_rand.hi, (uint32)0, nfs_lower, nfs_upper, cpu, // (uint32)L1CACHE, (uint32)L2CACHE, (uint32)THREADS, (uint32)0, (uint32)0, 0.0); // fobj->nfs_obj.mobj = obj; // // printf("output: %s\n", fobj->nfs_obj.mobj->savefile.name); // printf("log: %s\n", fobj->nfs_obj.mobj->logfile_name); // printf("fb: %s\n", fobj->nfs_obj.mobj->nfs_fbfile_name); break; // should really be "resume_job", since we do more than just resume sieving... case NFS_STATE_RESUMESIEVE: // last_specialq == 0 if: // 1) user specifies -R and -ns with params // 2) user specifies post processing steps only // 3) user wants to resume sieving (either with a solo -ns or no arguements) // but no data file or special-q was found // 4) -R was not specified (but then we won't be in this state, we'll be in DONE) // last_specialq > 1 if: // 5) user wants to resume sieving (either with a solo -ns or no arguements) // and a data file and special-q was found // 6) it contains poly->time info (in which case we'll be in NFS_STATE_RESUMEPOLY) strcpy(tmpstr, ""); if ((last_specialq == 0) && ((fobj->nfs_obj.nfs_phases == NFS_DEFAULT_PHASES) || (fobj->nfs_obj.nfs_phases & NFS_PHASE_SIEVE))) { // this if-block catches cases 1 and 3 from above uint32 missing_params = parse_job_file(fobj, &job); // set min_rels. get_ggnfs_params(fobj, &job); fill_job_file(fobj, &job, missing_params); // if any ggnfs params are missing, fill them // this means the user can provide an SNFS poly or external GNFS poly, // but let YAFU choose the other params // this won't override any params in the file. if (fobj->nfs_obj.startq > 0) { job.startq = fobj->nfs_obj.startq; sprintf(tmpstr, "nfs: resuming with sieving at user specified special-q %u\n", job.startq); } else { // this is a guess, may be completely wrong job.startq = (job.poly->side == RATIONAL_SPQ ? job.rlim : job.alim) / 2; sprintf(tmpstr, "nfs: continuing with sieving - could not determine " "last special q; using default startq\n"); } // next step is sieving nfs_state = NFS_STATE_SIEVE; } else if ((last_specialq == 0) && ((fobj->nfs_obj.nfs_phases & NFS_PHASE_FILTER) || (fobj->nfs_obj.nfs_phases & NFS_PHASE_LA) || (fobj->nfs_obj.nfs_phases & NFS_PHASE_LA_RESUME) || (fobj->nfs_obj.nfs_phases & NFS_PHASE_SQRT))) { // this if-block catches case 2 from above // with these options we don't check for the last special-q, so this isn't // really a new factorization if ((fobj->nfs_obj.nfs_phases & NFS_PHASE_FILTER)) { nfs_state = NFS_STATE_FILTCHECK; sprintf(tmpstr, "nfs: resuming with filtering\n"); } else if ((fobj->nfs_obj.nfs_phases & NFS_PHASE_LA) || (fobj->nfs_obj.nfs_phases & NFS_PHASE_LA_RESUME)) { nfs_state = NFS_STATE_LINALG; sprintf(tmpstr, "nfs: resuming with linear algebra\n"); } else if (fobj->nfs_obj.nfs_phases & NFS_PHASE_SQRT) { nfs_state = NFS_STATE_SQRT; sprintf(tmpstr, "nfs: resuming with sqrt\n"); } } else // data file already exists { // this if-block catches case 5 from above (void) parse_job_file(fobj, &job); // set min_rels. get_ggnfs_params(fobj, &job); if (fobj->nfs_obj.startq > 0) { // user wants to resume sieving. // i don't believe this case is ever executed... // because if startq is > 0, then last_specialq will be 0... job.startq = fobj->nfs_obj.startq; nfs_state = NFS_STATE_SIEVE; } else { job.startq = last_specialq; // we found some relations - find the appropriate state // given user input if ((fobj->nfs_obj.nfs_phases == NFS_DEFAULT_PHASES) || (fobj->nfs_obj.nfs_phases & NFS_PHASE_FILTER)) { nfs_state = NFS_STATE_FILTCHECK; sprintf(tmpstr, "nfs: resuming with filtering\n"); } else if (fobj->nfs_obj.nfs_phases & NFS_PHASE_SIEVE) { nfs_state = NFS_STATE_SIEVE; sprintf(tmpstr, "nfs: resuming with sieving at special-q = %u\n", last_specialq); } else if ((fobj->nfs_obj.nfs_phases & NFS_PHASE_LA) || (fobj->nfs_obj.nfs_phases & NFS_PHASE_LA_RESUME)) { nfs_state = NFS_STATE_LINALG; sprintf(tmpstr, "nfs: resuming with linear algebra\n"); } else if (fobj->nfs_obj.nfs_phases & NFS_PHASE_SQRT) { nfs_state = NFS_STATE_SQRT; sprintf(tmpstr, "nfs: resuming with sqrt\n"); } } } if (VFLAG >= 0) printf("%s", tmpstr); logprint_oc(fobj->flogname, "a", "%s", tmpstr); // if there is a job file and the user has specified -np, print // this warning. if (fobj->nfs_obj.nfs_phases & NFS_PHASE_POLY) { printf("WARNING: .job file exists! If you really want to redo poly selection," " delete the .job file.\n"); // non ideal solution to infinite loop in factor() if we return without factors // (should return error code instead) NFS_ABORT = 1; process_done = 1; } break; case NFS_STATE_RESUMEPOLY: if (VFLAG > 1) printf("nfs: resuming poly select\n"); fobj->nfs_obj.polystart = job.last_leading_coeff; nfs_state = NFS_STATE_POLY; break; default: printf("unknown state, bailing\n"); // non ideal solution to infinite loop in factor() if we return without factors // (should return error code instead) NFS_ABORT = 1; break; } //after every state, check elasped time against a specified timeout value gettimeofday(&stop, NULL); difference = my_difftime (&start, &stop); t_time = ((double)difference->secs + (double)difference->usecs / 1000000); free(difference); if ((fobj->nfs_obj.timeout > 0) && (t_time > (double)fobj->nfs_obj.timeout)) { if (VFLAG >= 0) printf("NFS timeout after %6.4f seconds.\n",t_time); logprint_oc(fobj->flogname, "a", "NFS timeout after %6.4f seconds.\n",t_time); process_done = 1; } if (NFS_ABORT) { print_factors(fobj); exit(1); } } //reset signal handler to default (no handler). signal(SIGINT,NULL); if (obj != NULL) msieve_obj_free(obj); free(input); if( job.snfs ) { snfs_clear(job.snfs); free(job.snfs); } else if( job.poly ) { mpz_polys_free(job.poly); free(job.poly); } return; }
// top level routine: the only one visible to the rest of the program void pollard_loop(fact_obj_t *fobj) { //run pollard's p-1 algorithm once on the input, using a //32 bit random base //expects the input in pm1_obj->gmp_n mpz_t d,t; FILE *flog; clock_t start, stop; double tt; //check for trivial cases if ((mpz_cmp_ui(fobj->pm1_obj.gmp_n, 1) == 0) || (mpz_cmp_ui(fobj->pm1_obj.gmp_n, 0) == 0)) return; if (mpz_cmp_ui(fobj->pm1_obj.gmp_n, 2) == 0) return; start = clock(); //open the log file flog = fopen(fobj->flogname,"a"); if (flog == NULL) { printf("fopen error: %s\n", strerror(errno)); printf("could not open %s for writing\n",fobj->flogname); return; } if (mpz_probab_prime_p(fobj->pm1_obj.gmp_n, NUM_WITNESSES)) { logprint(flog,"prp%d = %s\n", gmp_base10(fobj->pm1_obj.gmp_n), mpz_conv2str(&gstr1.s, 10, fobj->pm1_obj.gmp_n)); add_to_factor_list(fobj, fobj->pm1_obj.gmp_n); stop = clock(); tt = (double)(stop - start)/(double)CLOCKS_PER_SEC; mpz_set_ui(fobj->pm1_obj.gmp_n, 1); fclose(flog); return; } //initialize the flag to watch for interrupts, and set the //pointer to the function to call if we see a user interrupt PM1_ABORT = 0; signal(SIGINT,pm1exit); //initialize some local args mpz_init(d); mpz_init(t); pm1_init(fobj); pm1_print_B1_B2(fobj,flog); pm1_wrapper(fobj); //check to see if 'f' is non-trivial if ((mpz_cmp_ui(fobj->pm1_obj.gmp_f, 1) > 0) && (mpz_cmp(fobj->pm1_obj.gmp_f, fobj->pm1_obj.gmp_n) < 0)) { //non-trivial factor found stop = clock(); tt = (double)(stop - start)/(double)CLOCKS_PER_SEC; //check if the factor is prime if (mpz_probab_prime_p(fobj->pm1_obj.gmp_f, NUM_WITNESSES)) { add_to_factor_list(fobj, fobj->pm1_obj.gmp_f); if (VFLAG > 0) gmp_printf("pm1: found prp%d factor = %Zd\n", gmp_base10(fobj->pm1_obj.gmp_f), fobj->pm1_obj.gmp_f); logprint(flog,"prp%d = %s\n", gmp_base10(fobj->pm1_obj.gmp_f), mpz_conv2str(&gstr1.s, 10, fobj->pm1_obj.gmp_f)); } else { add_to_factor_list(fobj, fobj->pm1_obj.gmp_f); if (VFLAG > 0) gmp_printf("pm1: found c%d factor = %Zd\n", gmp_base10(fobj->pm1_obj.gmp_f), fobj->pm1_obj.gmp_f); logprint(flog,"c%d = %s\n", gmp_base10(fobj->pm1_obj.gmp_f), mpz_conv2str(&gstr1.s, 10, fobj->pm1_obj.gmp_f)); } start = clock(); //reduce input mpz_tdiv_q(fobj->pm1_obj.gmp_n, fobj->pm1_obj.gmp_n, fobj->pm1_obj.gmp_f); } fclose(flog); pm1_finalize(fobj); //watch for an abort if (PM1_ABORT) { print_factors(fobj); exit(1); } signal(SIGINT,NULL); mpz_clear(d); mpz_clear(t); return; }
void factor_perfect_power(fact_obj_t *fobj, mpz_t b) { // check if (b^1/i)^i == b for i = 2 to bitlen(b) uint32 bits = mpz_sizeinbase(b,2); uint32 i; FILE *flog; mpz_t base, ans; mpz_init(base); mpz_init(ans); //open the log file flog = fopen(fobj->flogname,"a"); if (flog == NULL) { printf("fopen error: %s\n", strerror(errno)); printf("could not open %s for writing\n",fobj->flogname); return; } for (i=2; i<bits; i++) { mpz_root(base, b, i); mpz_pow_ui(ans, base, i); if (mpz_cmp(ans, b) == 0) { // found a base. if (is_mpz_prp(base)) { uint32 j; //gmp_printf("\nAdding prime base %Zd to factor list...\n", base); for (j=0; j<i; j++) { add_to_factor_list(fobj, base); mpz_tdiv_q(b, b, base); logprint(flog,"prp%d = %s\n", gmp_base10(base), mpz_conv2str(&gstr1.s, 10, base)); } } else { // if composite, factor it and then multiply // all factors by i (the exponent). fact_obj_t *fobj_refactor; uint32 j; gmp_printf("\nFactoring composite base %Zd...\n", base); // load the new fobj with this number fobj_refactor = (fact_obj_t *)malloc(sizeof(fact_obj_t)); init_factobj(fobj_refactor); mpz_set(fobj_refactor->N, base); // recurse on factor factor(fobj_refactor); // add all factors found during the refactorization for (j=0; j< fobj_refactor->num_factors; j++) { int k, c; //gmp_printf("\nAdding prime base %Zd to factor list...\n", // fobj_refactor->fobj_factors[j].factor); for (k=0; k < fobj_refactor->fobj_factors[j].count; k++) { // add i copies of it, since this was a perfect power for (c = 0; c < i; c++) { add_to_factor_list(fobj, fobj_refactor->fobj_factors[j].factor); mpz_tdiv_q(b, b, fobj_refactor->fobj_factors[j].factor); logprint(flog,"prp%d = %s\n", gmp_base10(fobj_refactor->fobj_factors[j].factor), mpz_conv2str(&gstr1.s, 10, fobj_refactor->fobj_factors[j].factor)); } } } // free temps free_factobj(fobj_refactor); free(fobj_refactor); } break; } } mpz_clear(base); mpz_clear(ans); fclose(flog); return; }
void zFermat(uint64 limit, uint32 mult, fact_obj_t *fobj) { // Fermat's factorization method with a sieve-based improvement // provided by 'neonsignal' mpz_t a, b2, tmp, multN, a2; int i; int numChars; uint64 reportIt, reportInc; uint64 count; uint64 i64; FILE *flog = NULL; uint32 M = 2 * 2 * 2 * 2 * 3 * 3 * 5 * 5 * 7 * 7; //176400u uint32 M1 = 11 * 17 * 23 * 31; //133331u uint32 M2 = 13 * 19 * 29 * 37; //265031u uint8 *sqr, *sqr1, *sqr2, *mod, *mod1, *mod2; uint16 *skip; uint32 m, mmn, s, d; uint8 masks[8] = {0xfe, 0xfd, 0xfb, 0xf7, 0xef, 0xdf, 0xbf, 0x7f}; uint8 nmasks[8]; uint32 iM = 0, iM1 = 0, iM2 = 0; if (mpz_even_p(fobj->div_obj.gmp_n)) { mpz_init(tmp); mpz_set_ui(tmp, 2); mpz_tdiv_q_2exp(fobj->div_obj.gmp_n, fobj->div_obj.gmp_n, 1); add_to_factor_list(fobj, tmp); mpz_clear(tmp); return; } if (mpz_perfect_square_p(fobj->div_obj.gmp_n)) { //open the log file flog = fopen(fobj->flogname,"a"); if (flog == NULL) { printf("fopen error: %s\n", strerror(errno)); printf("could not open %s for writing\n",fobj->flogname); return; } mpz_sqrt(fobj->div_obj.gmp_n, fobj->div_obj.gmp_n); if (is_mpz_prp(fobj->div_obj.gmp_n)) { logprint(flog, "Fermat method found perfect square factorization:\n"); logprint(flog,"prp%d = %s\n", gmp_base10(fobj->div_obj.gmp_n), mpz_conv2str(&gstr1.s, 10, fobj->div_obj.gmp_n)); logprint(flog,"prp%d = %s\n", gmp_base10(fobj->div_obj.gmp_n), mpz_conv2str(&gstr1.s, 10, fobj->div_obj.gmp_n)); } else { logprint(flog, "Fermat method found perfect square factorization:\n"); logprint(flog,"c%d = %s\n", gmp_base10(fobj->div_obj.gmp_n), mpz_conv2str(&gstr1.s, 10, fobj->div_obj.gmp_n)); logprint(flog,"c%d = %s\n", gmp_base10(fobj->div_obj.gmp_n), mpz_conv2str(&gstr1.s, 10, fobj->div_obj.gmp_n)); } add_to_factor_list(fobj, fobj->div_obj.gmp_n); add_to_factor_list(fobj, fobj->div_obj.gmp_n); mpz_set_ui(fobj->div_obj.gmp_n, 1); fclose(flog); return; } mpz_init(a); mpz_init(b2); mpz_init(tmp); mpz_init(multN); mpz_init(a2); // apply the user supplied multiplier mpz_mul_ui(multN, fobj->div_obj.gmp_n, mult); // compute ceil(sqrt(multN)) mpz_sqrt(a, multN); // form b^2 mpz_mul(b2, a, a); mpz_sub(b2, b2, multN); // test successive 'a' values using a sieve-based approach. // the idea is that not all 'a' values allow a^2 or b^2 to be square. // we pre-compute allowable 'a' values modulo various smooth numbers and // build tables to allow us to quickly iterate over 'a' values that are // more likely to produce squares. // init sieve structures sqr = (uint8 *)calloc((M / 8 + 1) , sizeof(uint8)); sqr1 = (uint8 *)calloc((M1 / 8 + 1) , sizeof(uint8)); sqr2 = (uint8 *)calloc((M2 / 8 + 1) , sizeof(uint8)); mod = (uint8 *)calloc((M / 8 + 1) , sizeof(uint8)); mod1 = (uint8 *)calloc((M1 / 8 + 1) , sizeof(uint8)); mod2 = (uint8 *)calloc((M2 / 8 + 1) , sizeof(uint8)); skip = (uint16 *)malloc(M * sizeof(uint16)); // test it. This will be good enough if |u*p-v*q| < 2 * N^(1/4), where // mult = u*v count = 0; if (mpz_perfect_square_p(b2)) goto found; for (i=0; i<8; i++) nmasks[i] = ~masks[i]; // marks locations where squares can occur mod M, M1, M2 for (i64 = 0; i64 < M; ++i64) setbit(sqr, (i64*i64)%M); for (i64 = 0; i64 < M1; ++i64) setbit(sqr1, (i64*i64)%M1); for (i64 = 0; i64 < M2; ++i64) setbit(sqr2, (i64*i64)%M2); // for the modular sequence of b*b = a*a - n values // (where b2_2 = b2_1 * 2a + 1), mark locations where // b^2 can be a square m = mpz_mod_ui(tmp, a, M); mmn = mpz_mod_ui(tmp, b2, M); for (i = 0; i < M; ++i) { if (getbit(sqr, mmn)) setbit(mod, i); mmn = (mmn+m+m+1)%M; m = (m+1)%M; } // we only consider locations where the modular sequence mod M can // be square, so compute the distance to the next square location // at each possible value of i mod M. s = 0; d = 0; for (i = 0; !getbit(mod,i); ++i) ++s; for (i = M; i > 0;) { --i; ++s; skip[i] = s; if (s > d) d = s; if (getbit(mod,i)) s = 0; } //printf("maxSkip = %u\n", d); // for the modular sequence of b*b = a*a - n values // (where b2_2 = b2_1 * 2a + 1), mark locations where the // modular sequence can be a square mod M1. These will // generally differ from the sequence mod M. m = mpz_mod_ui(tmp, a, M1); mmn = mpz_mod_ui(tmp, b2, M1); for (i = 0; i < M1; ++i) { if (getbit(sqr1, mmn)) setbit(mod1, i); mmn = (mmn+m+m+1)%M1; m = (m+1)%M1; } // for the modular sequence of b*b = a*a - n values // (where b2_2 = b2_1 * 2a + 1), mark locations where the // modular sequence can be a square mod M2. These will // generally differ from the sequence mod M or M1. m = mpz_mod_ui(tmp, a, M2); mmn = mpz_mod_ui(tmp, b2, M2); for (i = 0; i < M2; ++i) { if (getbit(sqr2, mmn)) setbit(mod2, i); mmn = (mmn+m+m+1)%M2; m = (m+1)%M2; } // loop, checking for perfect squares mpz_mul_2exp(a2, a, 1); count = 0; numChars = 0; reportIt = limit / 100; reportInc = reportIt; do { d = 0; i64 = 0; do { // skip to the next possible square residue of b*b mod M s = skip[iM]; // remember how far we skipped d += s; // update the other residue indices if ((iM1 += s) >= M1) iM1 -= M1; if ((iM2 += s) >= M2) iM2 -= M2; if ((iM += s) >= M) iM -= M; // some multpliers can lead to infinite loops. bail out // if so. if (++i64 > M) goto done; // continue if either of the other residues indicates // non-square. } while (!getbit(mod1,iM1) || !getbit(mod2,iM2)); // form b^2 by incrementing by many factors of 2*a+1 mpz_add_ui(tmp, a2, d); mpz_mul_ui(tmp, tmp, d); mpz_add(b2, b2, tmp); // accumulate so that we can reset d // (and thus keep it single precision) mpz_add_ui(a2, a2, d*2); count += d; if (count > limit) break; //progress report if ((count > reportIt) && (VFLAG > 1)) { for (i=0; i< numChars; i++) printf("\b"); numChars = printf("%" PRIu64 "%%",(uint64)((double)count / (double)limit * 100)); fflush(stdout); reportIt += reportInc; } } while (!mpz_perfect_square_p(b2)); found: // 'count' is how far we had to scan 'a' to find a square b mpz_add_ui(a, a, count); //printf("count is %" PRIu64 "\n", count); if ((mpz_size(b2) > 0) && mpz_perfect_square_p(b2)) { //printf("found square at count = %d: a = %s, b2 = %s",count, // z2decstr(&a,&gstr1),z2decstr(&b2,&gstr2)); mpz_sqrt(tmp, b2); mpz_add(tmp, a, tmp); mpz_gcd(tmp, fobj->div_obj.gmp_n, tmp); flog = fopen(fobj->flogname,"a"); if (flog == NULL) { printf("fopen error: %s\n", strerror(errno)); printf("could not open %s for writing\n",fobj->flogname); goto done; } logprint(flog, "Fermat method found factors:\n"); add_to_factor_list(fobj, tmp); if (is_mpz_prp(tmp)) { logprint(flog,"prp%d = %s\n", gmp_base10(tmp), mpz_conv2str(&gstr1.s, 10, tmp)); } else { logprint(flog,"c%d = %s\n", gmp_base10(tmp), mpz_conv2str(&gstr1.s, 10, tmp)); } mpz_tdiv_q(fobj->div_obj.gmp_n, fobj->div_obj.gmp_n, tmp); mpz_sqrt(tmp, b2); mpz_sub(tmp, a, tmp); mpz_gcd(tmp, fobj->div_obj.gmp_n, tmp); add_to_factor_list(fobj, tmp); if (is_mpz_prp(tmp)) { logprint(flog,"prp%d = %s\n", gmp_base10(tmp), mpz_conv2str(&gstr1.s, 10, tmp)); } else { logprint(flog,"c%d = %s\n", gmp_base10(tmp), mpz_conv2str(&gstr1.s, 10, tmp)); } mpz_tdiv_q(fobj->div_obj.gmp_n, fobj->div_obj.gmp_n, tmp); } done: mpz_clear(tmp); mpz_clear(a); mpz_clear(b2); mpz_clear(multN); mpz_clear(a2); free(sqr); free(sqr1); free(sqr2); free(mod); free(mod1); free(mod2); free(skip); if (flog != NULL) fclose(flog); return; }
void williams_loop(fact_obj_t *fobj) { //use william's p+1 algorithm 'trials' times on n. //we allow multiple trials since we may not always get a p+1 group //with our random choice of base //expects the input in pp1_obj->gmp_n mpz_t d,t; int i,it,trials = fobj->pp1_obj.numbases; FILE *flog; clock_t start, stop; double tt; //check for trivial cases if ((mpz_cmp_ui(fobj->pp1_obj.gmp_n, 1) == 0) || (mpz_cmp_ui(fobj->pp1_obj.gmp_n, 0) == 0)) return; if (mpz_cmp_ui(fobj->pp1_obj.gmp_n, 2) == 0) return; //open the log file flog = fopen(fobj->flogname,"a"); if (flog == NULL) { printf("fopen error: %s\n", strerror(errno)); printf("could not open %s for appending\n",fobj->flogname); return; } //initialize the flag to watch for interrupts, and set the //pointer to the function to call if we see a user interrupt PP1_ABORT = 0; signal(SIGINT,pp1exit); //initialize some local args mpz_init(d); mpz_init(t); pp1_init(fobj); i=0; while (i < trials) { //watch for an abort if (PP1_ABORT) { print_factors(fobj); exit(1); } start = clock(); if (is_mpz_prp(fobj->pp1_obj.gmp_n)) { logprint(flog,"prp%d = %s\n", gmp_base10(fobj->pp1_obj.gmp_n), mpz_conv2str(&gstr1.s, 10, fobj->pp1_obj.gmp_n)); add_to_factor_list(fobj, fobj->pp1_obj.gmp_n); stop = clock(); tt = (double)(stop - start)/(double)CLOCKS_PER_SEC; mpz_set_ui(fobj->pp1_obj.gmp_n, 1); break; } fobj->pp1_obj.base = spRand(3,MAX_DIGIT); pp1_print_B1_B2(fobj,flog); it = pp1_wrapper(fobj); //check to see if 'f' is non-trivial if ((mpz_cmp_ui(fobj->pp1_obj.gmp_f, 1) > 0) && (mpz_cmp(fobj->pp1_obj.gmp_f, fobj->pp1_obj.gmp_n) < 0)) { //non-trivial factor found stop = clock(); tt = (double)(stop - start)/(double)CLOCKS_PER_SEC; //check if the factor is prime if (is_mpz_prp(fobj->pp1_obj.gmp_f)) { add_to_factor_list(fobj, fobj->pp1_obj.gmp_f); if (VFLAG > 0) gmp_printf("pp1: found prp%d factor = %Zd\n", gmp_base10(fobj->pp1_obj.gmp_f),fobj->pp1_obj.gmp_f); logprint(flog,"prp%d = %s\n", gmp_base10(fobj->pp1_obj.gmp_f), mpz_conv2str(&gstr1.s, 10, fobj->pp1_obj.gmp_f)); } else { add_to_factor_list(fobj, fobj->pp1_obj.gmp_f); if (VFLAG > 0) gmp_printf("pp1: found c%d factor = %Zd\n", gmp_base10(fobj->pp1_obj.gmp_f),fobj->pp1_obj.gmp_f); logprint(flog,"c%d = %s\n", gmp_base10(fobj->pp1_obj.gmp_f), mpz_conv2str(&gstr1.s, 10, fobj->pp1_obj.gmp_f)); } start = clock(); //reduce input mpz_tdiv_q(fobj->pp1_obj.gmp_n, fobj->pp1_obj.gmp_n, fobj->pp1_obj.gmp_f); i++; break; } i++; } fclose(flog); pp1_finalize(fobj); signal(SIGINT,NULL); mpz_clear(d); mpz_clear(t); return; }
int check_specialcase(FILE *sieve_log, fact_obj_t *fobj) { //check for some special cases of input number //sieve_log is passed in already open, and should return open if (mpz_even_p(fobj->qs_obj.gmp_n)) { printf("input must be odd\n"); return 1; } if (mpz_probab_prime_p(fobj->qs_obj.gmp_n, NUM_WITNESSES)) { add_to_factor_list(fobj, fobj->qs_obj.gmp_n); if (sieve_log != NULL) logprint(sieve_log,"prp%d = %s\n", gmp_base10(fobj->qs_obj.gmp_n), mpz_conv2str(&gstr1.s, 10, fobj->qs_obj.gmp_n)); mpz_set_ui(fobj->qs_obj.gmp_n,1); return 1; } if (mpz_perfect_square_p(fobj->qs_obj.gmp_n)) { mpz_sqrt(fobj->qs_obj.gmp_n,fobj->qs_obj.gmp_n); add_to_factor_list(fobj, fobj->qs_obj.gmp_n); if (sieve_log != NULL) logprint(sieve_log,"prp%d = %s\n",gmp_base10(fobj->qs_obj.gmp_n), mpz_conv2str(&gstr1.s, 10, fobj->qs_obj.gmp_n)); add_to_factor_list(fobj, fobj->qs_obj.gmp_n); if (sieve_log != NULL) logprint(sieve_log,"prp%d = %s\n",gmp_base10(fobj->qs_obj.gmp_n), mpz_conv2str(&gstr1.s, 10, fobj->qs_obj.gmp_n)); mpz_set_ui(fobj->qs_obj.gmp_n,1); return 1; } if (mpz_perfect_power_p(fobj->qs_obj.gmp_n)) { if (VFLAG > 0) printf("input is a perfect power\n"); factor_perfect_power(fobj, fobj->qs_obj.gmp_n); if (sieve_log != NULL) { uint32 j; logprint(sieve_log,"input is a perfect power\n"); for (j=0; j<fobj->num_factors; j++) { uint32 k; for (k=0; k<fobj->fobj_factors[j].count; k++) { logprint(sieve_log,"prp%d = %s\n",gmp_base10(fobj->fobj_factors[j].factor), mpz_conv2str(&gstr1.s, 10, fobj->fobj_factors[j].factor)); } } } return 1; } if (mpz_sizeinbase(fobj->qs_obj.gmp_n,2) < 115) { //run MPQS, as SIQS doesn't work for smaller inputs //MPQS will take over the log file, so close it now. int i; // we've verified that the input is not odd or prime. also // do some very quick trial division before calling smallmpqs, which // does none of these things. for (i=1; i<25; i++) { if (mpz_tdiv_ui(fobj->qs_obj.gmp_n, spSOEprimes[i]) == 0) mpz_tdiv_q_ui(fobj->qs_obj.gmp_n, fobj->qs_obj.gmp_n, spSOEprimes[i]); } smallmpqs(fobj); return 1; //tells SIQS to not try to close the logfile } if (gmp_base10(fobj->qs_obj.gmp_n) > 140) { printf("input too big for SIQS\n"); return 1; } return 0; }
void extract_factors(factor_list_t *factor_list, fact_obj_t *fobj) { int i; FILE *logfile; char c[4]; // extract the factors for (i=0;i<factor_list->num_factors;i++) { mpz_t tmp; //init locals mpz_init(tmp); //convert the factor mp_t2gmp(&factor_list->final_factors[i]->factor,tmp); //divide it out mpz_tdiv_q(fobj->nfs_obj.gmp_n, fobj->nfs_obj.gmp_n, tmp); //check if its prime and log accordingly if (is_mpz_prp(tmp)) { //need to convert to yafu bigint to store add_to_factor_list(fobj, tmp); strncpy(c,"prp",4); } else { add_to_factor_list(fobj, tmp); strncpy(c,"C",2); } logfile = fopen(fobj->flogname, "a"); if (logfile == NULL) { printf("fopen error: %s\n", strerror(errno)); printf("could not open yafu logfile for appending\n"); } else { logprint(logfile, "%s%d = %s\n",c, gmp_base10(tmp), mpz_conv2str(&gstr1.s, 10, tmp)); fclose(logfile); } //free locals mpz_clear(tmp); } //log anything left over if (mpz_cmp_ui(fobj->nfs_obj.gmp_n, 1) > 0) { char c[4]; if (is_mpz_prp(fobj->nfs_obj.gmp_n)) { add_to_factor_list(fobj, fobj->nfs_obj.gmp_n); strncpy(c,"prp",4); } else { add_to_factor_list(fobj, fobj->nfs_obj.gmp_n); strncpy(c,"C",2); } logfile = fopen(fobj->flogname, "a"); if (logfile == NULL) { printf("fopen error: %s\n", strerror(errno)); printf("could not open yafu logfile for appending\n"); } else { logprint(logfile, "%s%d = %s\n",c, gmp_base10(fobj->nfs_obj.gmp_n), mpz_conv2str(&gstr1.s, 10, fobj->nfs_obj.gmp_n)); fclose(logfile); } mpz_set_ui(fobj->nfs_obj.gmp_n, 1); } return; }