예제 #1
0
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);
}
예제 #2
0
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);
}
예제 #3
0
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));
}
예제 #4
0
// 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;

}
예제 #6
0
//----------------------- 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;
}
예제 #7
0
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;
}
예제 #8
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;
}
예제 #9
0
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;

}
예제 #10
0
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;
}
예제 #11
0
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;
}
예제 #12
0
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;
}
예제 #13
0
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;
}