/*-------------------------------------------------------------------*/ static void convert_to_integer(mpz_poly_t *alg_sqrt, mpz_t n, mpz_t c, mpz_t m1, mpz_t m0, mpz_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 m1_pow; mpz_t m0c; mpz_init_set(m1_pow, m1); mpz_poly_mod_q(alg_sqrt, n, alg_sqrt); mpz_init_set_ui(m0c, 0); mpz_submul(m0c, m0, c); mpz_mod(m0c, m0c, n); i = alg_sqrt->degree; mpz_set(res, alg_sqrt->coeff[i]); while (--i) { mpz_mul(res, res, m0c); mpz_addmul(res, m1_pow, alg_sqrt->coeff[i]); mpz_mul(m1_pow, m1_pow, m1); } mpz_mul(res, res, m0c); mpz_addmul(res, m1_pow, alg_sqrt->coeff[i]); mpz_mod(res, res, n); mpz_clear(m1_pow); mpz_clear(m0c); }
void refmpq_sub (mpq_ptr w, mpq_srcptr x, mpq_srcptr y) { mpz_mul (mpq_numref(w), mpq_numref(x), mpq_denref(y)); mpz_submul (mpq_numref(w), mpq_denref(x), mpq_numref(y)); mpz_mul (mpq_denref(w), mpq_denref(x), mpq_denref(y)); mpq_canonicalize (w); }
void testmain (int argc, char **argv) { unsigned i; mpz_t a, b, res, ref; mpz_init (a); mpz_init (b); mpz_init_set_ui (res, 5); mpz_init (ref); for (i = 0; i < COUNT; i++) { mini_random_op3 (OP_MUL, MAXBITS, a, b, ref); if (i & 1) { mpz_add (ref, ref, res); if (mpz_fits_ulong_p (b)) mpz_addmul_ui (res, a, mpz_get_ui (b)); else mpz_addmul (res, a, b); } else { mpz_sub (ref, res, ref); if (mpz_fits_ulong_p (b)) mpz_submul_ui (res, a, mpz_get_ui (b)); else mpz_submul (res, a, b); } if (mpz_cmp (res, ref)) { if (i & 1) fprintf (stderr, "mpz_addmul failed:\n"); else fprintf (stderr, "mpz_submul failed:\n"); dump ("a", a); dump ("b", b); dump ("r", res); dump ("ref", ref); abort (); } } mpz_clear (a); mpz_clear (b); mpz_clear (res); mpz_clear (ref); }
/** * Set pivot column to 0 * @param r indice de la premiere ligne a annuler * on recalcule les coefficients modulo mod a chaque fois */ void del_coeffs(int r, int matrix_length, mpz_t *M, mpz_t mod){ int i, j; mpz_t M_tmp[matrix_length*matrix_length]; for (i=0; i < matrix_length*matrix_length; i++){ mpz_init(M_tmp[i]); mpz_set(M_tmp[i], M[i]); } for (i=r; i<matrix_length; i++){ for (j=r-1; j<matrix_length; j++){ /* a modifier si on enleve la normalisation */ mpz_submul(M_tmp[i*matrix_length+j], M[i*matrix_length+r-1], M[(r-1)*matrix_length+j]); } } for (i=0; i < matrix_length*matrix_length; i++){ mpz_mod(M[i], M_tmp[i], mod); } /* Clear */ for(i=0;i<matrix_length*matrix_length;i++) mpz_clear(M_tmp[i]); }
void check_one (mpz_srcptr w, mpz_srcptr x, mpz_srcptr y) { mpz_t want, got; mpz_init (want); mpz_init (got); mpz_mul (want, x, y); mpz_add (want, w, want); mpz_set (got, w); mpz_addmul (got, x, y); MPZ_CHECK_FORMAT (got); if (mpz_cmp (want, got) != 0) { printf ("mpz_addmul fail\n"); fail: mpz_trace ("w", w); mpz_trace ("x", x); mpz_trace ("y", y); mpz_trace ("want", want); mpz_trace ("got ", got); abort (); } mpz_mul (want, x, y); mpz_sub (want, w, want); mpz_set (got, w); mpz_submul (got, x, y); MPZ_CHECK_FORMAT (got); if (mpz_cmp (want, got) != 0) { printf ("mpz_submul fail\n"); goto fail; } mpz_clear (want); mpz_clear (got); }
/** * Extended Euclid's algorithm * output the combination coefficients */ void cpt_ext_gcd(mpz_t res, mpz_t c1, mpz_t c2, mpz_srcptr a, mpz_srcptr b) { mpz_t ax,bx,x,y,q,r,ay,by; mpz_init(q); mpz_init(r); mpz_init_set_si(bx,0); mpz_init_set_si(ay,0); if(mpz_cmp_si(a,0)>=0) { mpz_init_set(x,a); mpz_init_set_si(ax,1); } else { mpz_init(x); mpz_neg(x,a); mpz_init_set_si(ax,-1); } if(mpz_cmp_si(b,0)>=0) { mpz_init_set(y,b); mpz_init_set_si(by,1); } else { mpz_init(y); mpz_neg(y,b); mpz_init_set_si(by,-1); } if(mpz_cmp(x,y) > 0) { mpz_swap(x,y); mpz_swap(ax,ay); mpz_swap(bx,by); } while(mpz_cmp_si(x,0)>0) { mpz_t tmp1,tmp2; mpz_tdiv_qr(q,r,y,x); mpz_set(y,x); mpz_init_set(tmp1,ay); mpz_init_set(tmp2,by); mpz_set(ay,ax); mpz_set(by,bx); mpz_set(x,r); mpz_submul(tmp1,q,ax); mpz_submul(tmp2,q,bx); mpz_set(ax,tmp1); mpz_set(bx,tmp2); mpz_clear(tmp1); mpz_clear(tmp2); } mpz_set(res,y); mpz_set(c1,ay); mpz_set(c2,by); mpz_clear(ax); mpz_clear(bx); mpz_clear(ay); mpz_clear(by); mpz_clear(x); mpz_clear(y); mpz_clear(q); mpz_clear(r); }
//Le but de la fonction est de calculer le développement en fractions continue jusqu'à un certain rang de racine carrée de kN et de stocker les couples (A_n-1,Q_n) comme décrit dans la section (à venir) cfrac expand(const mpz_t N, const long long unsigned int rang, const mpz_t k) { cfrac res; //Contient l'ensemble des A_n-1 et l'ensemble Q_n mpz_inits(res.N, res.k, res.g, NULL); //Initialisation des variables mpz_t* A = (mpz_t*)malloc((rang+1)*sizeof(mpz_t)); //Le tableau contenant les A_n-1 mpz_t* Q = (mpz_t*)malloc((rang+2)*sizeof(mpz_t)); //Le tableau contenant les Q_n mpz_t* P = (mpz_t*)malloc((rang+1)*sizeof(mpz_t)); //Éléments reliés au Q_n mpz_t* r = (mpz_t*)malloc((rang+1)*sizeof(mpz_t)); //Interviennent dans le calcul des A_n-1 & Q_n mpz_t* q = (mpz_t*)malloc(rang*sizeof(mpz_t)); //Idem mpz_t g, tempz; //Idem, tempz = variable à tout faire mpf_t sqrtkN, tempf, tempf2; //sqrtkN = sqrt(k*N), tempf = variable à tout faire //Valeurs d'initialisation de la boucle mpz_inits(g, A[0], Q[0], r[0], tempz, NULL); mpf_inits(tempf, sqrtkN, tempf2, NULL); //Initialisation des différentes valeurs "indépendantes" mpz_set(tempz, N); mpz_mul(tempz, tempz, k); mpf_set_z(sqrtkN, tempz); mpf_sqrt(sqrtkN, sqrtkN); mpf_floor(tempf, sqrtkN); mpz_set_f(g, tempf); //g = [sqrt(kN)] mpz_set(Q[0], k); mpz_mul(Q[0], Q[0], N); //Q_-1 = kN = Q[0] mpz_set(r[0], g); //r_-1 = r[0] mpz_set_ui(A[0], 1); //A_-1 = A[0] //Calcul de P_0 & Q_0 mpz_init_set_ui(Q[1], 1); //Q_0 = Q[1] mpz_init_set_ui(P[0], 0); //P_0 = P[0] for(long long int i = 0; i < rang; i++) { switch(i) { case 0: //Calcul de q_0 mpz_init_set(q[0], g); //q_0 = [(sqrt(kN) + P_0)/Q_0] avec P_0 = 0 et Q_0 = 1 //Calcul de A_0 mpz_init_set(A[1],A[0]); mpz_mul(A[1], A[1], q[0]); //A_0 = q_0*A_-1 mpz_mod(A[1], A[1], N); //On réduit mod N //Calcul de r_0 mpz_init_set_ui(r[1], 0); //r_0 = P_0 + g - q_0.Q_0 = 0 + g - g.1 = 0 //Calcul de P_1 mpz_init_set(P[1], g); //P_1 = g - r_0 = g - 0 = g //Calcul de Q_1 = Q[2] mpz_init_set(Q[2], r[1]); mpz_sub(Q[2], Q[2], r[0]); mpz_mul(Q[2], Q[2], q[0]); mpz_add(Q[2], Q[2], Q[0]); break; default: //Calcul q_i mpz_init(q[i]); mpf_set_z(tempf, P[i]); mpf_set_z(tempf2, Q[i+1]); mpf_add(tempf, tempf, sqrtkN); //sqrt(kN) + P_i mpf_div(tempf, tempf, tempf2); mpf_floor(tempf, tempf); //floor((sqrt(kN) + P_i)/Q_i) mpz_set_f(q[i], tempf); //Calcul de r_n = r[n+1] mpz_init(r[i+1]); mpz_submul(r[i+1], q[i], Q[i+1]); mpz_add(r[i+1], r[i+1], P[i]); mpz_add(r[i+1], r[i+1], g); //Calcul de A_n = A[n+1] mpz_init_set(A[i+1],A[i]); mpz_mul(A[i+1], A[i+1], q[i]); //A_i-1*q_i mpz_add(A[i+1], A[i+1], A[i-1]); //A_i-1*q_i + A_i-2 mpz_mod(A[i+1], A[i+1], N); //réduction modulo N //Calcul P_n+1 mpz_init_set(P[i+1], g); mpz_sub(P[i+1], P[i+1], r[i+1]); //P[n+1] = g - r_n = g - r[n+1] //Calcul Q_n+1 = Q[n+2] mpz_init_set(Q[i+2], r[i+1]); mpz_sub(Q[i+2], Q[i+2], r[i]); //(r_n - r_n-1) mpz_mul(Q[i+2], Q[i+2], q[i]); //q_n(r_n - r_n-1) mpz_add(Q[i+2], Q[i+2], Q[i]); //Q_n-1 + q_n(r_n - r_n-1) break; } } //Test de routine pour voir si le développement de la fraction continue s'est bien passé mpz_t tempsqrt; mpz_init(tempsqrt); mpz_set(tempsqrt, k); mpz_mul(tempsqrt, tempsqrt, N); mpz_sqrt(tempsqrt, tempsqrt); mpz_mul_ui(tempsqrt, tempsqrt, 2); for(int i = 1; i < rang; i++) //Éviter de commencer à i = 0 puisque cela représente Q_-1 qui n'intervient uniquement dans l'algo et non dans le développement en fraction continue { if(mpz_cmp(Q[i], tempsqrt) >= 0) //Si Q_n >= 2sqrt(kN) { res.rang = 0; mpz_clears(g, tempz, NULL); mpf_clears(sqrtkN, tempf, tempf2, NULL); return res; } } //Assignation des tableaux dans le résultat res.A = A; res.Q = Q; res.r = r; res.q = q; res.P = P; mpz_set(res.N, N); mpz_set(res.k, k); res.rang = rang; mpz_set(res.g, g); //Libération de mémoire mpz_clears(g, tempz, NULL); mpf_clears(sqrtkN, tempf, tempf2, NULL); return res; }
/* If x^y is exactly representable (with maybe a larger precision than z), round it in z and return the (mpc) inexact flag in [0, 10]. If x^y is not exactly representable, return -1. If intermediate computations lead to numbers of more than maxprec bits, then abort and return -2 (in that case, to avoid loops, mpc_pow_exact should be called again with a larger value of maxprec). Assume one of Re(x) or Im(x) is non-zero, and y is non-zero (y is real). Warning: z and x might be the same variable, same for Re(z) or Im(z) and y. In case -1 or -2 is returned, z is not modified. */ static int mpc_pow_exact (mpc_ptr z, mpc_srcptr x, mpfr_srcptr y, mpc_rnd_t rnd, mpfr_prec_t maxprec) { mpfr_exp_t ec, ed, ey; mpz_t my, a, b, c, d, u; unsigned long int t; int ret = -2; int sign_rex = mpfr_signbit (mpc_realref(x)); int sign_imx = mpfr_signbit (mpc_imagref(x)); int x_imag = mpfr_zero_p (mpc_realref(x)); int z_is_y = 0; mpfr_t copy_of_y; if (mpc_realref (z) == y || mpc_imagref (z) == y) { z_is_y = 1; mpfr_init2 (copy_of_y, mpfr_get_prec (y)); mpfr_set (copy_of_y, y, MPFR_RNDN); } mpz_init (my); mpz_init (a); mpz_init (b); mpz_init (c); mpz_init (d); mpz_init (u); ey = mpfr_get_z_exp (my, y); /* normalize so that my is odd */ t = mpz_scan1 (my, 0); ey += (mpfr_exp_t) t; mpz_tdiv_q_2exp (my, my, t); /* y = my*2^ey with my odd */ if (x_imag) { mpz_set_ui (c, 0); ec = 0; } else ec = mpfr_get_z_exp (c, mpc_realref(x)); if (mpfr_zero_p (mpc_imagref(x))) { mpz_set_ui (d, 0); ed = ec; } else { ed = mpfr_get_z_exp (d, mpc_imagref(x)); if (x_imag) ec = ed; } /* x = c*2^ec + I * d*2^ed */ /* equalize the exponents of x */ if (ec < ed) { mpz_mul_2exp (d, d, (unsigned long int) (ed - ec)); if ((mpfr_prec_t) mpz_sizeinbase (d, 2) > maxprec) goto end; } else if (ed < ec) { mpz_mul_2exp (c, c, (unsigned long int) (ec - ed)); if ((mpfr_prec_t) mpz_sizeinbase (c, 2) > maxprec) goto end; ec = ed; } /* now ec=ed and x = (c + I * d) * 2^ec */ /* divide by two if possible */ if (mpz_cmp_ui (c, 0) == 0) { t = mpz_scan1 (d, 0); mpz_tdiv_q_2exp (d, d, t); ec += (mpfr_exp_t) t; } else if (mpz_cmp_ui (d, 0) == 0) { t = mpz_scan1 (c, 0); mpz_tdiv_q_2exp (c, c, t); ec += (mpfr_exp_t) t; } else /* neither c nor d is zero */ { unsigned long v; t = mpz_scan1 (c, 0); v = mpz_scan1 (d, 0); if (v < t) t = v; mpz_tdiv_q_2exp (c, c, t); mpz_tdiv_q_2exp (d, d, t); ec += (mpfr_exp_t) t; } /* now either one of c, d is odd */ while (ey < 0) { /* check if x is a square */ if (ec & 1) { mpz_mul_2exp (c, c, 1); mpz_mul_2exp (d, d, 1); ec --; } /* now ec is even */ if (mpc_perfect_square_p (a, b, c, d) == 0) break; mpz_swap (a, c); mpz_swap (b, d); ec /= 2; ey ++; } if (ey < 0) { ret = -1; /* not representable */ goto end; } /* Now ey >= 0, it thus suffices to check that x^my is representable. If my > 0, this is always true. If my < 0, we first try to invert (c+I*d)*2^ec. */ if (mpz_cmp_ui (my, 0) < 0) { /* If my < 0, 1 / (c + I*d) = (c - I*d)/(c^2 + d^2), thus a sufficient condition is that c^2 + d^2 is a power of two, assuming |c| <> |d|. Assume a prime p <> 2 divides c^2 + d^2, then if p does not divide c or d, 1 / (c + I*d) cannot be exact. If p divides both c and d, then we can write c = p*c', d = p*d', and 1 / (c + I*d) = 1/p * 1/(c' + I*d'). This shows that if 1/(c+I*d) is exact, then 1/(c' + I*d') is exact too, and we are back to the previous case. In conclusion, a necessary and sufficient condition is that c^2 + d^2 is a power of two. */ /* FIXME: we could first compute c^2+d^2 mod a limb for example */ mpz_mul (a, c, c); mpz_addmul (a, d, d); t = mpz_scan1 (a, 0); if (mpz_sizeinbase (a, 2) != 1 + t) /* a is not a power of two */ { ret = -1; /* not representable */ goto end; } /* replace (c,d) by (c/(c^2+d^2), -d/(c^2+d^2)) */ mpz_neg (d, d); ec = -ec - (mpfr_exp_t) t; mpz_neg (my, my); } /* now ey >= 0 and my >= 0, and we want to compute [(c + I * d) * 2^ec] ^ (my * 2^ey). We first compute [(c + I * d) * 2^ec]^my, then square ey times. */ t = mpz_sizeinbase (my, 2) - 1; mpz_set (a, c); mpz_set (b, d); ed = ec; /* invariant: (a + I*b) * 2^ed = ((c + I*d) * 2^ec)^trunc(my/2^t) */ while (t-- > 0) { unsigned long int v, w; /* square a + I*b */ mpz_mul (u, a, b); mpz_mul (a, a, a); mpz_submul (a, b, b); mpz_mul_2exp (b, u, 1); ed *= 2; if (mpz_tstbit (my, t)) /* multiply by c + I*d */ { mpz_mul (u, a, c); mpz_submul (u, b, d); /* ac-bd */ mpz_mul (b, b, c); mpz_addmul (b, a, d); /* bc+ad */ mpz_swap (a, u); ed += ec; } /* remove powers of two in (a,b) */ if (mpz_cmp_ui (a, 0) == 0) { w = mpz_scan1 (b, 0); mpz_tdiv_q_2exp (b, b, w); ed += (mpfr_exp_t) w; } else if (mpz_cmp_ui (b, 0) == 0) { w = mpz_scan1 (a, 0); mpz_tdiv_q_2exp (a, a, w); ed += (mpfr_exp_t) w; } else { w = mpz_scan1 (a, 0); v = mpz_scan1 (b, 0); if (v < w) w = v; mpz_tdiv_q_2exp (a, a, w); mpz_tdiv_q_2exp (b, b, w); ed += (mpfr_exp_t) w; } if ( (mpfr_prec_t) mpz_sizeinbase (a, 2) > maxprec || (mpfr_prec_t) mpz_sizeinbase (b, 2) > maxprec) goto end; } /* now a+I*b = (c+I*d)^my */ while (ey-- > 0) { unsigned long sa, sb; /* square a + I*b */ mpz_mul (u, a, b); mpz_mul (a, a, a); mpz_submul (a, b, b); mpz_mul_2exp (b, u, 1); ed *= 2; /* divide by largest 2^n possible, to avoid many loops for e.g., (2+2*I)^16777216 */ sa = mpz_scan1 (a, 0); sb = mpz_scan1 (b, 0); sa = (sa <= sb) ? sa : sb; mpz_tdiv_q_2exp (a, a, sa); mpz_tdiv_q_2exp (b, b, sa); ed += (mpfr_exp_t) sa; if ( (mpfr_prec_t) mpz_sizeinbase (a, 2) > maxprec || (mpfr_prec_t) mpz_sizeinbase (b, 2) > maxprec) goto end; } ret = mpfr_set_z (mpc_realref(z), a, MPC_RND_RE(rnd)); ret = MPC_INEX(ret, mpfr_set_z (mpc_imagref(z), b, MPC_RND_IM(rnd))); mpfr_mul_2si (mpc_realref(z), mpc_realref(z), ed, MPC_RND_RE(rnd)); mpfr_mul_2si (mpc_imagref(z), mpc_imagref(z), ed, MPC_RND_IM(rnd)); end: mpz_clear (my); mpz_clear (a); mpz_clear (b); mpz_clear (c); mpz_clear (d); mpz_clear (u); if (ret >= 0 && x_imag) fix_sign (z, sign_rex, sign_imx, (z_is_y) ? copy_of_y : y); if (z_is_y) mpfr_clear (copy_of_y); return ret; }
/*-------------------------------------------------------------------*/ static void gmp_poly_mul(gmp_poly_t *p1, gmp_poly_t *p2, gmp_poly_t *mod, uint32 free_p2) { /* multiply p1(x) by p2(x) modulo mod(x) (assumed monic) If free_p2 is nonzero the coefficients of p2(x) are freed after being used */ uint32 i, j; uint32 d = mod->degree; uint32 d1 = p1->degree; uint32 d2 = p2->degree; uint32 prod_degree; mpz_t tmp[MAX_POLY_DEGREE + 1]; /* initialize */ for (i = 0; i < MAX_POLY_DEGREE + 1; i++) mpz_init_set_ui(tmp[i], (unsigned long)0); /* multiply p1 by the leading coefficient of p2 */ for (i = 0; i <= d1; i++) { mpz_mul(tmp[i], p1->coeff[i], p2->coeff[d2]); } prod_degree = d1; if (free_p2) { mpz_realloc2(p2->coeff[d2], 1); } /* for each of the other coefficients in p2 */ for (i = d2 - 1; (int32)i >= 0; i--) { /* shift the accumulator up by one, bubbling the highest-order coefficient to the lowest */ for (j = prod_degree; (int32)j >= 0; j--) mpz_swap(tmp[j+1], tmp[j]); /* add in the product of p1(x) and coefficient i of p2 */ for (j = d1; j; j--) { mpz_addmul(tmp[j], p1->coeff[j], p2->coeff[i]); } mpz_mul(tmp[j], p1->coeff[j], p2->coeff[i]); if (free_p2) { mpz_realloc2(p2->coeff[i], 1); } /* recalculate the degree of the result */ prod_degree = d + 1; while (prod_degree && mpz_sgn(tmp[prod_degree]) == 0) prod_degree--; /* if it exceeds the degree of mod(x), subtract mod(x) * (leading accumulator coefficient) */ if (prod_degree <= d) continue; for (j = d; (int32)j >= 0; j--) { mpz_submul(tmp[j], mod->coeff[j], tmp[prod_degree]); } prod_degree--; } /* move the result in the accumulator over to p1 */ for (i = 0; i <= prod_degree; i++) { mpz_swap(p1->coeff[i], tmp[i]); mpz_clear(tmp[i]); } for (; i < MAX_POLY_DEGREE + 1; i++) mpz_clear(tmp[i]); /* recalculate the degree */ i = prod_degree; while (i > 0 && mpz_sgn(p1->coeff[i]) == 0) { mpz_realloc2(p1->coeff[i], 1); i--; } p1->degree = i; }
int ecpp_test(unsigned long n) { mpz_t a, b, x0, y0, xt, yt, tmp; int z; int is_prime = 0; if (n <= USHRT_MAX) { return sieve_test(n); } mpz_init(a); mpz_init(b); mpz_init(x0); mpz_init(y0); mpz_init(xt); mpz_init(yt); mpz_init(tmp); #ifdef DEBUG gmp_fprintf(stderr, "\nTesting %d with ECPP...\n", n); #endif /* DEBUG */ for (;;) /* keep trying while the curve order factoring fails */ { for (;;) /* keep trying while n divides curve discriminant */ { /* initialise a random point P = (x0, y0) * and a random elliptic curve E(a, b): y^2 = x^3 + a*x + b * with b expressed in terms of (a, x0, y0) so the point lies on the curve */ mpz_set_ui(a, rand() % n); mpz_set_ui(x0, rand() % n); mpz_set_ui(y0, rand() % n); mpz_init(b); mpz_mul(b, y0, y0); mpz_mul(tmp, x0, x0); mpz_submul(b, tmp, x0); mpz_submul(b, a, x0); mpz_mod_ui(b, b, n); #ifdef DEBUG gmp_fprintf(stderr, "\n\tn = %d\n", n); gmp_fprintf(stderr, "\tE: y^2 = x^3 + %Zd * x + %Zd\n", a, b); gmp_fprintf(stderr, "\tP = (%Zd,%Zd,1)\n", x0, y0); #endif /* DEBUG */ /* the discriminant of the curve and n are required to be coprimes * -- if not, then either * A) n divides the discriminant -- a new curve must be generated * B) n is composite and a proper factor is found -- the algorithm can * terminate */ ec_discriminant(tmp, a, b); #ifdef DEBUG mpz_mod_ui(tmp, tmp, n); gmp_fprintf(stderr, "\tdelta(E/GF(n)) = %Zd\n", tmp); #endif /* DEBUG */ mpz_gcd_ui(tmp, tmp, n); #ifdef DEBUG gmp_fprintf(stderr, "\tgcd(delta, n) = %Zd\n", tmp); #endif /* DEBUG */ if (0 == mpz_cmp_ui(tmp, 1)) { break; } else if (0 != mpz_cmp_ui(tmp, n)) { #ifdef DEBUG gmp_fprintf(stderr, "\tfound a proper factor, %d is composite\n", n); #endif /* DEBUG */ is_prime = 0; goto cleanup_and_return; } } /* P + P != 0, or a new curve is generated */ z = ec_add(xt, yt, x0, y0, 1, x0, y0, 1, n, a); #ifdef DEBUG gmp_fprintf(stderr, "\t2 * P = (%Zd,%Zd,%d)\n", xt, yt, z); #endif /* DEBUG */ if (0 == z) { continue; } /* the curve order algorithm failing indicates n is composite */ if (!(ec_order(tmp, a, b, n))) { #ifdef DEBUG gmp_fprintf(stderr, "\tcurve order algorithm failed, %d must be composite\n", n); #endif /* DEBUG */ is_prime = 0; break; } #ifdef DEBUG gmp_fprintf(stderr, "\t|E/GF(n)| = %Zd\n", tmp); #endif /* DEBUG */ /* the curve order should be the multiple of 2 and a "probable prime" n -- * if the order is not even, a new curve is generated */ if (!mpz_even_p(tmp)) { #ifdef DEBUG gmp_fprintf(stderr, "\t|E/GF(n)| is odd, generating new curve...\n"); #endif /* DEBUG */ continue; } /* order * P = 0, or n is composite */ z = ec_times(xt, yt, x0, y0, 1, tmp, n, a); #ifdef DEBUG gmp_fprintf(stderr, "\t|E| * P = (%Zd,%Zd,%d)\n", xt, yt, z); #endif /* DEBUG */ if (0 != z) { #ifdef DEBUG gmp_fprintf(stderr, "\t|E| * P is non-zero, %d is composite\n", n); #endif /* DEBUG */ is_prime = 0; break; } /* at this point, order/2 being a prime implies n is a prime -- * a recursive call to ecpp_test is used to test order/2 for primality */ mpz_div_ui(tmp, tmp, 2); if (ecpp_test(mpz_get_ui(tmp))) { is_prime = 1; break; } } cleanup_and_return: mpz_clear(a); mpz_clear(b); mpz_clear(x0); mpz_clear(y0); mpz_clear(xt); mpz_clear(yt); mpz_clear(tmp); return is_prime; }
/*------------------------------------------------------------------------*/ uint32 handle_collision(poly_coeff_t *c, uint64 p, uint32 special_q, uint64 special_q_root, int64 res) { /* the proposed rational coefficient is p*special_q; p and special_q must be coprime. The 'trivial special q' has special_q = 1 and special_q_root = 0 */ uint64_2gmp(p, c->p); mpz_gcd_ui(c->tmp1, c->p, special_q); if (mpz_cmp_ui(c->tmp1, 1)) return 0; mpz_mul_ui(c->p, c->p, (unsigned long)special_q); /* the corresponding correction to trans_m0 is special_q_root + res * special_q^2, and can be positive or negative */ uint64_2gmp(special_q_root, c->tmp1); int64_2gmp(res, c->tmp2); mpz_set_ui(c->tmp3, special_q); mpz_mul(c->tmp3, c->tmp3, c->tmp3); mpz_addmul(c->tmp1, c->tmp2, c->tmp3); mpz_add(c->m, c->trans_m0, c->tmp1); /* a lot can go wrong before this function is called! Check that Kleinjung's modular condition is satisfied */ mpz_pow_ui(c->tmp1, c->m, c->degree); mpz_mul(c->tmp2, c->p, c->p); mpz_sub(c->tmp1, c->trans_N, c->tmp1); mpz_tdiv_r(c->tmp3, c->tmp1, c->tmp2); if (mpz_cmp_ui(c->tmp3, 0)) { gmp_printf("crap %Zd %Zd %Zd\n", c->high_coeff, c->p, c->m); return 0; } /* the pair works, now translate the computed m back to the original polynomial. We have computed_m = degree * high_coeff * real_m + (second_highest_coeff) * p and need to solve for real_m and second_highest_coeff. Per the CADO code: reducing the above modulo degree*high_coeff causes the first term on the right to disappear, so second_highest_coeff can be found modulo degree*high_coeff and real_m then follows */ mpz_mul_ui(c->tmp1, c->high_coeff, c->degree); mpz_tdiv_r(c->tmp2, c->m, c->tmp1); mpz_invert(c->tmp3, c->p, c->tmp1); mpz_mul(c->tmp2, c->tmp3, c->tmp2); mpz_tdiv_r(c->tmp2, c->tmp2, c->tmp1); /* make second_highest_coeff as small as possible in absolute value */ mpz_tdiv_q_2exp(c->tmp3, c->tmp1, 1); if (mpz_cmp(c->tmp2, c->tmp3) > 0) { mpz_sub(c->tmp2, c->tmp2, c->tmp1); } /* solve for real_m */ mpz_submul(c->m, c->tmp2, c->p); mpz_tdiv_q(c->m, c->m, c->tmp1); return 1; }
void subtract_multiple(ElementType& result, const ElementType& a, const ElementType& b) const { mpz_submul(&result, &a, &b); }
Integer& Integer::maxpyin(Integer& res, const Integer& a, const Integer& x) { if (isZero(a) || isZero(x)) return res; mpz_submul( (mpz_ptr)&res.gmp_rep, (mpz_srcptr)&a.gmp_rep, (mpz_srcptr)&x.gmp_rep); return res; }