示例#1
0
/*--------------------------------------------------------------------*/
static void build_factor_base(mp_t *n, 
				prime_list_t *prime_list,
				fb_t **out_fb,
				uint32 **out_modsqrt,
				uint32 *out_fb_size, 
				uint32 *out_multiplier) {

	/* Fills in all the factor base information */

	uint32 i, j;
	fb_t *fb_array, *fbptr;
	uint32 fb_size = *out_fb_size;
	uint32 num_primes = prime_list->num_primes;
	uint32 *modsqrt_array;

	*out_multiplier = choose_multiplier(n, prime_list, fb_size);
	mp_mul_1(n, *out_multiplier, n);

	fb_array = (fb_t *)xmalloc(fb_size * sizeof(fb_t));
	modsqrt_array = (uint32 *)xmalloc(fb_size * sizeof(uint32));
	fbptr = fb_array + MIN_FB_OFFSET;
	fbptr->prime = 2;
	fbptr++;

	for (i = 1, j = MIN_FB_OFFSET+1; i < num_primes; i++) {

		uint32 prime = prime_list->list[i];
		uint32 nmodp;

		if (j == fb_size)
			break;

		/* if n is a quadratic residue mod 'prime', then
		   'prime' belongs in the factor base */

		nmodp = mp_mod_1(n, prime);
		if (nmodp == 0 || mp_legendre_1(nmodp, prime) == 1) {

			fbptr->prime = prime;
			fbptr->logprime = (uint8)(log((double)prime) / 
							M_LN2 + .5);

			/* find x such that x^2 mod prime = n mod prime */

			if (nmodp != 0) {
				modsqrt_array[j] = mp_modsqrt_1(nmodp, prime);
			}
			fbptr++;
			j++;
		}
	}
	*out_fb_size = j;
	*out_fb = fb_array;
	*out_modsqrt = modsqrt_array;
}
示例#2
0
文件: makefb.c 项目: pstach/gls
/*------------------------------------------------------------------*/
static void get_zeros_rec(u_int32_t *zeros, u_int32_t shift,
			u_int32_t *num_zeros, poly_t f, u_int32_t p) {

	/* get the zeros of a poly, f, that is known to split
	   completely over Z/pZ. Many thanks to Bob Silverman
	   for a neat implementation of Cantor-Zassenhaus splitting */

	poly_t g, xpow;
	u_int32_t degree1, degree2;

	/* base cases of the recursion: we can find the roots
	   of linear and quadratic polynomials immediately */

	if (f->degree == 1) {
		u_int32_t w = f->coef[1];
		if (w != 1) {
			w = mp_modinv_1(w, p);
			zeros[(*num_zeros)++] = mp_modmul_1(p - f->coef[0],w,p);
		}
		else {
			zeros[(*num_zeros)++] = (f->coef[0] == 0 ? 0 :
							p - f->coef[0]);
		}
		return;
	}
	else if (f->degree == 2) {

		/* if f is a quadratic polynomial, then it will
		   always have two distinct nonzero roots or else
		   we wouldn't have gotten to this point. The two
		   roots are the solution of a general quadratic
		   equation, mod p */

		u_int32_t d = mp_modmul_1(f->coef[0], f->coef[2], p);
		u_int32_t root1 = p - f->coef[1];
		u_int32_t root2 = root1;
		u_int32_t ainv = mp_modinv_1(
				mp_modadd_1(f->coef[2], f->coef[2], p),
				p);

		d = mp_modsub_1(mp_modmul_1(f->coef[1], f->coef[1], p),
				mp_modmul_1(4, d, p),
				p);
		d = mp_modsqrt_1(d, p);

		root1 = mp_modadd_1(root1, d, p);
		root2 = mp_modsub_1(root2, d, p);
		zeros[(*num_zeros)++] = mp_modmul_1(root1, ainv, p);
		zeros[(*num_zeros)++] = mp_modmul_1(root2, ainv, p);
		return;
	}

	/* For an increasing sequence of integers 's', compute
	   the polynomial gcd((x-s)^(p-1)/2 - 1, f). If the result is
	   not g = 1 or g = f, this is a nontrivial splitting
	   of f. References require choosing s randomly, but however
	   s is chosen there is a 50% chance that it will split f.
	   Since only 0 <= s < p is valid, we choose each s in turn;
	   choosing random s allows the possibility that the same
	   s gets chosen twice (mod p), which would waste time */

	while (shift < p) {
		poly_xpow(xpow, shift, (p-1)/2, f, p);

		poly_cp(g, xpow);
		g->coef[0] = mp_modsub_1(g->coef[0], 1, p);
		poly_fix_degree(g);

		poly_gcd(g, f, p);

		if (g->degree > 0)
			break;
		shift++;
	}

	/* f was split; repeat the splitting process on
	   the two halves of f. The linear factors of f are
	   either somewhere in x^((p-1)/2) - 1, in
	   x^((p-1)/2) + 1, or 'shift' itself is a linear
	   factor. Test each of these possibilities in turn.
	   In the first two cases, begin trying values of s
	   strictly greater than have been tried thus far */

	degree1 = g->degree;
	get_zeros_rec(zeros, shift + 1, num_zeros, g, p);

	poly_cp(g, xpow);
	g->coef[0] = mp_modadd_1(g->coef[0], 1, p);
	poly_fix_degree(g);
	poly_gcd(g, f, p);
	degree2 = g->degree;

	if (degree2 > 0)
		get_zeros_rec(zeros, shift + 1, num_zeros, g, p);

	if (degree1 + degree2 < f->degree)
		zeros[(*num_zeros)++] = (shift == 0 ? 0 : p - shift);
}