/*------------------------------------------------------------------------*/
static uint32
get_prime_roots(poly_coeff_t *c, uint32 p, uint32 *roots,
		mpz_poly_t *tmp_poly)
{
	/* find all nonzero roots of (N' - x^d) mod p, where 
	   d is the desired polynomial degree and N' is the 
	   transformed version of N modulo p. We throw out roots
	   of zero because a zero root implies p divides the
	   degree or the leading algebraic poly coefficient, and
	   neither of these is allowed in later stages */

	uint32 i, high_coeff;

	mpz_tdiv_r_ui(tmp_poly->coeff[0], c->trans_N, p);

	if (mpz_cmp_ui(tmp_poly->coeff[0], 0) == 0) {
		/* when p divides trans_N, only a root of zero
		   exists, so skip this p */
		return 0;
	}
	for (i = 1; i < c->degree; i++)
		mpz_set_ui(tmp_poly->coeff[i], 0);

	tmp_poly->degree = i;
	mpz_set_ui(tmp_poly->coeff[i], p - 1);

	return poly_get_zeros(roots, tmp_poly, p, &high_coeff, 0);
}
Exemple #2
0
int main(int argc, char *argv[])
{
	int poly_idx;
	gls_config_t cfg;
	fb_t fb;
	u_int32_t i, n_roots;
	u_int64_t fb_idx, fb_alloc;
	mpz_t P, roots[MAX_POLY_DEGREE];
	u_int32_t roots_ui[MAX_POLY_DEGREE];
	char fname[4096];
	off_t align;
	int fd;

	if(argc < 2)
	{
		fprintf(stderr, "usage: %s <polyconfig>\n", argv[0]);
		return 1;
	}

	gls_config_init(cfg);
	if(polyfile_read(cfg, argv[1]) < 0)
		return 1;

	mpz_init(P);
	for(i = 0; i < sizeof(roots) / sizeof(roots[0]); i++)
		mpz_init(roots[i]);

	for(poly_idx = 0; poly_idx < POLY_CNT; poly_idx++)
	{
		fb_init(fb);

		fb_idx = 0;
		fb_alloc = 0;
		for(mpz_set_ui(P, 2); mpz_cmp_ui(P, MAX_SMALL_PRIME) < 0 && mpz_cmp_ui(P, cfg->lim[poly_idx]) < 0; mpz_nextprime(P, P))
		{
			n_roots = poly_get_zeros(roots_ui, cfg->poly[poly_idx], mpz_get_ui(P), 0);
			if(!n_roots)
				continue;
			qsort(roots_ui, n_roots, sizeof(roots_ui[0]), ui_cmp);
//#define TEST_ROOTFINDER 1
#ifdef TEST_ROOTFINDER
			for(i = 0; i < n_roots; i++)
			{
				mpz_t tmp1, tmp2;
				mpz_init_set_ui(tmp1, roots_ui[i]);
				mpz_init(tmp2);
				mpzpoly_eval_mod(tmp2, cfg->poly[poly_idx], tmp1, P);
				if(mpz_cmp_ui(tmp2, 0) != 0)
				{
					printf("BAD ROOT (%u,%u)\n", roots_ui[i], mpz_get_ui(P));
					exit(-1);
				}
				mpz_clear(tmp1);
				mpz_clear(tmp2);
			}
#endif

			fb->n_small += n_roots;
			if(fb->n_small > fb_alloc)
			{
				fb_alloc += 4096;
				fb->r_small = (u_int32_t *) realloc(fb->r_small, sizeof(u_int32_t) * fb_alloc);
				fb->p_small = (u_int32_t *) realloc(fb->p_small, sizeof(u_int32_t) * fb_alloc);

				if(!fb->r_small || !fb->p_small)
				{
					perror("realloc");
					exit(1);
				}
			}
			for(i = 0; i < n_roots; i++)
			{
				fb->r_small[fb_idx] = roots_ui[i];
				fb->p_small[fb_idx] = mpz_get_ui(P);
				fb_idx++;
			}
		}

		fb_idx = 0;
		fb_alloc = 0;
		for(; mpz_cmp_ui(P, cfg->lim[poly_idx]) < 0; mpz_nextprime(P, P))
		{
			n_roots = mpzpoly_get_roots(roots, cfg->poly[poly_idx], P);
			if(!n_roots)
				continue;

			fb->n_large += n_roots;
			if(fb->n_large > fb_alloc)
			{
				fb_alloc += 4096;
				fb->r_large = (u_int64_t *) realloc(fb->r_large, sizeof(u_int64_t) * fb_alloc);
				fb->p_large = (u_int64_t *) realloc(fb->p_large, sizeof(u_int64_t) * fb_alloc);

				if(!fb->r_large || !fb->p_large)
				{
					perror("realloc");
					exit(1);
				}
			}
			for(i = 0; i < n_roots; i++)
			{
				fb->r_large[fb_idx] = mpz_get_ui(roots[i]);
				fb->p_large[fb_idx] = mpz_get_ui(P);
				fb_idx++;
			}
		}

		memset(fname, 0, sizeof(fname));
		snprintf(fname, sizeof(fname) - 1, "%s.fb.%u", argv[1], poly_idx);

		if(fb_filesave(fb, fname) < 0)
			return 1;
//#define TEST_SAVELOAD 1
#ifdef TEST_SAVELOAD
		{
			fb_t fb2;

			fb_init(fb2);
			if(fb_fileread(fb2, fname) < 0)
				return 1;

			if(fb->n_small != fb2->n_small || fb->n_large != fb2->n_large)
			{
				printf("COUNT MISMATCH\n");
				return 1;
			}
			if(memcmp(fb->p_small, fb2->p_small, sizeof(u_int32_t) * fb->n_small) != 0)
			{
				printf("SMALL MISMATCH\n");
				return 1;
			}
			if(memcmp(fb->p_large, fb2->p_large, sizeof(u_int64_t) * fb->n_large) != 0)
			{
				printf("LARGE MISMATCH\n");
				return 1;
			}
			fb_clear(fb2);
		}
#endif
		fb_clear(fb);
	}
	return 0;
}