Example #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;
}
Example #2
0
static uint8 choose_multiplier(mp_t *n, prime_list_t *prime_list,
				uint32 fb_size) {
	uint32 i, j;
	uint32 num_primes = MIN(2 * fb_size, NUM_TEST_PRIMES);
	double best_score;
	uint8 best_mult;
	double scores[NUM_MULTIPLIERS];
	uint32 num_multipliers;
	double log2n = mp_log(n);

	num_primes = MIN(num_primes, prime_list->num_primes);

	/* measure the contribution of 2 as a factor of sieve
	   values. The multiplier itself must also be taken into
	   account in the score. scores[i] is the correction that
	   is implicitly applied to the size of sieve values for
	   multiplier i; a negative score makes sieve values 
	   smaller, and so is better */

	for (i = 0; i < NUM_MULTIPLIERS; i++) {
		uint8 curr_mult = mult_list[i];
		uint8 knmod8 = (curr_mult * n->val[0]) % 8;
		double logmult = log((double)curr_mult);

		/* only consider multipliers k such than
		   k*n will not overflow an mp_t */

		if (log2n + logmult > (32 * MAX_MP_WORDS - 2) * M_LN2)
			break;

		scores[i] = 0.5 * logmult;
		switch (knmod8) {
		case 1:
			scores[i] -= 2 * M_LN2;
			break;
		case 5:
			scores[i] -= M_LN2;
			break;
		case 3:
		case 7:
			scores[i] -= 0.5 * M_LN2;
			break;
		/* even multipliers start with a handicap */
		}
	}
	num_multipliers = i;

	/* for the rest of the small factor base primes */

	for (i = 1; i < num_primes; i++) {
		uint32 prime = prime_list->list[i];
		double contrib = log((double)prime) / (prime - 1);
		uint32 modp = mp_mod_1(n, prime);

		for (j = 0; j < num_multipliers; j++) {
			uint8 curr_mult = mult_list[j];
			uint32 knmodp = mp_modmul_1(modp, curr_mult, prime);

			/* if prime i is actually in the factor base
			   for k * n ... */

			if (knmodp == 0 || mp_legendre_1(knmodp, prime) == 1) {

				/* ...add its contribution. A prime p con-
				   tributes log(p) to 1 in p sieve values, plus
				   log(p) to 1 in p^2 sieve values, etc. The
				   average contribution of all multiples of p 
				   to a random sieve value is thus

				   log(p) * (1/p + 1/p^2 + 1/p^3 + ...)
				   = (log(p) / p) * 1 / (1 - (1/p)) 
				   = log(p) / (p-1)

				   This contribution occurs once for each
				   square root used for sieving. There are two
				   roots for each factor base prime, unless
				   the prime divides k*n. In that case there 
				   is only one root */

				if (knmodp == 0)
					scores[j] -= contrib;
				else
					scores[j] -= 2 * contrib;
			}
		}

	}

	/* use the multiplier that generates the best score */

	best_score = 1000.0;
	best_mult = 1;
	for (i = 0; i < num_multipliers; i++) {
		double score = scores[i];
		if (score < best_score) {
			best_score = score;
			best_mult = mult_list[i];
		}
	}
	return best_mult;
}
Example #3
0
File: makefb.c Project: pstach/gls
static inline u_int32_t mp_modsqrt_1(u_int32_t a, u_int32_t p)
{

	u_int32_t a0 = a;

	if((p & 7) == 3 || (p & 7) == 7)
	{
		return mp_expo_1(a0, (p+1)/4, p);
	}
	else if((p & 7) == 5)
	{
		u_int32_t x, y;

		if(a0 >= p)
		a0 = a0 % p;
		x = mp_expo_1(a0, (p+3)/8, p);

		if(mp_modmul_1(x, x, p) == a0)
			return x;

		y = mp_expo_1(2, (p-1)/4, p);

		return mp_modmul_1(x, y, p);
	}
	else
	{
		u_int32_t d0, d1, a1, s, t, m;
		u_int32_t i;

		if(a0 == 1)
			return 1;

		for(d0 = 2; d0 < p; d0++)
		{
			if(mp_legendre_1(d0, p) != -1)
				continue;

			t = p - 1;
			s = 0;
			while(!(t & 1))
			{
				s++;
				t = t / 2;
			}

			a1 = mp_expo_1(a0, t, p);
			d1 = mp_expo_1(d0, t, p);

			for(i = 0, m = 0; i < s; i++)
			{
				u_int32_t ad;

				ad = mp_expo_1(d1, m, p);
				ad = mp_modmul_1(ad, a1, p);
				ad = mp_expo_1(ad, (u_int32_t)(1) << (s-1-i), p);
				if(ad == (p - 1))
					m += (1 << i);
			}

			a1 = mp_expo_1(a0, (t+1)/2, p);
			d1 = mp_expo_1(d1, m/2, p);
			return mp_modmul_1(a1, d1, p);
		}
	}

	printf("modsqrt_1 failed\n");
	exit(-1);
	return 0;
}