static time_t check_date_min( struct tm * (*date_func)(const time_t *), const char *func_name ) { struct tm *date; time_t time = Time_Min; time_t good_time = 0; time_t time_change = Time_Min; /* Binary search for the exact failure point */ do { printf("# Trying %s(%.0f) min...", func_name, my_difftime(time, Time_Zero)); date = (*date_func)(&time); time_change /= 2; /* date_func() broke or tm_year overflowed or time_t overflowed */ if(date == NULL || date->tm_year > 70 || time > good_time) { printf(" failed\n"); time -= time_change; } else { printf(" success\n"); good_time = time; time += time_change; } } while((time_change < 0) && (good_time > Time_Min)); return(good_time); }
static struct tm * check_to_time_max( time_t (*to_time)(struct tm *), const char *func_name, struct tm * (*to_date)(const time_t *) ) { time_t round_trip; time_t time = Time_Max; time_t good_time = 0; struct tm *date; struct tm *good_date = (struct tm *) malloc(sizeof(struct tm)); time_t time_change = Time_Max; /* Binary search for the exact failure point */ do { printf("# Trying %s(%.0f) max...", func_name, my_difftime(time, Time_Zero)); date = (*to_date)(&time); round_trip = (*to_time)(date); time_change /= 2; /* date_func() broke or tm_year overflowed or time_t overflowed */ if(time != round_trip) { printf(" failed\n"); time -= time_change; } else { printf(" success\n"); good_time = time; memcpy(good_date, date, sizeof(struct tm)); time += time_change; } } while(time_change > 0 && good_time < Time_Max); return(good_date); }
void check_date_min( struct tm * (*date_func)(const time_t *), char *func_name ) { struct tm *date; time_t time = -1; time_t last_time = 0; time_t time_change; int i; for (i = 1; i <= 63; i++) { date = (*date_func)(&time); /* date_func() broke or tm_year underflowed */ if(date == NULL || date->tm_year > 70) break; last_time = time; time += time; /* time_t underflowed */ if( time > last_time ) break; } /* Binary search for the exact failure point */ time = last_time; time_change = last_time / 2; do { time += time_change; date = (*date_func)(&time); /* gmtime() broke or tm_year overflowed or time_t overflowed */ if(date == NULL || date->tm_year > 70 || time > last_time) { time = last_time; time_change = time_change / 2; } else { last_time = time; } } while(time_change < 0); printf("%20s min %.0f\n", func_name, my_difftime(last_time, Time_Zero)); }
// snap and save a frame from the camera tPvFrame *cameraSnap(tCamera* camera, int nbSnap) { unsigned long FrameSize = 0; PvAttrUint32Get(camera->Handle, "TotalBytesPerFrame", &FrameSize); tPvFrame *frames = new tPvFrame[nbSnap]; for(int i=0; i<nbSnap; i++) { // allocate the buffer for the single frame we need frames[i].Context[0] = camera; frames[i].ImageBuffer = new char[FrameSize]; if (frames[i].ImageBuffer) frames[i].ImageBufferSize = FrameSize; else throw "failed allocate Frame.ImageBuffer"; } /* cerr<<"Warming up !\n"; PvCaptureQueueFrame(camera->Handle, &(camera->Frame), NULL); while(camera->Frame.Status != ePvErrSuccess) PvCaptureQueueFrame(camera->Handle, &(camera->Frame), NULL); */ struct timeval myTVstart, myTVend; gettimeofday (&myTVstart, NULL); for(int i=0; i<nbSnap; i++) { if (!PvCaptureQueueFrame(camera->Handle, &(frames[i]), NULL)) { int index = 0; while ((PvCaptureWaitForFrameDone(camera->Handle, &(frames[i]), 10) == ePvErrTimeout) && (index < 100)){ index++; } if (frames[i].Status != ePvErrSuccess) cout << "the frame failed to be captured : "<< cameraGetError(frames[i].Status) << endl; } else cout << "failed to enqueue the frame" << endl; } gettimeofday (&myTVend, NULL); double duration = my_difftime (&myTVstart, &myTVend)/1000000.; cout << "Acuisition tooks " << duration*1000 << " mseconds, (" << (double)nbSnap/duration << " Hz)" << endl; return frames; }
void med_sieveblock_32k_sse41(uint8 *sieve, sieve_fb_compressed *fb, fb_list *full_fb, uint32 start_prime, uint8 s_init) { uint32 i; uint32 med_B; uint32 prime, root1, root2, tmp, stop; uint8 logp; helperstruct_t asm_input; med_B = full_fb->med_B; #ifdef QS_TIMING gettimeofday(&qs_timing_start, NULL); #endif //initialize the block BLOCK_INIT; // sieve primes less than 2^13 using optimized loops: it becomes // inefficient to do fully unrolled sse2 loops as the number of // steps through the block increases. While I didn't specifically // test whether 2^13 is the best point to start using loops, it seemed // good enough. any gains if it is not optmial will probably be minimal. #if defined(USE_ASM_SMALL_PRIME_SIEVING) asm_input.logptr = fb->logp; asm_input.primeptr = fb->prime; asm_input.root1ptr = fb->root1; asm_input.root2ptr = fb->root2; asm_input.sieve = sieve; asm_input.startprime = start_prime; asm_input.med_B = full_fb->fb_13bit_B-8; SIEVE_13b_ASM; i = asm_input.startprime; #else for (i=start_prime;i< full_fb->fb_13bit_B-8;i++) { uint8 *s2; prime = fb->prime[i]; root1 = fb->root1[i]; root2 = fb->root2[i]; logp = fb->logp[i]; SIEVE_2X; SIEVE_1X; SIEVE_LAST; UPDATE_ROOTS; } #endif // the small prime sieve stops just before prime exceeds 2^13 // the next sse2 sieve assumes primes exceed 2^13. since // some of the primes in the next set of 8 primes could be less // than the cutoff and some are greater than, we have to do this // small set of crossover primes manually, one at a time. for (; i<full_fb->fb_13bit_B; i++) { uint8 *s2; prime = fb->prime[i]; root1 = fb->root1[i]; root2 = fb->root2[i]; logp = fb->logp[i]; //// special exit condition: when prime > 8192 and i % 8 is 0; //if ((prime > 8192) && ((i&7) == 0)) // break; // invalid root (part of poly->a) if (prime == 0) continue; SIEVE_2X; SIEVE_1X; SIEVE_LAST; UPDATE_ROOTS; } // sieve primes 8 at a time, where 8192 < p < blocksize/3 _INIT_SSE2_SMALL_PRIME_SIEVE; _SSE2_SMALL_PRIME_SIEVE_32k_DIV3; // the sse2 sieve stops just before prime exceeds blocksize/3 // the next sse2 sieve assumes primes exceed blocksize/3. since // some of the primes in the next set of 8 primes could be less // than the cutoff and some are greater than, we have to do this // small set of crossover primes manually, one at a time. for (; i < full_fb->fb_32k_div3; i++) { prime = fb->prime[i]; root1 = fb->root1[i]; root2 = fb->root2[i]; logp = fb->logp[i]; // invalid root (part of poly->a) if (prime == 0) continue; SIEVE_1X; SIEVE_LAST; UPDATE_ROOTS; } // sieve primes 8 at a time, where blocksize/3 < p < 2^14 _INIT_SSE2_SMALL_PRIME_SIEVE; _SSE2_SMALL_PRIME_SIEVE_14b; // do this small set of crossover primes manually, one at a time, // this time for the 14 bit crossover. for (; i < full_fb->fb_14bit_B; i++) { prime = fb->prime[i]; root1 = fb->root1[i]; root2 = fb->root2[i]; logp = fb->logp[i]; // invalid root (part of poly->a) if (prime == 0) continue; SIEVE_1X; SIEVE_LAST; UPDATE_ROOTS; } // sieve primes 8 at a time, 2^14 < p < 2^15 _INIT_SSE2_SMALL_PRIME_SIEVE; _SSE2_SMALL_PRIME_SIEVE_15b; // do this small set of crossover primes manually, one at a time, // this time for the 15 bit crossover. for (i = full_fb->fb_15bit_B - 8; i<med_B; i++) { prime = fb->prime[i]; root1 = fb->root1[i]; root2 = fb->root2[i]; logp = fb->logp[i]; if ((prime > 32768) && ((i&7) == 0)) break; // invalid root (part of poly->a) if (prime == 0) continue; SIEVE_1X; SIEVE_LAST; UPDATE_ROOTS; } // sieve primes 8 at a time, 2^15 < p < med_B _INIT_SSE2_SMALL_PRIME_SIEVE; _SSE41_SMALL_PRIME_SIEVE; #ifdef QS_TIMING gettimeofday (&qs_timing_stop, NULL); qs_timing_diff = my_difftime (&qs_timing_start, &qs_timing_stop); SIEVE_STG1 += ((double)qs_timing_diff->secs + (double)qs_timing_diff->usecs / 1000000); free(qs_timing_diff); gettimeofday(&qs_timing_start, NULL); #endif 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; }
int main(void) { time_t gmtime_max; time_t gmtime_min; time_t localtime_max; time_t localtime_min; #ifdef HAS_TIMEGM struct tm* timegm_max; struct tm* timegm_min; #endif struct tm* mktime_max; struct tm* mktime_min; guess_time_limits_from_types(); gmtime_max = check_date_max(gmtime, "gmtime"); gmtime_min = check_date_min(gmtime, "gmtime"); localtime_max = check_date_max(localtime, "localtime"); localtime_min = check_date_min(localtime, "localtime"); #ifdef HAS_TIMEGM Time_Max = gmtime_max; Time_Min = gmtime_min; timegm_max = check_to_time_max(timegm, "timegm", gmtime); timegm_min = check_to_time_min(timegm, "timegm", gmtime); #endif Time_Max = localtime_max; Time_Min = localtime_min; mktime_max = check_to_time_max(mktime, "mktime", localtime); mktime_min = check_to_time_min(mktime, "mktime", localtime); printf("# system time.h limits, as JSON\n"); printf("{\n"); printf(" \"gmtime\": { \"max\": %.0f, \"min\": %0.f },\n", my_difftime(gmtime_max, Time_Zero), my_difftime(gmtime_min, Time_Zero) ); printf(" \"localtime\": { \"max\": %.0f, \"min\": %0.f },\n", my_difftime(localtime_max, Time_Zero), my_difftime(localtime_min, Time_Zero) ); printf(" \"mktime\": {\n"); printf(" \"max\": { %s },\n", tm_as_json(mktime_max)); printf(" \"min\": { %s }\n", tm_as_json(mktime_min)); printf(" }\n"); #ifdef HAS_TIMEGM printf(" ,\n"); printf(" \"timegm\": {\n"); printf(" \"max\": { %s },\n", tm_as_json(timegm_max)); printf(" \"min\": { %s }\n", tm_as_json(timegm_min)); printf(" }\n"); #endif printf("}\n"); return 0; }
void resieve_medprimes_32k(uint8 parity, uint32 poly_id, uint32 bnum, static_conf_t *sconf, dynamic_conf_t *dconf) { //we have flagged this sieve offset as likely to produce a relation //nothing left to do now but check and see. int i; uint32 bound, report_num; int smooth_num; uint32 *fb_offsets; sieve_fb *fb; sieve_fb_compressed *fbc; fb_element_siqs *fullfb_ptr, *fullfb = sconf->factor_base->list; uint32 block_loc; uint16 *corrections = dconf->corrections; fullfb_ptr = fullfb; if (parity) { fb = dconf->fb_sieve_n; fbc = dconf->comp_sieve_n; } else { fb = dconf->fb_sieve_p; fbc = dconf->comp_sieve_p; } #ifdef QS_TIMING gettimeofday(&qs_timing_start, NULL); #endif for (report_num = 0; report_num < dconf->num_reports; report_num++) { #ifdef USE_YAFU_TDIV z32 *tmp32 = &dconf->Qvals32[report_num]; #endif if (!dconf->valid_Qs[report_num]) continue; // pull the details of this report to get started. fb_offsets = &dconf->fb_offsets[report_num][0]; smooth_num = dconf->smooth_num[report_num]; block_loc = dconf->reports[report_num]; // where tdiv_medprimes left off i = sconf->factor_base->fb_13bit_B; corrections[0] = 32768 - block_loc; corrections[1] = 32768 - block_loc; corrections[2] = 32768 - block_loc; corrections[3] = 32768 - block_loc; corrections[4] = 32768 - block_loc; corrections[5] = 32768 - block_loc; corrections[6] = 32768 - block_loc; corrections[7] = 32768 - block_loc; // since the blocksize is bigger for YAFU_64K, skip resieving of primes // up to 14 bits in size and instead use standard normal trial division. bound = sconf->factor_base->fb_14bit_B; while ((uint32)i < bound) { //minimum prime > blocksize / 2 //maximum correction = blocksize //maximum starting value > blocksize * 3/2 //max steps = 2 //this misses all reports at block_loc = 0. would need to check //for equality to blocksize in that case //printf("prime = %u, roots = %u,%u. max steps = %u\n", // fbc->prime[i],fbc->root1[i],fbc->root2[i], // (fbc->prime[i] - 1 + 32768) / fbc->prime[i]); //printf("prime = %u, roots = %u,%u. max steps = %u\n", // fbc->prime[i+1],fbc->root1[i+1],fbc->root2[i+1], // (fbc->prime[i+1] - 1 + 32768) / fbc->prime[i+1]); //printf("prime = %u, roots = %u,%u. max steps = %u\n", // fbc->prime[i+2],fbc->root1[i+2],fbc->root2[i+2], // (fbc->prime[i+2] - 1 + 32768) / fbc->prime[i+2]); //printf("prime = %u, roots = %u,%u. max steps = %u\n", // fbc->prime[i+3],fbc->root1[i+3],fbc->root2[i+3], // (fbc->prime[i+3] - 1 + 32768) / fbc->prime[i+3]); uint32 result = 0; RESIEVE_8X_14BIT_MAX; if (result == 0) { i += 8; continue; } if (result & 0x2) { DIVIDE_RESIEVED_PRIME(0); } if (result & 0x8) { DIVIDE_RESIEVED_PRIME(1); } if (result & 0x20) { DIVIDE_RESIEVED_PRIME(2); } if (result & 0x80) { DIVIDE_RESIEVED_PRIME(3); } if (result & 0x200) { DIVIDE_RESIEVED_PRIME(4); } if (result & 0x800) { DIVIDE_RESIEVED_PRIME(5); } if (result & 0x2000) { DIVIDE_RESIEVED_PRIME(6); } if (result & 0x8000) { DIVIDE_RESIEVED_PRIME(7); } i += 8; } bound = sconf->factor_base->fb_15bit_B; while ((uint32)i < bound) { uint32 result = 0; RESIEVE_8X_15BIT_MAX; if (result == 0) { i += 8; continue; } if (result & 0x2) { DIVIDE_RESIEVED_PRIME(0); } if (result & 0x8) { DIVIDE_RESIEVED_PRIME(1); } if (result & 0x20) { DIVIDE_RESIEVED_PRIME(2); } if (result & 0x80) { DIVIDE_RESIEVED_PRIME(3); } if (result & 0x200) { DIVIDE_RESIEVED_PRIME(4); } if (result & 0x800) { DIVIDE_RESIEVED_PRIME(5); } if (result & 0x2000) { DIVIDE_RESIEVED_PRIME(6); } if (result & 0x8000) { DIVIDE_RESIEVED_PRIME(7); } i += 8; } bound = sconf->factor_base->med_B; while ((uint32)i < bound) { uint32 result = 0; RESIEVE_8X_16BIT_MAX; if (result == 0) { i += 8; continue; } if (result & 0x2) { DIVIDE_RESIEVED_PRIME(0); } if (result & 0x8) { DIVIDE_RESIEVED_PRIME(1); } if (result & 0x20) { DIVIDE_RESIEVED_PRIME(2); } if (result & 0x80) { DIVIDE_RESIEVED_PRIME(3); } if (result & 0x200) { DIVIDE_RESIEVED_PRIME(4); } if (result & 0x800) { DIVIDE_RESIEVED_PRIME(5); } if (result & 0x2000) { DIVIDE_RESIEVED_PRIME(6); } if (result & 0x8000) { DIVIDE_RESIEVED_PRIME(7); } i += 8; } // after either resieving or standard trial division, record // how many factors we've found so far. dconf->smooth_num[report_num] = smooth_num; } #ifdef QS_TIMING gettimeofday (&qs_timing_stop, NULL); qs_timing_diff = my_difftime (&qs_timing_start, &qs_timing_stop); TF_STG4 += ((double)qs_timing_diff->secs + (double)qs_timing_diff->usecs / 1000000); free(qs_timing_diff); #endif return; }
void med_sieveblock_64k(uint8 *sieve, sieve_fb_compressed *fb, fb_list *full_fb, uint32 start_prime, uint8 s_init) { uint32 i; uint32 med_B; #if !defined(SSE2_ASM_SIEVING) && !defined(ASM_SIEVING) uint32 prime, root1, root2, tmp, stop; uint8 logp; #endif #if defined(SSE2_ASM_SIEVING) || defined(ASM_SIEVING) helperstruct_t asm_input; #endif med_B = full_fb->med_B; #ifdef QS_TIMING gettimeofday(&qs_timing_start, NULL); #endif //initialize the block BLOCK_INIT; #ifdef ASM_SIEVING asm_input.logptr = fb->logp; asm_input.primeptr = fb->prime; asm_input.root1ptr = fb->root1; asm_input.root2ptr = fb->root2; asm_input.sieve = sieve; asm_input.startprime = start_prime; asm_input.med_B = med_B; SIEVE_MED_P_ASM; i = asm_input.startprime; #else for (i=start_prime;i<med_B;i++) { uint8 *s2; prime = fb->prime[i]; root1 = fb->root1[i]; root2 = fb->root2[i]; logp = fb->logp[i]; CHECK_2X_DONE; SIEVE_2X; SIEVE_1X; SIEVE_LAST; UPDATE_ROOTS; } for (;i<med_B;i++) { prime = fb->prime[i]; root1 = fb->root1[i]; root2 = fb->root2[i]; logp = fb->logp[i]; CHECK_1X_DONE; SIEVE_1X; SIEVE_LAST; UPDATE_ROOTS; } //if there are primes left bigger than the blocksize, this will take //care of them. if not, it doesn't run at all. for (;i<med_B;i++) { prime = fb->prime[i]; root1 = fb->root1[i]; root2 = fb->root2[i]; logp = fb->logp[i]; SIEVE_BIG; UPDATE_ROOTS; } #endif #ifdef QS_TIMING gettimeofday (&qs_timing_stop, NULL); qs_timing_diff = my_difftime (&qs_timing_start, &qs_timing_stop); SIEVE_STG1 += ((double)qs_timing_diff->secs + (double)qs_timing_diff->usecs / 1000000); free(qs_timing_diff); gettimeofday(&qs_timing_start, NULL); #endif return; }
int test_sieve(fact_obj_t* fobj, void* args, int njobs, int are_files) /* if(are_files), then treat args as a char** list of (external) polys * else args is a nfs_job_t* array of job structs * the latter is preferred */ // @ben: the idea is a new yafu function "testsieve(n, ...)" where args are // an arbitrary list of files of external polys { uint32 count; int i, minscore_id = 0; double* score = (double*)malloc(njobs * sizeof(double)); double t_time, min_score = 999999999.; char orig_name[GSTR_MAXSIZE]; // don't clobber fobj->nfs_obj.job_infile char time[80]; uint32 spq_range = 2000, actual_range; FILE *flog; char** filenames; // args nfs_job_t* jobs; // args struct timeval stop, stop2; // stop time of this job struct timeval start, start2; // start time of this job TIME_DIFF * difference; if( score == NULL ) { printf("Couldn't alloc memory!\n"); exit(-1); } // check to make sure we can find ggnfs sievers if (check_for_sievers(fobj, 0) == 1) { printf("test: can't find ggnfs lattice sievers - aborting test sieving\n"); return -1; } gettimeofday(&start2, NULL); strcpy(orig_name, fobj->nfs_obj.job_infile); // necessary because parse/fill_job_file() get filename from fobj if( are_files ) { // read files into job structs (get fblim) filenames = (char**) args; jobs = (nfs_job_t*)malloc(njobs * sizeof(nfs_job_t)); if( jobs == NULL ) { printf("Couldn't alloc memory!\n"); exit(-1); } memset(jobs, 0, njobs*sizeof(nfs_job_t)); for(i = 0; i < njobs; i++) { uint32 missing_params; strcpy(fobj->nfs_obj.job_infile, filenames[i]); missing_params = parse_job_file(fobj, jobs+i); // get fblim get_ggnfs_params(fobj, jobs+i); // get siever if( missing_params ) { if( VFLAG >= 0 ) printf("test: warning: \"%s\" is missing some paramters (%#X). filling them.\n", filenames[i], missing_params); fill_job_file(fobj, jobs+i, missing_params); } // adjust a/rlim, lpbr/a, and mfbr/a if advantageous skew_snfs_params(fobj, jobs+i); } } else { // create poly files jobs = (nfs_job_t *) args; filenames = (char**)malloc(njobs*sizeof(char*)); if( !filenames ) { printf("malloc derped it up!\n"); exit(-1); } for(i = 0; i < njobs; i++) { FILE* out; filenames[i] = (char*)malloc(GSTR_MAXSIZE); if( !filenames[i] ) { printf("malloc failed\n"); exit(-1); } sprintf(filenames[i], "test-sieve-%d.poly", i); out = fopen(filenames[i], "w"); if( !out ) { printf("test: couldn't open %s for writing, aborting test sieve\n", filenames[i]); return -1; } if( jobs[i].snfs ) print_snfs(jobs[i].snfs, out); else { gmp_fprintf(out, "n: %Zd\n", fobj->nfs_obj.gmp_n); print_poly(jobs[i].poly, out); } fclose(out); strcpy(fobj->nfs_obj.job_infile, filenames[i]); fill_job_file(fobj, jobs+i, PARAM_FLAG_ALL); } // that seems like a lot more code than it should be } strcpy(fobj->nfs_obj.job_infile, orig_name); // now we can get to the actual testing for(i = 0; i < njobs; i++) { char syscmd[GSTR_MAXSIZE], tmpbuf[GSTR_MAXSIZE], side[32]; FILE* in; // should probably scale the range of special-q to test based // on input difficulty, but not sure how to do that easily... if( jobs[i].poly->side == RATIONAL_SPQ) { sprintf(side, "rational"); jobs[i].startq = jobs[i].rlim; // no reason to test sieve *inside* the fb } else { sprintf(side, "algebraic"); jobs[i].startq = jobs[i].alim; // ditto } flog = fopen(fobj->flogname, "a"); //create the afb/rfb - we don't want the time it takes to do this to //pollute the sieve timings sprintf(syscmd, "%s -b %s -k -c 0 -F", jobs[i].sievername, filenames[i]); if (VFLAG > 0) printf("\ntest: generating factor bases\n"); gettimeofday(&start, NULL); system(syscmd); gettimeofday(&stop, NULL); difference = my_difftime (&start, &stop); t_time = ((double)difference->secs + (double)difference->usecs / 1000000); free(difference); if (VFLAG > 0) printf("test: fb generation took %6.4f seconds\n", t_time); logprint(flog, "test: fb generation took %6.4f seconds\n", t_time); MySleep(.1); //start the test sprintf(syscmd,"%s%s -%c %s -f %u -c %u -o %s.out", jobs[i].sievername, VFLAG>0?" -v":"", side[0], filenames[i], jobs[i].startq, spq_range, filenames[i]); if (VFLAG > 0) printf("test: commencing test sieving of polynomial %d on the %s side over range %u-%u\n", i, side, jobs[i].startq, jobs[i].startq + spq_range); logprint(flog, "test: commencing test sieving of polynomial %d on the %s side over range %u-%u\n", i, side, jobs[i].startq, jobs[i].startq + spq_range); print_job(&jobs[i], flog); fclose(flog); gettimeofday(&start, NULL); system(syscmd); gettimeofday(&stop, NULL); difference = my_difftime (&start, &stop); t_time = ((double)difference->secs + (double)difference->usecs / 1000000); free(difference); //count relations sprintf(tmpbuf, "%s.out", filenames[i]); in = fopen(tmpbuf, "r"); actual_range = 0; count = 0; if( !in ) { score[i] = 999999999.; //est = 7*365*24*3600; // 7 years seems like a nice round number } else { // scan the data file and // 1) count the relations // 2) save the last four relations to a buffer in order to extract the last processed // special-q. // we need both 1) and 2) to compute yield correctly. char **lines, *ptr, tmp[GSTR_MAXSIZE]; int line; int j; lines = (char **)malloc(4 * sizeof(char *)); for (j=0; j < 4; j++) lines[j] = (char *)malloc(GSTR_MAXSIZE * sizeof(char)); line = 0; count = 0; while (1) { // read a line into the next position of the circular buffer ptr = fgets(tmp, GSTR_MAXSIZE, in); if (ptr == NULL) break; // quick check that it might be a valid line if (strlen(tmp) > 30) { // wrap if (++line > 3) line = 0; // then copy strcpy(lines[line], tmp); } count++; } fclose(in); line = get_spq(lines, line, fobj); actual_range = line - jobs[i].startq; if (VFLAG > 0) printf("test: found %u relations in a range of %u special-q\n", count, actual_range); if (actual_range > spq_range) actual_range = spq_range; for (j=0; j < 4; j++) free(lines[j]); free(lines); score[i] = t_time / count; // use estimated sieving time to rank, not sec/rel, since the latter // is a function of parameterization and therefore not directly comparable // to each other. score[i] = (score[i] * jobs[i].min_rels * 1.25) / THREADS; // be conservative about estimates } flog = fopen(fobj->flogname, "a"); if( score[i] < min_score ) { minscore_id = i; min_score = score[i]; if (VFLAG > 0) printf("test: new best estimated total sieving time = %s (with %d threads)\n", time_from_secs(time, (unsigned long)score[i]), THREADS); logprint(flog, "test: new best estimated total sieving time = %s (with %d threads)\n", time_from_secs(time, (unsigned long)score[i]), THREADS); // edit lbpr/a depending on test results. we target something around 2 rels/Q. // could also change siever version in more extreme cases. if (count > 4*actual_range) { if (VFLAG > 0) printf("test: yield greater than 4x/spq, reducing lpbr/lpba\n"); jobs[i].lpba--; jobs[i].lpbr--; jobs[i].mfba -= 2; jobs[i].mfbr -= 2; } if (count > 8*actual_range) { char *pos; int siever; pos = strstr(jobs[i].sievername, "gnfs-lasieve4I"); siever = (pos[14] - 48) * 10 + (pos[15] - 48); if (VFLAG > 0) printf("test: yield greater than 8x/spq, reducing siever version\n"); switch (siever) { case 11: if (VFLAG > 0) printf("test: siever version cannot be decreased further\n"); jobs[i].snfs->siever = 11; break; case 12: pos[15] = '1'; jobs[i].snfs->siever = 11; break; case 13: pos[15] = '2'; jobs[i].snfs->siever = 12; break; case 14: pos[15] = '3'; jobs[i].snfs->siever = 13; break; case 15: pos[15] = '4'; jobs[i].snfs->siever = 14; break; case 16: pos[15] = '5'; jobs[i].snfs->siever = 15; break; } } if (count < actual_range) { if (VFLAG > 0) printf("test: yield less than 1x/spq, increasing lpbr/lpba\n"); jobs[i].lpba++; jobs[i].lpbr++; jobs[i].mfba += 2; jobs[i].mfbr += 2; } if (count < (actual_range/2)) { char *pos; int siever; pos = strstr(jobs[i].sievername, "gnfs-lasieve4I"); siever = (pos[14] - 48) * 10 + (pos[15] - 48); if (VFLAG > 0) printf("test: yield less than 1x/2*spq, increasing siever version\n"); switch (siever) { case 16: if (VFLAG > 0) printf("test: siever version cannot be increased further\n"); jobs[i].snfs->siever = 16; break; case 15: pos[15] = '6'; jobs[i].snfs->siever = 16; break; case 14: pos[15] = '5'; jobs[i].snfs->siever = 15; break; case 13: pos[15] = '4'; jobs[i].snfs->siever = 14; break; case 12: pos[15] = '3'; jobs[i].snfs->siever = 13; break; case 11: pos[15] = '2'; jobs[i].snfs->siever = 12; break; } } } else { if (VFLAG > 0) printf("test: estimated total sieving time = %s (with %d threads)\n", time_from_secs(time, (unsigned long)score[i]), THREADS); logprint(flog, "test: estimated total sieving time = %s (with %d threads)\n", time_from_secs(time, (unsigned long)score[i]), THREADS); } fclose(flog); remove(tmpbuf); // clean up after ourselves sprintf(tmpbuf, "%s", filenames[i]); remove(tmpbuf); sprintf(tmpbuf, "%s.afb.0", filenames[i]); remove(tmpbuf); } // clean up memory allocated if( are_files ) { for(i = 0; i < njobs; i++) { mpz_polys_free(jobs[i].poly); free(jobs[i].poly); } free(jobs); } else { for(i = 0; i < njobs; i++) free(filenames[i]); free(filenames); } flog = fopen(fobj->flogname, "a"); gettimeofday(&stop2, NULL); difference = my_difftime (&start2, &stop2); t_time = ((double)difference->secs + (double)difference->usecs / 1000000); free(difference); if (VFLAG > 0) printf("test: test sieving took %1.2f seconds\n", t_time); logprint(flog, "test: test sieving took %1.2f seconds\n", t_time); return minscore_id; }
void resieve_medprimes_64k(uint8 parity, uint32 poly_id, uint32 bnum, static_conf_t *sconf, dynamic_conf_t *dconf) { //we have flagged this sieve offset as likely to produce a relation //nothing left to do now but check and see. int i; uint32 bound, report_num; int smooth_num; uint32 *fb_offsets; sieve_fb *fb; sieve_fb_compressed *fbc; fb_element_siqs *fullfb_ptr, *fullfb = sconf->factor_base->list; uint32 block_loc; uint16 *corrections = dconf->corrections; fullfb_ptr = fullfb; if (parity) { fb = dconf->fb_sieve_n; fbc = dconf->comp_sieve_n; } else { fb = dconf->fb_sieve_p; fbc = dconf->comp_sieve_p; } #ifdef QS_TIMING gettimeofday(&qs_timing_start, NULL); #endif for (report_num = 0; report_num < dconf->num_reports; report_num++) { #ifdef USE_YAFU_TDIV z32 *tmp32 = &dconf->Qvals32[report_num]; #endif if (!dconf->valid_Qs[report_num]) continue; // pull the details of this report to get started. fb_offsets = &dconf->fb_offsets[report_num][0]; smooth_num = dconf->smooth_num[report_num]; block_loc = dconf->reports[report_num]; // where tdiv_medprimes left off i = sconf->factor_base->fb_14bit_B; corrections[0] = 65536 - block_loc; corrections[1] = 65536 - block_loc; corrections[2] = 65536 - block_loc; corrections[3] = 65536 - block_loc; corrections[4] = 65536 - block_loc; corrections[5] = 65536 - block_loc; corrections[6] = 65536 - block_loc; corrections[7] = 65536 - block_loc; bound = sconf->factor_base->fb_15bit_B; while ((uint32)i < bound) { uint32 result = 0; RESIEVE_8X_15BIT_MAX; if (result == 0) { i += 8; continue; } if (result & 0x2) { DIVIDE_RESIEVED_PRIME(0); } if (result & 0x8) { DIVIDE_RESIEVED_PRIME(1); } if (result & 0x20) { DIVIDE_RESIEVED_PRIME(2); } if (result & 0x80) { DIVIDE_RESIEVED_PRIME(3); } if (result & 0x200) { DIVIDE_RESIEVED_PRIME(4); } if (result & 0x800) { DIVIDE_RESIEVED_PRIME(5); } if (result & 0x2000) { DIVIDE_RESIEVED_PRIME(6); } if (result & 0x8000) { DIVIDE_RESIEVED_PRIME(7); } i += 8; } bound = sconf->factor_base->med_B; while ((uint32)i < bound) { uint32 result = 0; RESIEVE_8X_16BIT_MAX; if (result == 0) { i += 8; continue; } if (result & 0x2) { DIVIDE_RESIEVED_PRIME(0); } if (result & 0x8) { DIVIDE_RESIEVED_PRIME(1); } if (result & 0x20) { DIVIDE_RESIEVED_PRIME(2); } if (result & 0x80) { DIVIDE_RESIEVED_PRIME(3); } if (result & 0x200) { DIVIDE_RESIEVED_PRIME(4); } if (result & 0x800) { DIVIDE_RESIEVED_PRIME(5); } if (result & 0x2000) { DIVIDE_RESIEVED_PRIME(6); } if (result & 0x8000) { DIVIDE_RESIEVED_PRIME(7); } i += 8; } // after either resieving or standard trial division, record // how many factors we've found so far. dconf->smooth_num[report_num] = smooth_num; } #ifdef QS_TIMING gettimeofday (&qs_timing_stop, NULL); qs_timing_diff = my_difftime (&qs_timing_start, &qs_timing_stop); TF_STG4 += ((double)qs_timing_diff->secs + (double)qs_timing_diff->usecs / 1000000); free(qs_timing_diff); #endif return; }
void getRoots(soe_staticdata_t *sdata, thread_soedata_t *thread_data) { int prime, prodN; uint64 startprime; uint64 i; int j; uint32 range, lastid; //timing double t; struct timeval tstart, tstop; TIME_DIFF * difference; prodN = (int)sdata->prodN; startprime = sdata->startprime; gettimeofday(&tstart, NULL); for (i=startprime; i<sdata->bucket_start_id; i++) { uint32 inv; prime = sdata->sieve_p[i]; //sieving requires that we find the offset of each sieve prime in each block //that we sieve. We are more restricted in choice of offset because we //sieve residue classes. A good way to find the offset is the extended //euclidean algorithm, which reads ax + by = gcd(a,b), //where a = prime, b = prodN, and therefore gcd = 1. //since a and b are coprime, y is the multiplicative inverse of prodN modulo prime. //This value is a constant, so compute it here in order to facilitate //finding offsets later. //solve prodN ^ -1 % p inv = modinv_1(prodN,prime); sdata->root[i] = prime - inv; } gettimeofday(&tstop, NULL); difference = my_difftime(&tstart, &tstop); t = ((double)difference->secs + (double)difference->usecs / 1000000); free(difference); if (VFLAG > 2) printf("time to compute linear sieve roots = %1.2f\n", t); gettimeofday(&tstart, NULL); // start the threads for (i = 0; i < THREADS - 1; i++) start_soe_worker_thread(thread_data + i, 0); start_soe_worker_thread(thread_data + i, 1); range = (sdata->pboundi - sdata->bucket_start_id) / THREADS; lastid = sdata->bucket_start_id; // divvy up the primes for (j = 0; j < THREADS; j++) { thread_soedata_t *t = thread_data + j; t->sdata = *sdata; t->startid = lastid; t->stopid = t->startid + range; lastid = t->stopid; } // the last one gets any leftover if (thread_data[THREADS-1].stopid != sdata->pboundi) thread_data[THREADS-1].stopid = sdata->pboundi; // now run with the threads for (j = 0; j < THREADS; j++) { thread_soedata_t *t = thread_data + j; if (j == (THREADS - 1)) { if (VFLAG > 2) printf("starting root computation over %u to %u\n", t->startid, t->stopid); // run in the current thread // bucket sieved primes need more data if (sdata->sieve_range == 0) { for (i = t->startid; i < t->stopid; i++) { uint32 inv; prime = t->sdata.sieve_p[i]; //sieving requires that we find the offset of each sieve prime in each block //that we sieve. We are more restricted in choice of offset because we //sieve residue classes. A good way to find the offset is the extended //euclidean algorithm, which reads ax + by = gcd(a,b), //where a = prime, b = prodN, and therefore gcd = 1. //since a and b are coprime, y is the multiplicative inverse of prodN modulo prime. //This value is a constant, so compute it here in order to facilitate //finding offsets later. //solve prodN ^ -1 % p inv = modinv_1(prodN, prime); t->sdata.root[i] = prime - inv; //we can also speed things up by computing and storing the residue //mod p of the first sieve location in the first residue class. This provides //a speedup by pulling this constant (involving a division) out of a critical loop //when finding offsets of bucket sieved primes. //these are only used by bucket sieved primes. t->sdata.lower_mod_prime[i - t->sdata.bucket_start_id] = (t->sdata.lowlimit + 1) % prime; } } else { mpz_t tmpz; //mpz_t t1, t2; mpz_init(tmpz); //uint64 res; //experiment for custom ranges that can be expressed as base^exp + range //mpz_init(t1); //mpz_init(t2); mpz_add_ui(tmpz, *t->sdata.offset, t->sdata.lowlimit + 1); for (i = t->startid; i < t->stopid; i++) { uint32 inv; prime = t->sdata.sieve_p[i]; //sieving requires that we find the offset of each sieve prime in each block //that we sieve. We are more restricted in choice of offset because we //sieve residue classes. A good way to find the offset is the extended //euclidean algorithm, which reads ax + by = gcd(a,b), //where a = prime, b = prodN, and therefore gcd = 1. //since a and b are coprime, y is the multiplicative inverse of prodN modulo prime. //This value is a constant, so compute it here in order to facilitate //finding offsets later. //solve prodN ^ -1 % p inv = modinv_1(prodN,prime); t->sdata.root[i] = prime - inv; //we can also speed things up by computing and storing the residue //mod p of the first sieve location in the first residue class. This provides //a speedup by pulling this constant (involving a division) out of a critical loop //when finding offsets of bucket sieved primes. //these are only used by bucket sieved primes. t->sdata.lower_mod_prime[i - t->sdata.bucket_start_id] = mpz_tdiv_ui(tmpz, prime); //mpz_set_ui(t2,prime); //mpz_set_ui(t1, 1000000000); //mpz_powm_ui(t1, t1, 111111, t2); //res = mpz_get_64(t1); //t->sdata.lower_mod_prime[i - t->sdata.bucket_start_id] = (uint32)res; } //mpz_clear(t1); //mpz_clear(t2); } } else { t->command = SOE_COMPUTE_ROOTS; #if defined(WIN32) || defined(_WIN64) SetEvent(t->run_event); #else pthread_cond_signal(&t->run_cond); pthread_mutex_unlock(&t->run_lock); #endif } } //wait for each thread to finish for (i = 0; i < THREADS; i++) { thread_soedata_t *t = thread_data + i; if (i < (THREADS - 1)) { #if defined(WIN32) || defined(_WIN64) WaitForSingleObject(t->finish_event, INFINITE); #else pthread_mutex_lock(&t->run_lock); while (t->command != SOE_COMMAND_WAIT) pthread_cond_wait(&t->run_cond, &t->run_lock); #endif } } //stop the worker threads for (i=0; i<THREADS - 1; i++) stop_soe_worker_thread(thread_data + i, 0); gettimeofday(&tstop, NULL); difference = my_difftime(&tstart, &tstop); t = ((double)difference->secs + (double)difference->usecs / 1000000); free(difference); if (VFLAG > 2) printf("time to compute bucket sieve roots = %1.2f\n", t); #ifdef INPLACE_BUCKET gettimeofday(&tstart, NULL); // inplace primes have special requirements because they operate on // the normal number line, and not in residue space for (; i < sdata->pboundi; i++) { uint64 starthit; uint32 startclass; uint64 startbit; uint32 rclass, bnum, rclassid; uint32 index = i - sdata->inplace_start_id; int a; // copy the prime into the special data structure //sdata->inplace_data[index].prime = sdata->sieve_p[i]; // pull some computations involving a division out of the inner loop. // we need to know what prime/prodN and prime%prodN are. sdata->inplace_data[index].p_div = sdata->sieve_p[i] / prodN; rclass = sdata->sieve_p[i] % prodN; rclassid = resID_mod30[rclass]; sdata->inplace_data[index].p_mod = rclass; // now compute the starting hit in our sieve interval... starthit = (sdata->lowlimit / sdata->sieve_p[i] + 1) * sdata->sieve_p[i]; // ... that is in one of our residue classes startclass = starthit % prodN; // using a lookup table startclass = next_mod30[rclassid][startclass]; starthit += ((uint64)sdata->sieve_p[i] * (uint64)(startclass >> 8)); startclass = startclass & 0xff; // the starting accumulated error is equal to the starting class sdata->inplace_data[index].eacc = startclass; // now compute the starting bit and block location for this starting hit startbit = (starthit - sdata->lowlimit - (uint64)startclass) / (uint64)prodN; // sanity check if (((starthit - sdata->lowlimit - (uint64)startclass) % (uint64)prodN) != 0) printf("starting bit is invalid!\n"); sdata->inplace_data[index].bitloc = startbit & FLAGSIZEm1; bnum = startbit >> FLAGBITS; // finally, add the prime to a linked list // if the next hit is within our interval if (bnum < sdata->blocks) { //then reassign this prime to its next hit if (sdata->inplace_ptrs[bnum][resID_mod30[startclass]] == -1) { // this is the first hit in this block and rclass, so set the pointer // to this prime, and set next_pid = 0 so that we know to stop here // when we sieve sdata->inplace_ptrs[bnum][resID_mod30[startclass]] = index; sdata->inplace_data[index].next_pid = 0; } else { // add this prime to a listed list within the inplace sieve array. // this is done by first setting the next id to the current prime // at the end of the list sdata->inplace_data[index].next_pid = sdata->inplace_ptrs[bnum][resID_mod30[startclass]]; // and then setting the end of the list to this prime sdata->inplace_ptrs[bnum][resID_mod30[startclass]] = index; } } } gettimeofday(&tstop, NULL); difference = my_difftime(&tstart, &tstop); t = ((double)difference->secs + (double)difference->usecs / 1000000); free(difference); if (VFLAG > 2) printf("time to compute inplace sieve roots = %1.2f\n", t); #endif return; }
void trial_divide_Q_siqs(uint32 report_num, uint8 parity, uint32 poly_id, uint32 bnum, static_conf_t *sconf, dynamic_conf_t *dconf) { //we have flagged this sieve offset as likely to produce a relation //nothing left to do now but check and see. uint64 q64, f64; int j,it; uint32 prime; int smooth_num; uint32 *fb_offsets; uint32 polya_factors[20]; sieve_fb *fb; uint32 offset, block_loc; fb_offsets = &dconf->fb_offsets[report_num][0]; smooth_num = dconf->smooth_num[report_num]; block_loc = dconf->reports[report_num]; #ifdef QS_TIMING gettimeofday(&qs_timing_start, NULL); #endif offset = (bnum << sconf->qs_blockbits) + block_loc; if (parity) fb = dconf->fb_sieve_n; else fb = dconf->fb_sieve_p; #ifdef USE_YAFU_TDIV z32_to_mpz(&dconf->Qvals32[report_num], dconf->Qvals[report_num]); #endif //check for additional factors of the a-poly factors //make a separate list then merge it with fb_offsets it=0; //max 20 factors allocated for - should be overkill for (j = 0; (j < dconf->curr_poly->s) && (it < 20); j++) { //fbptr = fb + dconf->curr_poly->qlisort[j]; //prime = fbptr->prime; prime = fb[dconf->curr_poly->qlisort[j]].prime; while ((mpz_tdiv_ui(dconf->Qvals[report_num],prime) == 0) && (it < 20)) { mpz_tdiv_q_ui(dconf->Qvals[report_num], dconf->Qvals[report_num], prime); polya_factors[it++] = dconf->curr_poly->qlisort[j]; } } //check if it completely factored by looking at the unfactored portion in tmp //if ((mpz_size(dconf->Qvals[report_num]) == 1) && //(mpz_get_64(dconf->Qvals[report_num]) < (uint64)sconf->large_prime_max)) if ((mpz_size(dconf->Qvals[report_num]) == 1) && (mpz_cmp_ui(dconf->Qvals[report_num], sconf->large_prime_max) < 0)) { uint32 large_prime[2]; large_prime[0] = (uint32)mpz_get_ui(dconf->Qvals[report_num]); //Q->val[0]; large_prime[1] = 1; //add this one if (sconf->is_tiny) { // we need to encode both the a_poly and b_poly index // in poly_id poly_id |= (sconf->total_poly_a << 16); buffer_relation(offset,large_prime,smooth_num+1, fb_offsets,poly_id,parity,dconf,polya_factors,it); } else buffer_relation(offset,large_prime,smooth_num+1, fb_offsets,poly_id,parity,dconf,polya_factors,it); #ifdef QS_TIMING gettimeofday (&qs_timing_stop, NULL); qs_timing_diff = my_difftime (&qs_timing_start, &qs_timing_stop); TF_STG6 += ((double)qs_timing_diff->secs + (double)qs_timing_diff->usecs / 1000000); free(qs_timing_diff); #endif return; } if (sconf->use_dlp == 0) return; //quick check if Q is way too big for DLP (more than 64 bits) if (mpz_sizeinbase(dconf->Qvals[report_num], 2) >= 64) return; q64 = mpz_get_64(dconf->Qvals[report_num]); if ((q64 > sconf->max_fb2) && (q64 < sconf->large_prime_max2)) { //quick prime check: compute 2^(residue-1) mod residue. uint64 res; //printf("%llu\n",q64); #if BITS_PER_DIGIT == 32 mpz_set_64(dconf->gmptmp1, q64); mpz_set_64(dconf->gmptmp2, 2); mpz_set_64(dconf->gmptmp3, q64-1); mpz_powm(dconf->gmptmp1, dconf->gmptmp2, dconf->gmptmp3, dconf->gmptmp1); res = mpz_get_64(dconf->gmptmp1); #else spModExp(2, q64 - 1, q64, &res); #endif //if equal to 1, assume it is prime. this may be wrong sometimes, but we don't care. //more important to quickly weed out probable primes than to spend more time to be //more sure. if (res == 1) { #ifdef QS_TIMING gettimeofday (&qs_timing_stop, NULL); qs_timing_diff = my_difftime (&qs_timing_start, &qs_timing_stop); TF_STG6 += ((double)qs_timing_diff->secs + (double)qs_timing_diff->usecs / 1000000); free(qs_timing_diff); #endif dconf->dlp_prp++; return; } //try to find a double large prime #ifdef HAVE_CUDA { uint32 large_prime[2] = {1,1}; // remember the residue and the relation it is associated with dconf->buf_id[dconf->num_squfof_cand] = dconf->buffered_rels; dconf->squfof_candidates[dconf->num_squfof_cand++] = q64; // buffer the relation buffer_relation(offset,large_prime,smooth_num+1, fb_offsets,poly_id,parity,dconf,polya_factors,it); } #else dconf->attempted_squfof++; mpz_set_64(dconf->gmptmp1, q64); f64 = sp_shanks_loop(dconf->gmptmp1, sconf->obj); if (f64 > 1 && f64 != q64) { uint32 large_prime[2]; large_prime[0] = (uint32)f64; large_prime[1] = (uint32)(q64 / f64); if (large_prime[0] < sconf->large_prime_max && large_prime[1] < sconf->large_prime_max) { //add this one dconf->dlp_useful++; buffer_relation(offset,large_prime,smooth_num+1, fb_offsets,poly_id,parity,dconf,polya_factors,it); } } else { dconf->failed_squfof++; //printf("squfof failure: %" PRIu64 "\n", q64); } #endif } else dconf->dlp_outside_range++; #ifdef QS_TIMING gettimeofday (&qs_timing_stop, NULL); qs_timing_diff = my_difftime (&qs_timing_start, &qs_timing_stop); TF_STG6 += ((double)qs_timing_diff->secs + (double)qs_timing_diff->usecs / 1000000); free(qs_timing_diff); #endif return; }