Example #1
0
int checkBl(mpz_t n, uint32 *qli, fb_list *fb, mpz_t *Bl, int s)
{
	//check that Bl^2 == N mod ql and Bl == 0 mod qj for 1<=j<=s, j != l
	int i,j,p,q;
	mpz_t t1,t2;

	mpz_init(t1);
	mpz_init(t2);

	for (i=0;i<s;i++)
	{
		p = fb->list->prime[qli[i]];

		mpz_tdiv_q_2exp(t2, Bl[i], 1); //zShiftRight(&t2,&Bl[i],1);
		mpz_mul(t1, t2, t2); //zSqr(&t2,&t1);
		if (mpz_tdiv_ui(t1,p) % mpz_tdiv_ui(n,p) != 0)
			printf("%s^2 mod %u != N mod %u\n",mpz_conv2str(&gstr1.s, 10, Bl[i]),p,p);

		for (j=0;j<s;j++)
		{
			if (j==i)
				continue;

			q = fb->list->prime[qli[j]];
			mpz_tdiv_q_2exp(t2, Bl[i], 1); //zShiftRight(&t2,&Bl[i],1);
			if (mpz_tdiv_ui(t2,q) != 0)
				printf("%s mod %u != 0\n",mpz_conv2str(&gstr1.s, 10, Bl[i]),q);
		}
	}

	mpz_clear(t1);
	mpz_clear(t2);
	return 0;
}
Example #2
0
int checkpoly_siqs(siqs_poly *poly, mpz_t n)
{
	//check that b^2 == N mod a
	//and that c == (b*b - n)/a
	mpz_t t1,t2,t3,t4;

	mpz_init(t1);
	mpz_init(t2);
	mpz_init(t3);
	mpz_init(t4);

	mpz_set(t1, n);
	mpz_tdiv_r(t3, t1, poly->mpz_poly_a); //zDiv(&t1,&poly->poly_a,&t2,&t3);

	mpz_mul(t2, poly->mpz_poly_b, poly->mpz_poly_b); //zMul(&poly->poly_b,&poly->poly_b,&t2);
	mpz_tdiv_r(t4, t2, poly->mpz_poly_a); //zDiv(&t2,&poly->poly_a,&t1,&t4);

	if (mpz_cmp(t3,t4) != 0)
	{
		printf("\nError in checkpoly: %s^2 !== N mod %s\n", 
			mpz_conv2str(&gstr1.s, 10, poly->mpz_poly_b),
			mpz_conv2str(&gstr2.s, 10, poly->mpz_poly_a));
		if (mpz_sgn(poly->mpz_poly_b) < 0)
			printf("b is negative\n");
	}

	if (mpz_kronecker(n, poly->mpz_poly_a) != 1)
		printf("\nError in checkpoly: (a|N) != 1\n");

	mpz_mul(t2, poly->mpz_poly_b, poly->mpz_poly_b); //zMul(&poly->poly_b,&poly->poly_b,&t2);
	mpz_sub(t2, t2, n);
	mpz_tdiv_q(t4, t2, poly->mpz_poly_a); //zDiv(&t2,&poly->poly_a,&t1,&t4);

	if (mpz_cmp(t4,poly->mpz_poly_c) != 0)
		printf("\nError in checkpoly: c != (b^2 - n)/a\n");
	
	mpz_clear(t1);
	mpz_clear(t2);
	mpz_clear(t3);
	mpz_clear(t4);
	return 0;
}
Example #3
0
void brent_loop(fact_obj_t *fobj)
{
	//repeatedly use brent's rho on n
	//we always use three constants 'c'.
	//it may be desirable to make the number of different
	//polynomials, and their values, configurable, but for 
	//now it is hardcoded.
	mpz_t d,t;
	FILE *flog;
	clock_t start, stop;
	double tt;
		
	//check for trivial cases
	if ((mpz_cmp_ui(fobj->rho_obj.gmp_n, 1) == 0) || (mpz_cmp_ui(fobj->rho_obj.gmp_n, 0) == 0))
		return;

	if (mpz_cmp_ui(fobj->rho_obj.gmp_n, 2) == 0)
		return;

	//open the log file
	flog = fopen(fobj->flogname,"a");
	if (flog == NULL)
	{
		printf("fopen error: %s\n", strerror(errno));
		printf("could not open %s for writing\n",fobj->flogname);
		return;
	}

	//initialize some local args
	mpz_init(d);
	mpz_init(t);	

	fobj->rho_obj.curr_poly = 0;
	while(fobj->rho_obj.curr_poly < 3)
	{
		//for each different constant, first check primalty because each
		//time around the number may be different
		start = clock();
		if (mpz_probab_prime_p(fobj->rho_obj.gmp_n, NUM_WITNESSES))
		{
			logprint(flog,"prp%d = %s\n", gmp_base10(fobj->rho_obj.gmp_n),
				mpz_conv2str(&gstr1.s, 10, fobj->rho_obj.gmp_n));

			add_to_factor_list(fobj, fobj->rho_obj.gmp_n);
			stop = clock();
			tt = (double)(stop - start)/(double)CLOCKS_PER_SEC;

			mpz_set_ui(fobj->rho_obj.gmp_n, 1);
			break;
		}

		//verbose: print status to screen
		if (VFLAG >= 0)
			printf("rho: x^2 + %u, starting %d iterations on C%u ",
			fobj->rho_obj.polynomials[fobj->rho_obj.curr_poly], fobj->rho_obj.iterations, 
			(int)gmp_base10(fobj->rho_obj.gmp_n));

		logprint(flog, "rho: x^2 + %u, starting %d iterations on C%u\n",
			fobj->rho_obj.polynomials[fobj->rho_obj.curr_poly], fobj->rho_obj.iterations, 
			(int)gmp_base10(fobj->rho_obj.gmp_n));
		
		//call brent's rho algorithm, using montgomery arithmetic.
		mbrent(fobj);

		//check to see if 'f' is non-trivial
		if ((mpz_cmp_ui(fobj->rho_obj.gmp_f, 1) > 0)
			&& (mpz_cmp(fobj->rho_obj.gmp_f, fobj->rho_obj.gmp_n) < 0))
		{				
			//non-trivial factor found
			stop = clock();
			tt = (double)(stop - start)/(double)CLOCKS_PER_SEC;

			//check if the factor is prime
			if (mpz_probab_prime_p(fobj->rho_obj.gmp_f, NUM_WITNESSES))
			{
				add_to_factor_list(fobj, fobj->rho_obj.gmp_f);

				if (VFLAG > 0)
					gmp_printf("rho: found prp%d factor = %Zd\n",
					gmp_base10(fobj->rho_obj.gmp_f),fobj->rho_obj.gmp_f);

				logprint(flog,"prp%d = %s\n",
					gmp_base10(fobj->rho_obj.gmp_f),
					mpz_conv2str(&gstr1.s, 10, fobj->rho_obj.gmp_f));
			}
			else
			{
				add_to_factor_list(fobj, fobj->rho_obj.gmp_f);

				if (VFLAG > 0)
					gmp_printf("rho: found c%d factor = %Zd\n",
					gmp_base10(fobj->rho_obj.gmp_f),fobj->rho_obj.gmp_f);

				logprint(flog,"c%d = %s\n",
					gmp_base10(fobj->rho_obj.gmp_f),
					mpz_conv2str(&gstr1.s, 10, fobj->rho_obj.gmp_f));
			}
			start = clock();

			//reduce input
			mpz_tdiv_q(fobj->rho_obj.gmp_n, fobj->rho_obj.gmp_n, fobj->rho_obj.gmp_f);
			
		}
		else
		{
			//no factor found, log the effort we made.
			stop = clock();
			tt = (double)(stop - start)/(double)CLOCKS_PER_SEC;

			fobj->rho_obj.curr_poly++; //try a different function
		}
	}

	fobj->rho_obj.ttime = tt;
	fclose(flog);
	mpz_clear(d);
	mpz_clear(t);

	return;
}
Example #4
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;
}
Example #5
0
// top level routine: the only one visible to the rest of the program
void pollard_loop(fact_obj_t *fobj)
{
	//run pollard's p-1 algorithm once on the input, using a 
	//32 bit random base
	//expects the input in pm1_obj->gmp_n
	mpz_t d,t;
	FILE *flog;
	clock_t start, stop;
	double tt;
		
	//check for trivial cases
	if ((mpz_cmp_ui(fobj->pm1_obj.gmp_n, 1) == 0) || (mpz_cmp_ui(fobj->pm1_obj.gmp_n, 0) == 0))
		return;

	if (mpz_cmp_ui(fobj->pm1_obj.gmp_n, 2) == 0)
		return;
		
	start = clock();

	//open the log file
	flog = fopen(fobj->flogname,"a");
	if (flog == NULL)
	{
		printf("fopen error: %s\n", strerror(errno));
		printf("could not open %s for writing\n",fobj->flogname);
		return;
	}

	if (mpz_probab_prime_p(fobj->pm1_obj.gmp_n, NUM_WITNESSES))
	{
		logprint(flog,"prp%d = %s\n", gmp_base10(fobj->pm1_obj.gmp_n),
			mpz_conv2str(&gstr1.s, 10, fobj->pm1_obj.gmp_n));

		add_to_factor_list(fobj, fobj->pm1_obj.gmp_n);

		stop = clock();
		tt = (double)(stop - start)/(double)CLOCKS_PER_SEC;			
		mpz_set_ui(fobj->pm1_obj.gmp_n, 1);
		fclose(flog);
		return;
	}

	//initialize the flag to watch for interrupts, and set the
	//pointer to the function to call if we see a user interrupt
	PM1_ABORT = 0;
	signal(SIGINT,pm1exit);

	//initialize some local args
	mpz_init(d);
	mpz_init(t);	

	pm1_init(fobj);
		
	pm1_print_B1_B2(fobj,flog);
	pm1_wrapper(fobj);
		
	//check to see if 'f' is non-trivial
	if ((mpz_cmp_ui(fobj->pm1_obj.gmp_f, 1) > 0)
		&& (mpz_cmp(fobj->pm1_obj.gmp_f, fobj->pm1_obj.gmp_n) < 0))
	{				
		//non-trivial factor found
		stop = clock();
		tt = (double)(stop - start)/(double)CLOCKS_PER_SEC;
		//check if the factor is prime
		if (mpz_probab_prime_p(fobj->pm1_obj.gmp_f, NUM_WITNESSES))
		{
			add_to_factor_list(fobj, fobj->pm1_obj.gmp_f);

			if (VFLAG > 0)
				gmp_printf("pm1: found prp%d factor = %Zd\n",
				gmp_base10(fobj->pm1_obj.gmp_f), fobj->pm1_obj.gmp_f);

			logprint(flog,"prp%d = %s\n",
				gmp_base10(fobj->pm1_obj.gmp_f),
				mpz_conv2str(&gstr1.s, 10, fobj->pm1_obj.gmp_f));
		}
		else
		{
			add_to_factor_list(fobj, fobj->pm1_obj.gmp_f);

			if (VFLAG > 0)
				gmp_printf("pm1: found c%d factor = %Zd\n",
				gmp_base10(fobj->pm1_obj.gmp_f), fobj->pm1_obj.gmp_f);

			logprint(flog,"c%d = %s\n",
				gmp_base10(fobj->pm1_obj.gmp_f),
				mpz_conv2str(&gstr1.s, 10, fobj->pm1_obj.gmp_f));
		}
		start = clock();

		//reduce input
		mpz_tdiv_q(fobj->pm1_obj.gmp_n, fobj->pm1_obj.gmp_n, fobj->pm1_obj.gmp_f);
	}

	fclose(flog);

	pm1_finalize(fobj);

	//watch for an abort
	if (PM1_ABORT)
	{
		print_factors(fobj);
		exit(1);
	}

	signal(SIGINT,NULL);
	mpz_clear(d);
	mpz_clear(t);

	return;
}
Example #6
0
void factor_perfect_power(fact_obj_t *fobj, mpz_t b)
{
	// check if (b^1/i)^i == b for i = 2 to bitlen(b)
	uint32 bits = mpz_sizeinbase(b,2);
	uint32 i;
	FILE *flog;
	mpz_t base, ans;

	mpz_init(base);
	mpz_init(ans);

	//open the log file
	flog = fopen(fobj->flogname,"a");
	if (flog == NULL)
	{
		printf("fopen error: %s\n", strerror(errno));
		printf("could not open %s for writing\n",fobj->flogname);
		return;
	}

	for (i=2; i<bits; i++)
	{
		mpz_root(base, b, i);
		mpz_pow_ui(ans, base, i);
		if (mpz_cmp(ans, b) == 0)
		{
			// found a base.  				
			if (is_mpz_prp(base))
			{
				uint32 j;
				//gmp_printf("\nAdding prime base %Zd to factor list...\n", base);
				for (j=0; j<i; j++)
				{
					add_to_factor_list(fobj, base);
					mpz_tdiv_q(b, b, base);
					logprint(flog,"prp%d = %s\n",
						gmp_base10(base),
						mpz_conv2str(&gstr1.s, 10, base));
				}
			}
			else
			{
				// if composite, factor it and then multiply
				// all factors by i (the exponent).
				fact_obj_t *fobj_refactor;
				uint32 j;

				gmp_printf("\nFactoring composite base %Zd...\n", base);

				// load the new fobj with this number
				fobj_refactor = (fact_obj_t *)malloc(sizeof(fact_obj_t));
				init_factobj(fobj_refactor);
				mpz_set(fobj_refactor->N, base);

				// recurse on factor
				factor(fobj_refactor);

				// add all factors found during the refactorization
				for (j=0; j< fobj_refactor->num_factors; j++)
				{
					int k, c;
					//gmp_printf("\nAdding prime base %Zd to factor list...\n", 
					//	fobj_refactor->fobj_factors[j].factor);

					for (k=0; k < fobj_refactor->fobj_factors[j].count; k++)
					{
						// add i copies of it, since this was a perfect power
						for (c = 0; c < i; c++)
						{
							add_to_factor_list(fobj, fobj_refactor->fobj_factors[j].factor);
							mpz_tdiv_q(b, b, fobj_refactor->fobj_factors[j].factor);
							logprint(flog,"prp%d = %s\n",
								gmp_base10(fobj_refactor->fobj_factors[j].factor),
								mpz_conv2str(&gstr1.s, 10, fobj_refactor->fobj_factors[j].factor));
						}
					}
				}

				// free temps
				free_factobj(fobj_refactor);
				free(fobj_refactor);
			}
			break;
		}
	}

	mpz_clear(base);
	mpz_clear(ans);
	fclose(flog);

	return;
}
Example #7
0
void zFermat(uint64 limit, uint32 mult, fact_obj_t *fobj)
{
	// Fermat's factorization method with a sieve-based improvement
	// provided by 'neonsignal'
	mpz_t a, b2, tmp, multN, a2;
	int i;
	int numChars;
	uint64 reportIt, reportInc;
	uint64 count;
	uint64 i64;
	FILE *flog = NULL;
	uint32 M = 2 * 2 * 2 * 2 * 3 * 3 * 5 * 5 * 7 * 7; //176400u
	uint32 M1 = 11 * 17 * 23 * 31; //133331u
	uint32 M2 = 13 * 19 * 29 * 37; //265031u
	uint8 *sqr, *sqr1, *sqr2, *mod, *mod1, *mod2;
	uint16 *skip;
	uint32 m, mmn, s, d;
	uint8 masks[8] = {0xfe, 0xfd, 0xfb, 0xf7, 0xef, 0xdf, 0xbf, 0x7f};
	uint8 nmasks[8];
	uint32 iM = 0, iM1 = 0, iM2 = 0;

	if (mpz_even_p(fobj->div_obj.gmp_n))
	{
		mpz_init(tmp);
		mpz_set_ui(tmp, 2);
		mpz_tdiv_q_2exp(fobj->div_obj.gmp_n, fobj->div_obj.gmp_n, 1);
		add_to_factor_list(fobj, tmp);
		mpz_clear(tmp);
		return;
	}

	if (mpz_perfect_square_p(fobj->div_obj.gmp_n))
	{
		//open the log file
		flog = fopen(fobj->flogname,"a");
		if (flog == NULL)
		{
			printf("fopen error: %s\n", strerror(errno));
			printf("could not open %s for writing\n",fobj->flogname);
			return;
		}

		mpz_sqrt(fobj->div_obj.gmp_n, fobj->div_obj.gmp_n);
		if (is_mpz_prp(fobj->div_obj.gmp_n))
		{			
			logprint(flog, "Fermat method found perfect square factorization:\n");
			logprint(flog,"prp%d = %s\n",
				gmp_base10(fobj->div_obj.gmp_n),
				mpz_conv2str(&gstr1.s, 10, fobj->div_obj.gmp_n));
			logprint(flog,"prp%d = %s\n",
				gmp_base10(fobj->div_obj.gmp_n),
				mpz_conv2str(&gstr1.s, 10, fobj->div_obj.gmp_n));
		}
		else
		{
			logprint(flog, "Fermat method found perfect square factorization:\n");
			logprint(flog,"c%d = %s\n",
				gmp_base10(fobj->div_obj.gmp_n),
				mpz_conv2str(&gstr1.s, 10, fobj->div_obj.gmp_n));
			logprint(flog,"c%d = %s\n",
				gmp_base10(fobj->div_obj.gmp_n),
				mpz_conv2str(&gstr1.s, 10, fobj->div_obj.gmp_n));
		}
		add_to_factor_list(fobj, fobj->div_obj.gmp_n);
		add_to_factor_list(fobj, fobj->div_obj.gmp_n);
		mpz_set_ui(fobj->div_obj.gmp_n, 1);
		fclose(flog);
		return;
	}

	mpz_init(a);
	mpz_init(b2);
	mpz_init(tmp);
	mpz_init(multN);
	mpz_init(a2);

	// apply the user supplied multiplier
	mpz_mul_ui(multN, fobj->div_obj.gmp_n, mult);
	
	// compute ceil(sqrt(multN))
	mpz_sqrt(a, multN);

	// form b^2
	mpz_mul(b2, a, a);
	mpz_sub(b2, b2, multN);

	// test successive 'a' values using a sieve-based approach.
	// the idea is that not all 'a' values allow a^2 or b^2 to be square.  
	// we pre-compute allowable 'a' values modulo various smooth numbers and 
	// build tables to allow us to quickly iterate over 'a' values that are 
	// more likely to produce squares.
	// init sieve structures
	sqr = (uint8 *)calloc((M / 8 + 1) , sizeof(uint8));
	sqr1 = (uint8 *)calloc((M1 / 8 + 1) , sizeof(uint8));
	sqr2 = (uint8 *)calloc((M2 / 8 + 1) , sizeof(uint8));
	mod = (uint8 *)calloc((M / 8 + 1) , sizeof(uint8));
	mod1 = (uint8 *)calloc((M1 / 8 + 1) , sizeof(uint8));
	mod2 = (uint8 *)calloc((M2 / 8 + 1) , sizeof(uint8));
	skip = (uint16 *)malloc(M * sizeof(uint16));

	// test it.  This will be good enough if |u*p-v*q| < 2 * N^(1/4), where
	// mult = u*v
	count = 0;
	if (mpz_perfect_square_p(b2))
		goto found;

	for (i=0; i<8; i++)
		nmasks[i] = ~masks[i];

	// marks locations where squares can occur mod M, M1, M2
	for (i64 = 0; i64 < M; ++i64)
		setbit(sqr, (i64*i64)%M);

	for (i64 = 0; i64 < M1; ++i64)
		setbit(sqr1, (i64*i64)%M1);

	for (i64 = 0; i64 < M2; ++i64)
		setbit(sqr2, (i64*i64)%M2);

	// for the modular sequence of b*b = a*a - n values 
	// (where b2_2 = b2_1 * 2a + 1), mark locations where
	// b^2 can be a square
	m = mpz_mod_ui(tmp, a, M);
	mmn = mpz_mod_ui(tmp, b2, M);
	for (i = 0; i < M; ++i)
	{
		if (getbit(sqr, mmn)) setbit(mod, i);
		mmn = (mmn+m+m+1)%M;
		m = (m+1)%M;
	}

	// we only consider locations where the modular sequence mod M can
	// be square, so compute the distance to the next square location
	// at each possible value of i mod M.
	s = 0;
	d = 0;
	for (i = 0; !getbit(mod,i); ++i)
		++s;
	for (i = M; i > 0;)
	{
		--i;
		++s;
		skip[i] = s;
		if (s > d) d = s;
		if (getbit(mod,i)) s = 0;
	}
	//printf("maxSkip = %u\n", d);

	// for the modular sequence of b*b = a*a - n values 
	// (where b2_2 = b2_1 * 2a + 1), mark locations where the
	// modular sequence can be a square mod M1.  These will
	// generally differ from the sequence mod M.
	m = mpz_mod_ui(tmp, a, M1);
	mmn = mpz_mod_ui(tmp, b2, M1);
	for (i = 0; i < M1; ++i)
	{
		if (getbit(sqr1, mmn)) setbit(mod1, i);
		mmn = (mmn+m+m+1)%M1;
		m = (m+1)%M1;
	}

	// for the modular sequence of b*b = a*a - n values 
	// (where b2_2 = b2_1 * 2a + 1), mark locations where the
	// modular sequence can be a square mod M2.  These will
	// generally differ from the sequence mod M or M1.
	m = mpz_mod_ui(tmp, a, M2);
	mmn = mpz_mod_ui(tmp, b2, M2);
	for (i = 0; i < M2; ++i)
	{
		if (getbit(sqr2, mmn)) setbit(mod2, i);
		mmn = (mmn+m+m+1)%M2;
		m = (m+1)%M2;
	}

	// loop, checking for perfect squares
	mpz_mul_2exp(a2, a, 1);
	count = 0;
	numChars = 0;
	reportIt = limit / 100;
	reportInc = reportIt;
	do
	{
		d = 0;
		i64 = 0;
		do
		{
			// skip to the next possible square residue of b*b mod M
			s = skip[iM];

			// remember how far we skipped
			d += s;

			// update the other residue indices
			if ((iM1 += s) >= M1) iM1 -= M1;
			if ((iM2 += s) >= M2) iM2 -= M2;
			if ((iM += s) >= M) iM -= M;

			// some multpliers can lead to infinite loops.  bail out 
			// if so.
			if (++i64 > M) goto done;

			// continue if either of the other residues indicates
			// non-square.
		} while (!getbit(mod1,iM1) || !getbit(mod2,iM2));

		// form b^2 by incrementing by many factors of 2*a+1
		mpz_add_ui(tmp, a2, d);
		mpz_mul_ui(tmp, tmp, d);
		mpz_add(b2, b2, tmp);

		// accumulate so that we can reset d 
		// (and thus keep it single precision)
		mpz_add_ui(a2, a2, d*2);

		count += d;
		if (count > limit)
			break;

		//progress report
		if ((count > reportIt) && (VFLAG > 1))
		{
			for (i=0; i< numChars; i++)
				printf("\b");
			numChars = printf("%" PRIu64 "%%",(uint64)((double)count / (double)limit * 100));
			fflush(stdout);
			reportIt += reportInc;
		}
	} while (!mpz_perfect_square_p(b2));


found:

	// 'count' is how far we had to scan 'a' to find a square b
	mpz_add_ui(a, a, count);
	//printf("count is %" PRIu64 "\n", count);

	if ((mpz_size(b2) > 0) && mpz_perfect_square_p(b2))
	{
		//printf("found square at count = %d: a = %s, b2 = %s",count,
		//	z2decstr(&a,&gstr1),z2decstr(&b2,&gstr2));
		mpz_sqrt(tmp, b2); 		
		mpz_add(tmp, a, tmp);
		mpz_gcd(tmp, fobj->div_obj.gmp_n, tmp);

		flog = fopen(fobj->flogname,"a");
		if (flog == NULL)
		{
			printf("fopen error: %s\n", strerror(errno));
			printf("could not open %s for writing\n",fobj->flogname);
			goto done;
		}
		logprint(flog, "Fermat method found factors:\n");

		add_to_factor_list(fobj, tmp);
		if (is_mpz_prp(tmp))
		{			
			logprint(flog,"prp%d = %s\n",
				gmp_base10(tmp),
				mpz_conv2str(&gstr1.s, 10, tmp));
		}
		else
		{
			logprint(flog,"c%d = %s\n",
				gmp_base10(tmp),
				mpz_conv2str(&gstr1.s, 10, tmp));
		}

		mpz_tdiv_q(fobj->div_obj.gmp_n, fobj->div_obj.gmp_n, tmp);
		mpz_sqrt(tmp, b2);
		mpz_sub(tmp, a, tmp);
		mpz_gcd(tmp, fobj->div_obj.gmp_n, tmp);

		add_to_factor_list(fobj, tmp);
		if (is_mpz_prp(tmp))
		{			
			logprint(flog,"prp%d = %s\n",
				gmp_base10(tmp),
				mpz_conv2str(&gstr1.s, 10, tmp));
		}
		else
		{
			logprint(flog,"c%d = %s\n",
				gmp_base10(tmp),
				mpz_conv2str(&gstr1.s, 10, tmp));
		}

		mpz_tdiv_q(fobj->div_obj.gmp_n, fobj->div_obj.gmp_n, tmp);
	}

done:
	mpz_clear(tmp);
	mpz_clear(a);
	mpz_clear(b2);
	mpz_clear(multN);
	mpz_clear(a2);
	free(sqr);
	free(sqr1);
	free(sqr2);
	free(mod);
	free(mod1);
	free(mod2);
	free(skip);
	if (flog != NULL)
		fclose(flog);
	return;

}
Example #8
0
void williams_loop(fact_obj_t *fobj)
{
    //use william's p+1 algorithm 'trials' times on n.
    //we allow multiple trials since we may not always get a p+1 group
    //with our random choice of base
    //expects the input in pp1_obj->gmp_n
    mpz_t d,t;
    int i,it,trials = fobj->pp1_obj.numbases;
    FILE *flog;
    clock_t start, stop;
    double tt;

    //check for trivial cases
    if ((mpz_cmp_ui(fobj->pp1_obj.gmp_n, 1) == 0) || (mpz_cmp_ui(fobj->pp1_obj.gmp_n, 0) == 0))
        return;

    if (mpz_cmp_ui(fobj->pp1_obj.gmp_n, 2) == 0)
        return;

    //open the log file
    flog = fopen(fobj->flogname,"a");
    if (flog == NULL)
    {
        printf("fopen error: %s\n", strerror(errno));
        printf("could not open %s for appending\n",fobj->flogname);
        return;
    }

    //initialize the flag to watch for interrupts, and set the
    //pointer to the function to call if we see a user interrupt
    PP1_ABORT = 0;
    signal(SIGINT,pp1exit);

    //initialize some local args
    mpz_init(d);
    mpz_init(t);

    pp1_init(fobj);

    i=0;
    while (i < trials)
    {
        //watch for an abort
        if (PP1_ABORT)
        {
            print_factors(fobj);
            exit(1);
        }

        start = clock();
        if (is_mpz_prp(fobj->pp1_obj.gmp_n))
        {
            logprint(flog,"prp%d = %s\n", gmp_base10(fobj->pp1_obj.gmp_n),
                     mpz_conv2str(&gstr1.s, 10, fobj->pp1_obj.gmp_n));

            add_to_factor_list(fobj, fobj->pp1_obj.gmp_n);

            stop = clock();
            tt = (double)(stop - start)/(double)CLOCKS_PER_SEC;
            mpz_set_ui(fobj->pp1_obj.gmp_n, 1);
            break;
        }

        fobj->pp1_obj.base = spRand(3,MAX_DIGIT);

        pp1_print_B1_B2(fobj,flog);

        it = pp1_wrapper(fobj);

        //check to see if 'f' is non-trivial
        if ((mpz_cmp_ui(fobj->pp1_obj.gmp_f, 1) > 0)
                && (mpz_cmp(fobj->pp1_obj.gmp_f, fobj->pp1_obj.gmp_n) < 0))
        {
            //non-trivial factor found
            stop = clock();
            tt = (double)(stop - start)/(double)CLOCKS_PER_SEC;

            //check if the factor is prime
            if (is_mpz_prp(fobj->pp1_obj.gmp_f))
            {
                add_to_factor_list(fobj, fobj->pp1_obj.gmp_f);

                if (VFLAG > 0)
                    gmp_printf("pp1: found prp%d factor = %Zd\n",
                               gmp_base10(fobj->pp1_obj.gmp_f),fobj->pp1_obj.gmp_f);

                logprint(flog,"prp%d = %s\n",
                         gmp_base10(fobj->pp1_obj.gmp_f),
                         mpz_conv2str(&gstr1.s, 10, fobj->pp1_obj.gmp_f));
            }
            else
            {
                add_to_factor_list(fobj, fobj->pp1_obj.gmp_f);

                if (VFLAG > 0)
                    gmp_printf("pp1: found c%d factor = %Zd\n",
                               gmp_base10(fobj->pp1_obj.gmp_f),fobj->pp1_obj.gmp_f);

                logprint(flog,"c%d = %s\n",
                         gmp_base10(fobj->pp1_obj.gmp_f),
                         mpz_conv2str(&gstr1.s, 10, fobj->pp1_obj.gmp_f));
            }
            start = clock();

            //reduce input
            mpz_tdiv_q(fobj->pp1_obj.gmp_n, fobj->pp1_obj.gmp_n, fobj->pp1_obj.gmp_f);

            i++;
            break;
        }

        i++;
    }

    fclose(flog);

    pp1_finalize(fobj);
    signal(SIGINT,NULL);
    mpz_clear(d);
    mpz_clear(t);

    return;
}
Example #9
0
int check_specialcase(FILE *sieve_log, fact_obj_t *fobj)
{
	//check for some special cases of input number
	//sieve_log is passed in already open, and should return open
	if (mpz_even_p(fobj->qs_obj.gmp_n))
	{
		printf("input must be odd\n");
		return 1;
	}

	if (mpz_probab_prime_p(fobj->qs_obj.gmp_n, NUM_WITNESSES))
	{
		add_to_factor_list(fobj, fobj->qs_obj.gmp_n);
		if (sieve_log != NULL)
			logprint(sieve_log,"prp%d = %s\n", gmp_base10(fobj->qs_obj.gmp_n), 
			mpz_conv2str(&gstr1.s, 10, fobj->qs_obj.gmp_n));
		mpz_set_ui(fobj->qs_obj.gmp_n,1);
		return 1;
	}

	if (mpz_perfect_square_p(fobj->qs_obj.gmp_n))
	{
		mpz_sqrt(fobj->qs_obj.gmp_n,fobj->qs_obj.gmp_n);

		add_to_factor_list(fobj, fobj->qs_obj.gmp_n);
		if (sieve_log != NULL)
			logprint(sieve_log,"prp%d = %s\n",gmp_base10(fobj->qs_obj.gmp_n), 
			mpz_conv2str(&gstr1.s, 10, fobj->qs_obj.gmp_n));
		add_to_factor_list(fobj, fobj->qs_obj.gmp_n);
		if (sieve_log != NULL)
			logprint(sieve_log,"prp%d = %s\n",gmp_base10(fobj->qs_obj.gmp_n),
			mpz_conv2str(&gstr1.s, 10, fobj->qs_obj.gmp_n));

		mpz_set_ui(fobj->qs_obj.gmp_n,1);
		return 1;
	}

	if (mpz_perfect_power_p(fobj->qs_obj.gmp_n))
	{
		if (VFLAG > 0)
			printf("input is a perfect power\n");
		
		factor_perfect_power(fobj, fobj->qs_obj.gmp_n);

		if (sieve_log != NULL)
		{
			uint32 j;
			logprint(sieve_log,"input is a perfect power\n");

			for (j=0; j<fobj->num_factors; j++)
			{
				uint32 k;
				for (k=0; k<fobj->fobj_factors[j].count; k++)
				{
					logprint(sieve_log,"prp%d = %s\n",gmp_base10(fobj->fobj_factors[j].factor), 
						mpz_conv2str(&gstr1.s, 10, fobj->fobj_factors[j].factor));
				}
			}
		}
		return 1;
	}

	if (mpz_sizeinbase(fobj->qs_obj.gmp_n,2) < 115)
	{
		//run MPQS, as SIQS doesn't work for smaller inputs
		//MPQS will take over the log file, so close it now.
		int i;

		// we've verified that the input is not odd or prime.  also
		// do some very quick trial division before calling smallmpqs, which
		// does none of these things.
		for (i=1; i<25; i++)
		{
			if (mpz_tdiv_ui(fobj->qs_obj.gmp_n, spSOEprimes[i]) == 0)
				mpz_tdiv_q_ui(fobj->qs_obj.gmp_n, fobj->qs_obj.gmp_n, spSOEprimes[i]);
		}

		smallmpqs(fobj);
		return 1;	//tells SIQS to not try to close the logfile
	}

	if (gmp_base10(fobj->qs_obj.gmp_n) > 140)
	{
		printf("input too big for SIQS\n");
		return 1;
	}

	return 0;
}
Example #10
0
void extract_factors(factor_list_t *factor_list, fact_obj_t *fobj)
{
	int i;
	FILE *logfile;
	char c[4];

	// extract the factors
	for (i=0;i<factor_list->num_factors;i++)
	{
		mpz_t tmp;

		//init locals
		mpz_init(tmp);
		
		//convert the factor
		mp_t2gmp(&factor_list->final_factors[i]->factor,tmp);

		//divide it out
		mpz_tdiv_q(fobj->nfs_obj.gmp_n, fobj->nfs_obj.gmp_n, tmp);

		//check if its prime and log accordingly
		if (is_mpz_prp(tmp))
		{
			//need to convert to yafu bigint to store
			add_to_factor_list(fobj, tmp);
			strncpy(c,"prp",4);
		}
		else
		{
			add_to_factor_list(fobj, tmp);
			strncpy(c,"C",2);
		}

		logfile = fopen(fobj->flogname, "a");
		if (logfile == NULL)
		{
			printf("fopen error: %s\n", strerror(errno));
			printf("could not open yafu logfile for appending\n");
		}
		else
		{
			logprint(logfile, "%s%d = %s\n",c,
				gmp_base10(tmp), mpz_conv2str(&gstr1.s, 10, tmp));
			fclose(logfile);
		}		

		//free locals
		mpz_clear(tmp);
	}

	//log anything left over
	if (mpz_cmp_ui(fobj->nfs_obj.gmp_n, 1) > 0) 
	{
		char c[4];

		if (is_mpz_prp(fobj->nfs_obj.gmp_n))
		{
			add_to_factor_list(fobj, fobj->nfs_obj.gmp_n);
			strncpy(c,"prp",4);			
		}
		else
		{
			add_to_factor_list(fobj, fobj->nfs_obj.gmp_n);
			strncpy(c,"C",2);
		}
		
		logfile = fopen(fobj->flogname, "a");
		if (logfile == NULL)
		{
			printf("fopen error: %s\n", strerror(errno));
			printf("could not open yafu logfile for appending\n");
		}
		else
		{
			logprint(logfile, "%s%d = %s\n",c,
				gmp_base10(fobj->nfs_obj.gmp_n), 
				mpz_conv2str(&gstr1.s, 10, fobj->nfs_obj.gmp_n));
			fclose(logfile);
		}		

		mpz_set_ui(fobj->nfs_obj.gmp_n, 1);
	}

	return;
}