Beispiel #1
0
int isPrime(z *n)
{
	// translate into gmp's test
	mpz_t gmpz;
	int i;

	mpz_init(gmpz);
		
	mp2gmp(n, gmpz);
	i = is_mpz_prp(gmpz);

	mpz_clear(gmpz);
	return (i > 0);
}
Beispiel #2
0
/*-------------------------------------------------------------------*/
static void relation_to_poly(abpair_t *abpair, mp_t *c,
				gmp_poly_t *poly) {

	/* given a and b in abpair, along with c, compute
	   poly(x) = a*c - b*x */

	mp2gmp(c, poly->coeff[0]);
	int64_2gmp(abpair->a, poly->coeff[1]);
	mpz_mul(poly->coeff[0], poly->coeff[0], poly->coeff[1]);
	mpz_set_ui(poly->coeff[1], (unsigned long)abpair->b);

	poly->degree = 0;
	if (abpair->b > 0) {
		poly->degree = 1;
		mpz_neg(poly->coeff[1], poly->coeff[1]);
	}
}
/*------------------------------------------------------------------*/
static void relation_to_gmp(relation_batch_t *rb,
				uint32 index, mpz_t out) {

	/* multiply together the unfactored parts of an
	   NFS relation, then convert to an mpz_t */

	uint32 i, nwords;
	cofactor_t *c = rb->relations + index;
	uint32 *f = rb->factors + c->factor_list_word + 
			c->num_factors_r + c->num_factors_a;
	mp_t num1, num2, num3;

	if (c->lp_r_num_words > 1 && c->lp_a_num_words > 1) {

		/* rational and algebraic parts need to be
		   multiplied together first */

		mp_clear(&num1);
		mp_clear(&num2);
		num1.nwords = c->lp_r_num_words;
		for (i = 0; i < c->lp_r_num_words; i++)
			num1.val[i] = f[i];
		num2.nwords = c->lp_a_num_words;
		f += c->lp_r_num_words;
		for (i = 0; i < c->lp_a_num_words; i++)
			num2.val[i] = f[i];
		mp_mul(&num1, &num2, &num3);
	}
	else {
		/* no multiply necesary */

		mp_clear(&num3);
		nwords = c->lp_r_num_words;

		if (c->lp_a_num_words > 1) {
			nwords = c->lp_a_num_words;
			f += c->lp_r_num_words;
		}

		num3.nwords = nwords;
		for (i = 0; i < nwords; i++)
			num3.val[i] = f[i];
	}
	mp2gmp(&num3, out);
}
Beispiel #4
0
/*-------------------------------------------------------------------*/
static void convert_to_integer(gmp_poly_t *alg_sqrt, mp_t *n,
				mp_t *c, signed_mp_t *m1, 
				signed_mp_t *m0, mp_t *res) {

	/* given the completed square root, apply the homomorphism
	   to convert the polynomial to an integer. We do this
	   by evaluating alg_sqrt at c*m0/m1, with all calculations
	   performed mod n */

	uint32 i;
	mpz_t gmp_n;
	mp_t m1_pow;
	mp_t m1_tmp;
	mp_t m0_tmp;
	mp_t next_coeff;

	mpz_init(gmp_n); 
	mp2gmp(n, gmp_n);
	gmp_poly_mod_q(alg_sqrt, gmp_n, alg_sqrt);
	mpz_clear(gmp_n);

	mp_copy(&m1->num, &m1_tmp);
	if (m1->sign == NEGATIVE)
		mp_sub(n, &m1_tmp, &m1_tmp);
	mp_copy(&m1_tmp, &m1_pow);

	mp_modmul(&m0->num, c, n, &m0_tmp);
	if (m0->sign == POSITIVE)
		mp_sub(n, &m0_tmp, &m0_tmp);

	i = alg_sqrt->degree;
	gmp2mp(alg_sqrt->coeff[i], res);

	for (i--; (int32)i >= 0; i--) {
		mp_modmul(res, &m0_tmp, n, res);
		gmp2mp(alg_sqrt->coeff[i], &next_coeff);
		mp_modmul(&next_coeff, &m1_pow, n, &next_coeff);
		mp_add(res, &next_coeff, res);
		if (i > 0)
			mp_modmul(&m1_pow, &m1_tmp, n, &m1_pow);
	}
	if (mp_cmp(res, n) > 0)
		mp_sub(res, n, res);
}
Beispiel #5
0
/*-------------------------------------------------------------------*/
void alg_square_root(msieve_obj *obj, mp_poly_t *mp_alg_poly, 
			mp_t *n, mp_t *c, signed_mp_t *m1, 
			signed_mp_t *m0, abpair_t *rlist, 
			uint32 num_relations, uint32 check_q,
			mp_t *sqrt_a) {
	
	/* external interface for computing the algebraic
	   square root */

	uint32 i;
	gmp_poly_t alg_poly;
	gmp_poly_t d_alg_poly;
	gmp_poly_t prod;
	gmp_poly_t alg_sqrt;
	relation_prod_t prodinfo;
	double log2_prodsize;
	mpz_t q;

	/* initialize */

	mpz_init(q);
	gmp_poly_init(&alg_poly);
	gmp_poly_init(&d_alg_poly);
	gmp_poly_init(&prod);
	gmp_poly_init(&alg_sqrt);

	/* convert the algebraic poly to arbitrary precision */

	for (i = 0; i < mp_alg_poly->degree; i++) {
		signed_mp_t *coeff = mp_alg_poly->coeff + i;
		mp2gmp(&coeff->num, alg_poly.coeff[i]);
		if (coeff->sign == NEGATIVE)
			mpz_neg(alg_poly.coeff[i], alg_poly.coeff[i]);
	}
	alg_poly.degree = mp_alg_poly->degree - 1;

	/* multiply all the relations together */

	prodinfo.monic_poly = &alg_poly;
	prodinfo.rlist = rlist;
	prodinfo.c = c;

	logprintf(obj, "multiplying %u relations\n", num_relations);
	multiply_relations(&prodinfo, 0, num_relations - 1, &prod);
	logprintf(obj, "multiply complete, coefficients have about "
			"%3.2lf million bits\n",
			(double)mpz_sizeinbase(prod.coeff[0], 2) / 1e6);

	/* perform a sanity check on the result */

	i = verify_product(&prod, rlist, num_relations, 
				check_q, c, mp_alg_poly);
	free(rlist);
	if (i == 0) {
		logprintf(obj, "error: relation product is incorrect\n");
		goto finished;
	}

	/* multiply by the square of the derivative of alg_poly;
	   this will guarantee that the square root of prod actually 
	   is an element of the number field defined by alg_poly.
	   If we didn't do this, we run the risk of the main Newton
	   iteration not converging */

	gmp_poly_monic_derivative(&alg_poly, &d_alg_poly);
	gmp_poly_mul(&d_alg_poly, &d_alg_poly, &alg_poly, 0);
	gmp_poly_mul(&prod, &d_alg_poly, &alg_poly, 1);

	/* pick the initial small prime to start the Newton iteration.
	   To save both time and memory, choose an initial prime 
	   such that squaring it a large number of times will produce
	   a value just a little larger than we need to calculate
	   the square root.
	
	   Note that contrary to what some authors write, pretty much
	   any starting prime is okay. The Newton iteration has a division
	   by 2, so that 2 must be invertible mod the prime (this is
	   guaranteed for odd primes). Also, the Newton iteration will
	   fail if both square roots have the same value mod the prime;
	   however, even a 16-bit prime makes this very unlikely */

	i = mpz_size(prod.coeff[0]);
	log2_prodsize = (double)GMP_LIMB_BITS * (i - 2) +
			log(mpz_getlimbn(prod.coeff[0], (mp_size_t)(i-1)) *
				pow(2.0, (double)GMP_LIMB_BITS) +
			    mpz_getlimbn(prod.coeff[0], (mp_size_t)(i-2))) / 
			M_LN2 + 10000;

	while (log2_prodsize > 31.5)
		log2_prodsize *= 0.5;

	mpz_set_d(q, (uint32)pow(2.0, log2_prodsize) + 1);

	/* get the initial inverse square root */

	if (!get_initial_inv_sqrt(obj, mp_alg_poly, 
				&prod, &alg_sqrt, q)) {
		goto finished;
	}

	/* compute the actual square root */

	if (get_final_sqrt(obj, &alg_poly, &prod, &alg_sqrt, q))
		convert_to_integer(&alg_sqrt, n, c, m1, m0, sqrt_a);

finished:
	gmp_poly_clear(&prod);
	gmp_poly_clear(&alg_sqrt);
	gmp_poly_clear(&alg_poly);
	gmp_poly_clear(&d_alg_poly);
	mpz_clear(q);
}
Beispiel #6
0
uint32 ecm_pp1_pm1(msieve_obj *obj, mp_t *n, mp_t *reduced_n, 
		   factor_list_t *factor_list) {

	uint32 i, j, max_digits;
	uint32 bits;
	mpz_t gmp_n, gmp_factor;
	pm1_pp1_t non_ecm_vals[NUM_NON_ECM];
	uint32 factor_found = 0;
	uint32 num_trivial = 0;
	ecm_params params;

	/* factorization will continue until any remaining
	   composite cofactors are smaller than the cutoff for
	   using other methods */

	/* initialize */

	mpz_init(gmp_n);
	mpz_init(gmp_factor);
	for (i = 0; i < NUM_NON_ECM; i++) {
		pm1_pp1_t *tmp = non_ecm_vals + i;
		tmp->stage_1_done = 1.0;
		mpz_init_set_ui(tmp->start_val, (unsigned long)0);
	}
	ecm_init(params);
	gmp_randseed_ui(params->rng, get_rand(&obj->seed1, &obj->seed2));
	mp2gmp(n, gmp_n);
	max_digits = choose_max_digits(obj, mp_bits(n));

	/* for each digit level */

	for (i = 0; i < NUM_TABLE_ENTRIES; i++) {
		const work_t *curr_work = work_table + i;
		uint32 log_rate, next_log;
		int status;

		if (curr_work->digits > max_digits)
			break;

		logprintf(obj, "searching for %u-digit factors\n",
				curr_work->digits);

		/* perform P-1. Stage 1 runs much faster for this
		   algorithm than it does for ECM, so crank up the
		   stage 1 bound
		
		   We save the stage 1 output to reduce the work at
		   the next digit level */

		for (j = 0; j < NUM_PM1_TRIALS; j++) {
			pm1_pp1_t *tmp = non_ecm_vals + j;

			params->method = ECM_PM1;
			params->B1done = tmp->stage_1_done;
			mpz_set(params->x, tmp->start_val);

			status = ecm_factor(gmp_factor, gmp_n,
					10 * curr_work->stage_1_bound, params);

			tmp->stage_1_done = params->B1done;
			mpz_set(tmp->start_val, params->x);
			HANDLE_FACTOR_FOUND("P-1");
		}

		/* perform P+1. Stage 1 runs somewhat faster for this
		   algorithm than it does for ECM, so crank up the
		   stage 1 bound
		
		   We save the stage 1 output to reduce the work at
		   the next digit level */

		for (j = 0; j < NUM_PP1_TRIALS; j++) {
			pm1_pp1_t *tmp = non_ecm_vals + NUM_PM1_TRIALS + j;

			params->method = ECM_PP1;
			params->B1done = tmp->stage_1_done;
			mpz_set(params->x, tmp->start_val);

			status = ecm_factor(gmp_factor, gmp_n,
					5 * curr_work->stage_1_bound, params);

			tmp->stage_1_done = params->B1done;
			mpz_set(tmp->start_val, params->x);
			HANDLE_FACTOR_FOUND("P+1");
		}

		/* run the specified number of ECM curves. Because
		   so many curves could be necessary, just start each
		   one from scratch */

		log_rate = 0;
		if (obj->flags & (MSIEVE_FLAG_USE_LOGFILE |
	    		   	  MSIEVE_FLAG_LOG_TO_STDOUT)) {
			if (curr_work->digits >= 35)
				log_rate = 1;
			else if (curr_work->digits >= 30)
				log_rate = 5;
			else if (curr_work->digits >= 25)
				log_rate = 20;
		}

		next_log = log_rate;
		for (j = 0; j < curr_work->num_ecm_trials; j++) {

			params->method = ECM_ECM;
			params->B1done = 1.0;
			mpz_set_ui(params->x, (unsigned long)0);
			mpz_set_ui(params->sigma, (unsigned long)0);

			status = ecm_factor(gmp_factor, gmp_n,
					curr_work->stage_1_bound, params);
			HANDLE_FACTOR_FOUND("ECM");

			if (log_rate && j == next_log) {
				next_log += log_rate;
				fprintf(stderr, "%u of %u curves\r",
						j, curr_work->num_ecm_trials);
				fflush(stderr);
			}
		}

		if (log_rate)
			fprintf(stderr, "\ncompleted %u ECM curves\n", j);
	}

clean_up:
	ecm_clear(params);
	gmp2mp(gmp_n, reduced_n);
	mpz_clear(gmp_n);
	mpz_clear(gmp_factor);
	for (i = 0; i < NUM_NON_ECM; i++)
		mpz_clear(non_ecm_vals[i].start_val);
	return factor_found;
}