Пример #1
0
/*------------------------------------------------------------------*/
uint32 add_free_relations(msieve_obj *obj, 
			factor_base_t *fb, uint8 *free_bits) {

	uint32 i, j;
	uint32 num_relations = 0;
	uint32 alg_degree = fb->afb.poly.degree;
	uint32 rat_degree = fb->rfb.poly.degree;
	uint32 free_bytes = (FREE_RELATION_LIMIT / 2 + 7) / 8;

	savefile_open(&obj->savefile, SAVEFILE_APPEND);

	for (i = 0; i < free_bytes; i++) {

		if (free_bits[i] == 0)
			continue;

		for (j = 0; j < 8; j++) {

			char buf[LINE_BUF_SIZE];
			uint32 dummy_roots[MAX_POLY_DEGREE];
			uint32 high_coeff;
			uint32 num_roots;
			uint32 p;

			if (!(free_bits[i] & (1 << j)))
				continue;

			/* bit 8*i+j could be a new free relation */

			p = 2 * (8 * i + j) + 1;
			num_roots = poly_get_zeros(dummy_roots, 
						&fb->afb.poly,
						p, &high_coeff, 1);

			if (num_roots == alg_degree && high_coeff != 0) {

				num_roots = poly_get_zeros(dummy_roots, 
							&fb->rfb.poly,
							p, &high_coeff, 1);

				if (num_roots == rat_degree && 
						high_coeff != 0) {
					sprintf(buf, "%u,0:\n", p);
					savefile_write_line(&obj->savefile, 
								buf);
					num_relations++;
				}
			}
		}
	}

	if (num_relations)
		logprintf(obj, "added %u free relations\n", num_relations);
	savefile_flush(&obj->savefile);
	savefile_close(&obj->savefile);
	return num_relations;
}
Пример #2
0
// SGL : セーブイメージを読み込む (T.Yui)
int isfcmd_6f(SCR_OPE *op) {

	SINT32		savenum;
	SINT32		num;
	POINT_T		pt;
	VRAMHDL		dst;
	SAVEHDL		sh;
	_SAVEINF	inf;
	BOOL		r;

	if ((scr_getval(op, &savenum) != SUCCESS) ||
		(scr_getval(op, &num) != SUCCESS) ||
		(scr_getpt(op, &pt) != SUCCESS)) {
		return(GAMEEV_WRONGLENG);
	}
	if ((num < 0) || (num >= GAMECORE_MAXVRAM)) {
		goto cmd6f_exit;
	}
	dst = gamecore.vram[num];
	if (dst == NULL) {
		goto cmd6f_exit;
	}

	sh = savefile_open(FALSE);
	r = sh->readinf(sh, savenum, &inf, -1, -1);
	sh->close(sh);
	if (r == SUCCESS) {
#ifdef SIZE_QVGA
		vramdraw_halfpoint(&pt);
#endif
		vramcpy_cpy(dst, (VRAMHDL)inf.preview, &pt, NULL);
		vram_destroy((VRAMHDL)inf.preview);
	}

cmd6f_exit:
	return(GAMEEV_SUCCESS);
}
Пример #3
0
/*------------------------------------------------------------------*/
static uint32 nfs_init_savefile(msieve_obj *obj, mp_t *n) {

	char buf[LINE_BUF_SIZE];
	uint32 relations_found = 0;
	savefile_t *savefile = &obj->savefile;
	uint32 update = 1;

	/* open the savefile; if the file already
	   exists and the first line contains n,
	   then we are restarting from a previous factorization */

	if (savefile_exists(savefile)) {
		savefile_open(savefile, SAVEFILE_READ);
		buf[0] = 0;
		savefile_read_line(buf, sizeof(buf), savefile);
		if (buf[0] == 'N') {
			mp_t read_n;
			mp_str2mp(buf + 2, &read_n, 10);
			if (mp_cmp(n, &read_n) == 0)
				update = 0;
		}
		savefile_close(savefile);
	}

	if (update && (obj->flags & MSIEVE_FLAG_NFS_SIEVE)) {
		/* If sieving is about to add new relations, truncate 
		   the file and write the present n. I hope you backed 
		   up savefiles you wanted! */

		savefile_open(savefile, SAVEFILE_WRITE);
		sprintf(buf, "N %s\n", mp_sprintf(n, 10, obj->mp_sprintf_buf));
		savefile_write_line(savefile, buf);
		savefile_flush(savefile);
		savefile_close(savefile);
	}
	else {
		/* we don't care how many relations are present,
		   so don't waste time counting them */
		return 0;
	}


	/* count the number of relations in the savefile;
	   do not verify any of them */

	savefile_open(savefile, SAVEFILE_READ);

	while (!savefile_eof(savefile)) {

		/* count relations; No checking of relations 
		   happens here */

		savefile_read_line(buf, sizeof(buf), savefile);

		while (!savefile_eof(savefile)) {
			if (isdigit(buf[0]) || buf[0] == '-')
				relations_found++;
			savefile_read_line(buf, sizeof(buf), savefile);
		}

		if (relations_found)
			logprintf(obj, "restarting with %u relations\n",
							relations_found);
	}
	savefile_close(savefile);
	return relations_found;
}
Пример #4
0
/*--------------------------------------------------------------------*/
uint32 factor_gnfs(msieve_obj *obj, mp_t *n,
			factor_list_t *factor_list) {

	int32 status;
	uint32 bits;
	sieve_param_t params;
	mp_poly_t rat_poly;
	mp_poly_t alg_poly;
	uint32 relations_found = 0;
	uint32 max_relations = 0;
	uint32 factor_found = 0;

	/* Calculate the factor base bound */

	bits = mp_bits(n);
	get_sieve_params(bits, &params);

	logprintf(obj, "commencing number field sieve (%d-digit input)\n",
			strlen(mp_sprintf(n, 10, obj->mp_sprintf_buf)));

	/* generate or read in the NFS polynomials */

	memset(&rat_poly, 0, sizeof(rat_poly));
	memset(&alg_poly, 0, sizeof(alg_poly));
	status = read_poly(obj, n, &rat_poly, &alg_poly, &params.skewness);
	if (status != 0 && 
	   (obj->flags & (MSIEVE_FLAG_NFS_POLY1 | 
			  MSIEVE_FLAG_NFS_POLY2))) {
		status = find_poly(obj, n);
		status = read_poly(obj, n, &rat_poly, 
					&alg_poly, &params.skewness);
	}
	if (status != 0) {
		printf("error generating or reading NFS polynomials\n");
		return 0;
	}
	analyze_one_poly(obj, &rat_poly, &alg_poly, params.skewness);

	if ((obj->flags & MSIEVE_FLAG_STOP_SIEVING) ||
	    !(obj->flags & (MSIEVE_FLAG_NFS_SIEVE |
	    		    MSIEVE_FLAG_NFS_FILTER |
			    MSIEVE_FLAG_NFS_LA |
			    MSIEVE_FLAG_NFS_SQRT))) {
		return 0;
	}

	/* if we're supposed to be sieving, 
	   initialize the savefile */

	if (obj->flags & (MSIEVE_FLAG_NFS_SIEVE |
			  MSIEVE_FLAG_NFS_FILTER)) {

		/* figure out how many relations to look for, and 
		   quit early if that many have already been found */

		relations_found = nfs_init_savefile(obj, n);
		if (obj->max_relations > 0) {
			max_relations = relations_found + 
						obj->max_relations;
		}
		else {
			/* if no guidance on this is available, make a
			   wild guess: a fixed fraction of the total number 
			   of large primes possible */

			max_relations = 0.8 * (params.rfb_lp_size /
					(log((double)params.rfb_lp_size) - 1) +
					params.afb_lp_size /
					(log((double)params.afb_lp_size) - 1));
		}
	}

	/* this is a little tricky: perform only sieving (and
	   quit when enough relations are found), only filtering
	   (and quit if it fails, or continue the postprocessing
	   if it succeeds), or alternate between sieving and
	   filtering until the filtering succeeds */

	while (1) {
		if (!(obj->flags & (MSIEVE_FLAG_NFS_SIEVE |
				    MSIEVE_FLAG_NFS_FILTER))) {
			break;
		}

		if (obj->flags & MSIEVE_FLAG_NFS_SIEVE) {
			savefile_open(&obj->savefile, SAVEFILE_APPEND);
			relations_found = do_line_sieving(obj, &params, n, 
							relations_found,
							max_relations);
			savefile_close(&obj->savefile);
			if (relations_found == 0)
				break;
			if (!(obj->flags & MSIEVE_FLAG_NFS_FILTER))
				return 0;
		}

		if (obj->flags & MSIEVE_FLAG_STOP_SIEVING)
			return 0;

		if (obj->flags & MSIEVE_FLAG_NFS_FILTER) {

			max_relations = nfs_filter_relations(obj, n);
			if (max_relations == 0)
				break;
			logprintf(obj, "filtering wants %u more relations\n",
							max_relations);
			if (!(obj->flags & MSIEVE_FLAG_NFS_SIEVE))
				return 0;
			max_relations += relations_found;
		}
	}

	if (obj->flags & MSIEVE_FLAG_NFS_LA)
		nfs_solve_linear_system(obj, n);
		
	if (obj->flags & MSIEVE_FLAG_NFS_SQRT)
		factor_found = nfs_find_factors(obj, n, factor_list);

	return factor_found;
}
Пример #5
0
void qs_filter_relations(sieve_conf_t *conf) {

	/* Perform all of the postprocessing on the list
	   of relations from the sieving phase. There are
	   two main jobs, reading in all the relations that
	   will be used and then determining the list of 
	   cycles in which partial relations appear. Care
	   should be taken to avoid wasting huge amounts of
	   memory */

	msieve_obj *obj = conf->obj;
	uint32 *hashtable = conf->cycle_hashtable;
	cycle_t *table = conf->cycle_table;
	uint32 num_poly_factors = conf->num_poly_factors;
	uint32 num_derived_poly = 1 << (num_poly_factors - 1);
	uint32 *final_poly_index;
	uint32 num_relations, num_cycles, num_poly;
	la_col_t *cycle_list;
	relation_t *relation_list;

	uint32 i, passes, start;
	uint32 curr_a_idx, curr_poly_idx, curr_rel; 
	uint32 curr_expected, curr_saved, curr_cycle; 
	uint32 total_poly_a;
	uint32 poly_saved;
	uint32 cycle_bins[NUM_CYCLE_BINS+1] = {0};
	char buf[LINE_BUF_SIZE];

 	/* Rather than reading all the relations in and 
	   then removing singletons, read only the large 
	   primes of each relation into an initial list,
	   remove the singletons, and then only read in
	   the relations that survive. This avoids reading
	   in useless relations (and usually the polynomials 
	   they would need) */

	savefile_open(&obj->savefile, SAVEFILE_READ);

	relation_list = (relation_t *)xmalloc(10000 * sizeof(relation_t));
	curr_rel = 10000;
	i = 0;
	total_poly_a = 0;
	/* skip over the first line */
	savefile_read_line(buf, sizeof(buf), &obj->savefile);

	while (!savefile_eof(&obj->savefile)) {
		char *start;

		switch (buf[0]) {
		case 'A':
			total_poly_a++;
			break;

		case 'R':
			start = strchr(buf, 'L');
			if (start != NULL) {
				uint32 prime1, prime2;
				read_large_primes(start, &prime1, &prime2);
				if (i == curr_rel) {
					curr_rel = 3 * curr_rel / 2;
					relation_list = (relation_t *)xrealloc(
							relation_list,
							curr_rel *
							sizeof(relation_t));
				}
				relation_list[i].poly_idx = i;
				relation_list[i].large_prime[0] = prime1;
				relation_list[i].large_prime[1] = prime2;
				i++;
			}
			break;
		}

		savefile_read_line(buf, sizeof(buf), &obj->savefile);
	}
	num_relations = i;
	num_relations = purge_singletons(obj, relation_list, num_relations,
					table, hashtable);
	relation_list = (relation_t *)xrealloc(relation_list, num_relations * 
							sizeof(relation_t));

	/* Now we know how many relations to expect. Also
	   initialize the lists of polynomial 'a' and 'b' values */

	num_poly = 10000;
	conf->poly_list = (poly_t *)xmalloc(num_poly * sizeof(poly_t));
	conf->poly_a_list = (mp_t *)xmalloc(total_poly_a * sizeof(mp_t));
	final_poly_index = (uint32 *)xmalloc(num_derived_poly * 
						sizeof(uint32));
	
	/* initialize the running counts of relations and
	   polynomials */

	i = 0;
	curr_expected = 0;
	curr_saved = 0;
	curr_rel = (uint32)(-1);
	curr_poly_idx = (uint32)(-1);
	curr_a_idx = (uint32)(-1);
	poly_saved = 0;
	logprintf(obj, "attempting to read %u relations\n", num_relations);

	/* Read in the relations and the polynomials they use
	   at the same time. */

	savefile_rewind(&obj->savefile);

	while (curr_expected < num_relations) {
		
		char *tmp;
		relation_t *r;

		/* read in the next entity */

		if (savefile_eof(&obj->savefile))
			break;
		savefile_read_line(buf, sizeof(buf), &obj->savefile);

		switch (buf[0]) {
		case 'A':
			/* Read in a new 'a' value */

			curr_a_idx++;
			read_poly_a(conf, buf);
			mp_copy(&conf->curr_a, conf->poly_a_list+curr_a_idx);

			/* build all of the 'b' values associated with it */

			build_derived_poly(conf);

			/* all 'b' values start off unused */

			memset(final_poly_index, -1, num_derived_poly *
							sizeof(uint32));
			break;

		case 'R':
			/* handle a new relation. First find the 
			   large primes; these will determine
	     		   if a relation is full or partial */

			tmp = strchr(buf, 'L');
			if (tmp == NULL)
				break;

			/* Check if this relation is needed. If it
			   survived singleton removal then its 
			   ordinal ID will be in the next entry 
			   of relation_list. 
		   
			   First move up the index of relation_list 
			   until the relation index to check is >= 
			   the one we have (it may have gotten behind 
			   because relations were corrupted) */

			curr_rel++;
			while (curr_expected < num_relations &&
				relation_list[curr_expected].poly_idx <
						curr_rel) {
				curr_expected++;
			}

			/* now check if the relation should be saved */

			if (curr_expected >= num_relations ||
			    relation_list[curr_expected].poly_idx != curr_rel)
				break;

			curr_expected++;

			/* convert the ASCII text of the relation to a
			   relation_t, verifying correctness in the process */

			r = relation_list + curr_saved;
			if (read_relation(conf, buf, r) != 0) {
				logprintf(obj, "failed to read relation %d\n", 
							curr_expected - 1);
				break;
			}

			curr_saved++;

			/* if necessary, save the b value corresponding 
			   to this relation */

			if (final_poly_index[r->poly_idx] == (uint32)(-1)) {
				if (i == num_poly) {
					num_poly *= 2;
					conf->poly_list = (poly_t *)xrealloc(
							conf->poly_list,
							num_poly *
							sizeof(poly_t));
				}
				conf->poly_list[i].a_idx = curr_a_idx;
				signed_mp_copy(&(conf->curr_b[r->poly_idx]), 
					&(conf->poly_list[i].b));
				final_poly_index[r->poly_idx] = i;
				r->poly_idx = i++;
			}
			else {
				r->poly_idx = final_poly_index[r->poly_idx];
			}

			break;  /* done with this relation */
		}
	}

	/* update the structures with the counts of relations
	   and polynomials actually recovered */

	num_relations = curr_saved;
	logprintf(obj, "recovered %u relations\n", num_relations);
	logprintf(obj, "recovered %u polynomials\n", i);
	savefile_close(&obj->savefile);
	free(final_poly_index);
	conf->poly_list = (poly_t *)xrealloc(conf->poly_list,
					   i * sizeof(poly_t));

	/* begin the cycle generation process by purging
	   duplicate relations. For the sake of consistency, 
	   always rebuild the graph afterwards */

	num_relations = purge_duplicate_relations(obj, 
				relation_list, num_relations);

	memset(hashtable, 0, sizeof(uint32) << LOG2_CYCLE_HASH);
	conf->vertices = 0;
	conf->components = 0;
	conf->cycle_table_size = 1;

	for (i = 0; i < num_relations; i++) {
		relation_t *r = relation_list + i;
		if (r->large_prime[0] != r->large_prime[1]) {
			add_to_cycles(conf, r->large_prime[0], 
					r->large_prime[1]);
		}
	}
	
	/* compute the number of cycles to expect. Note that
	   this number includes cycles from both full and partial
	   relations (the cycle for a full relation is trivial) */

	num_cycles = num_relations + conf->components - conf->vertices;

	/* The idea behind the cycle-finding code is this: the 
	   graph is composed of a bunch of connected components, 
	   and each component contains one or more cycles. To 
	   find the cycles, you build the 'spanning tree' for 
	   each component.

	   Think of the spanning tree as a binary tree; there are
	   no cycles in it because leaves are only connected to a
	   common root and not to each other. Any time you connect 
	   together two leaves of the tree, though, a cycle is formed.
	   So, for a spanning tree like this:

	         1
	         o
		/ \
	    2  o   o  3
	      / \   \
	     o   o   o
	     4   5   6

	   if you connect leaves 4 and 5 you get a cycle (4-2-5). If
	   you connect leaves 4 and 6 you get another cycle (4-2-1-3-6)
	   that will reuse two of the nodes in the first cycle. It's
	   this reuse that makes double large primes so powerful.

	   For our purposes, every edge in the tree above represents
	   a partial relation. Every edge that would create a cycle
	   comes from another partial relation. So to find all the cycles,
	   you begin with the roots of all of the connected components,
	   and then iterate through the list of partial relations until 
	   all have been 'processed'. A partial relation is considered 
	   processed when one or both of its primes is in the tree. If 
	   one prime is present then the relation gets added to the tree; 
	   if both primes are present then the relation creates one cycle 
	   but is *not* added to the tree. 
	   
	   It's really great to see such simple ideas do something so
	   complicated as finding cycles (and doing it very quickly) */

	/* First traverse the entire graph and remove any vertices
	   that are not the roots of connected components (i.e.
	   remove any primes whose cycle_t entry does not point
	   to itself */

	for (i = 0; i < (1 << LOG2_CYCLE_HASH); i++) {
		uint32 offset = hashtable[i];

		while (offset != 0) {
			cycle_t *entry = table + offset;
			if (offset != entry->data)
				entry->data = 0;
			offset = entry->next;
		}
	}

	logprintf(obj, "attempting to build %u cycles\n", num_cycles);
	cycle_list = (la_col_t *)xmalloc(num_cycles * sizeof(la_col_t));

	/* keep going until either all cycles are found, all
	   relations are processed, or cycles stop arriving. 
	   Normally these conditions all occur at the same time */

	for (start = passes = curr_cycle = 0; start < num_relations && 
			curr_cycle < num_cycles; passes++) {

		/* The list of relations up to index 'start' is con-
		   sidered processed. For all relations past that... */

		uint32 start_cycles = curr_cycle;

		for (i = start; i < num_relations &&
				curr_cycle < num_cycles; i++) {

			cycle_t *entry1, *entry2;
			relation_t rtmp = relation_list[i];
			
			if (rtmp.large_prime[0] == rtmp.large_prime[1]) {

				/* this is a full relation, and forms a
				   cycle just by itself. Move it to position 
				   'start' of the relation list and increment 
				   'start'. The relation is now frozen at 
				   that position */

				la_col_t *c = cycle_list + curr_cycle++;
				relation_list[i] = relation_list[start];
				relation_list[start] = rtmp;

				/* build a trivial cycle for the relation */

				c->cycle.num_relations = 1;
				c->cycle.list = (uint32 *)
						xmalloc(sizeof(uint32));
				c->cycle.list[0] = start++;
				continue;
			}

			/* retrieve the cycle_t entries associated
			   with the large primes in relation r. */

			entry1 = get_table_entry(table, hashtable, 
						rtmp.large_prime[0], 0);
			entry2 = get_table_entry(table, hashtable, 
						rtmp.large_prime[1], 0);

			/* if both vertices do not point to other
			   vertices, then neither prime has been added
			   to the graph yet, and r must remain unprocessed */

			if (entry1->data == 0 && entry2->data == 0)
				continue;

			/* if one or the other prime is part of the
			   graph, add r to the graph. The vertex not in
			   the graph points to the vertex that is, and
			   this entry also points to the relation that
			   is associated with rtmp.

			   If both primes are in the graph, recover the
			   cycle this generates */

			if (entry1->data == 0) {
				entry1->data = entry2 - table;
				entry1->count = start;
			}
			else if (entry2->data == 0) {
				entry2->data = entry1 - table;
				entry2->count = start;
			}
			else {
				la_col_t *c = cycle_list + curr_cycle;
				c->cycle.list = NULL;
				enumerate_cycle(obj, c, table, entry1,
						entry2, start);
				if (c->cycle.list)
					curr_cycle++;
			}

			/* whatever happened above, the relation is
			   processed now; move it to position 'start'
			   of the relation list and increment 'start'.
			   The relation is now frozen at that position */

			relation_list[i] = relation_list[start];
			relation_list[start++] = rtmp;
		}

		/* If this pass did not find any new cycles, then
		   we've reached steady state and are finished */

		if (curr_cycle == start_cycles)
			break;
	}
	num_cycles = curr_cycle;

	logprintf(obj, "found %u cycles in %u passes\n", num_cycles, passes);
	
	/* sort the list of cycles so that the cycles with
	   the largest number of relations will come last. 
	   If the linear algebra code skips any cycles it
	   can easily skip the most dense cycles */

	qsort(cycle_list, (size_t)num_cycles, sizeof(la_col_t), sort_cycles);

	conf->relation_list = relation_list;
	conf->num_relations = num_relations;
	conf->cycle_list = cycle_list;
	conf->num_cycles = num_cycles;

	/* print out a histogram of cycle lengths for infor-
	   mational purposes */

	for (i = 0; i < num_cycles; i++) {
		num_relations = cycle_list[i].cycle.num_relations;

		if (num_relations >= NUM_CYCLE_BINS)
			cycle_bins[NUM_CYCLE_BINS]++;
		else
			cycle_bins[num_relations - 1]++;
	}
	logprintf(obj, "distribution of cycle lengths:\n");
	for (i = 0; i < NUM_CYCLE_BINS; i++) {
		if (cycle_bins[i]) {
			logprintf(obj, "   length %d : %d\n", 
					i + 1, cycle_bins[i]);
		}
	}
	if (cycle_bins[i])
		logprintf(obj, "   length %u+: %u\n", i + 1, cycle_bins[i]);
	logprintf(obj, "largest cycle: %u relations\n",
			cycle_list[num_cycles-1].cycle.num_relations);
}