Пример #1
0
int main(void)
{
    int i, num_factors;
    mpz_t n, d, tmp, x_1, x_2;
    mpz_init(n);
    mpz_init(d);
    mpz_init(tmp);
    mpz_init(x_1);
    mpz_init(x_2);
    mpz_init(cp);

    srand(1337);

    mpz_t *factors = malloc(sizeof(mpz_t) * MAX_FACTORS);

    for(i = 0; i < MAX_FACTORS; ++i) {
        mpz_init(factors[i]);
    }

    for (i = 0; i < NUM_INPUT; ++i) {
        mpz_inp_str(n, stdin, 10);
        num_factors = factor(x_1, x_2, d, n, tmp, factors);
        print_factors(factors, num_factors);
    }

    return 0;
}
Пример #2
0
int
main ()
{
  int argc;
  char **argv;
  int fail = 0;
  char *fake_argv[3];
  argv = fake_argv;

  argv[0] = "factor";
  /*argv[1] = "81064801949712479";*/
  argv[1] = "324259213033341373";
  argv[2] = 0;
  argc = 2;

  program_name = argv[0];

  {
    int i;
      for (i = 1; i < argc; i++)
	fail |= print_factors (argv[i]);
  }

  return fail;
}
Пример #3
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;
}
Пример #4
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;
}
Пример #5
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;
}
Пример #6
0
int main(void) {
    printf("The factors of %llu are:\n",N);
    print_factors(N);
    return 0;
}