poly_t * poly_syndrome_init(poly_t generator, gf_t *support, int n) { int i,j,t; gf_t a; poly_t * F; F = malloc(n * sizeof (poly_t)); t = poly_deg(generator); //g(z)=g_t+g_(t-1).z^(t-1)+......+g_1.z+g_0 //f(z)=f_(t-1).z^(t-1)+......+f_1.z+f_0 for(j=0; j<n; j++) { F[j] = poly_alloc(t-1); poly_set_coeff(F[j],t-1,gf_unit()); for(i=t-2; i>=0; i--) { poly_set_coeff(F[j],i,gf_add(poly_coeff(generator,i+1), gf_mul(support[j],poly_coeff(F[j],i+1)))); } a = gf_add(poly_coeff(generator,0),gf_mul(support[j],poly_coeff(F[j],0))); for(i=0; i<t; i++) { poly_set_coeff(F[j],i, gf_div(poly_coeff(F[j],i),a)); } } return F; }
// le corps est déjà défini // retourne un polynôme unitaire de degré t irreductible dans le corps poly_t poly_randgen_irred(int t, int (*u8rnd)()) { int i; poly_t g; g = poly_alloc(t); poly_set_deg(g, t); poly_set_coeff(g, t, gf_unit()); i = 0; do for (i = 0; i < t; ++i) poly_set_coeff(g, i, gf_rand(u8rnd)); while (poly_degppf(g) < t); return g; }
/* Subtract two polynomials */ poly_t *poly_diff(poly_t *p, poly_t *q) { int n = MAX(p->n, q->n); poly_t *r = poly_new(n); int i; for (i = 0; i < n + 1; i++) { double c = poly_get_coeff(p, i) - poly_get_coeff(q, i); poly_set_coeff(r, i, c); } return r; }
poly_t * poly_sqrtmod_init(poly_t g) { int i, t; poly_t * sqrt, aux, p, q, * sq_aux; t = poly_deg(g); sq_aux = malloc(t * sizeof (poly_t)); for (i = 0; i < t; ++i) sq_aux[i] = poly_alloc(t - 1); poly_sqmod_init(g, sq_aux); q = poly_alloc(t - 1); p = poly_alloc(t - 1); poly_set_deg(p, 1); poly_set_coeff(p, 1, gf_unit()); // q(z) = 0, p(z) = z for (i = 0; i < t * gf_extd() - 1; ++i) { // q(z) <- p(z)^2 mod g(z) poly_sqmod(q, p, sq_aux, t); // q(z) <-> p(z) aux = q; q = p; p = aux; } // p(z) = z^(2^(tm-1)) mod g(z) = sqrt(z) mod g(z) sqrt = malloc(t * sizeof (poly_t)); for (i = 0; i < t; ++i) sqrt[i] = poly_alloc(t - 1); poly_set(sqrt[1], p); poly_calcule_deg(sqrt[1]); for(i = 3; i < t; i += 2) { poly_set(sqrt[i], sqrt[i - 2]); poly_shiftmod(sqrt[i], g); poly_calcule_deg(sqrt[i]); } for (i = 0; i < t; i += 2) { poly_set_to_zero(sqrt[i]); sqrt[i]->coeff[i / 2] = gf_unit(); sqrt[i]->deg = i / 2; } for (i = 0; i < t; ++i) poly_free(sq_aux[i]); free(sq_aux); poly_free(p); poly_free(q); return sqrt; }
poly_t poly_quo(poly_t p, poly_t d) { int i, j, dd, dp; gf_t a, b; poly_t quo, rem; dd = poly_calcule_deg(d); dp = poly_calcule_deg(p); rem = poly_copy(p); quo = poly_alloc(dp - dd); poly_set_deg(quo, dp - dd); a = gf_inv(poly_coeff(d, dd)); for (i = dp; i >= dd; --i) { b = gf_mul_fast(a, poly_coeff(rem, i)); poly_set_coeff(quo, i - dd, b); if (b != gf_zero()) { poly_set_coeff(rem, i, gf_zero()); for (j = i - 1; j >= i - dd; --j) poly_addto_coeff(rem, j, gf_mul_fast(b, poly_coeff(d, dd - i + j))); } } poly_free(rem); return quo; }
// retourne le degré du plus petit facteur int poly_degppf(poly_t g) { int i, d, res; poly_t *u, p, r, s; d = poly_deg(g); u = malloc(d * sizeof (poly_t *)); for (i = 0; i < d; ++i) u[i] = poly_alloc(d + 1); poly_sqmod_init(g, u); p = poly_alloc(d - 1); poly_set_deg(p, 1); poly_set_coeff(p, 1, gf_unit()); r = poly_alloc(d - 1); res = d; for (i = 1; i <= (d / 2) * gf_extd(); ++i) { poly_sqmod(r, p, u, d); // r = x^(2^i) mod g if ((i % gf_extd()) == 0) { // donc 2^i = (2^m)^j (m deg d'extension) poly_addto_coeff(r, 1, gf_unit()); poly_calcule_deg(r); // le degré peut changer s = poly_gcd(g, r); if (poly_deg(s) > 0) { poly_free(s); res = i / gf_extd(); break; } poly_free(s); poly_addto_coeff(r, 1, gf_unit()); poly_calcule_deg(r); // le degré peut changer } // on se sert de s pour l'échange s = p; p = r; r = s; } poly_free(p); poly_free(r); for (i = 0; i < d; ++i) { poly_free(u[i]); } free(u); return res; }
// Returns the degree of the smallest factor int poly_degppf(poly_t g) { int i, d, res; poly_t *u, p, r, s; d = poly_deg(g); u = malloc(d * sizeof (poly_t *)); for (i = 0; i < d; ++i) u[i] = poly_alloc(d + 1); poly_sqmod_init(g, u); p = poly_alloc(d - 1); poly_set_deg(p, 1); poly_set_coeff(p, 1, gf_unit()); r = poly_alloc(d - 1); res = d; for (i = 1; i <= (d / 2) * gf_extd(); ++i) { poly_sqmod(r, p, u, d); // r = x^(2^i) mod g if ((i % gf_extd()) == 0) { // so 2^i = (2^m)^j (m ext. degree) poly_addto_coeff(r, 1, gf_unit()); poly_calcule_deg(r); // The degree may change s = poly_gcd(g, r); if (poly_deg(s) > 0) { poly_free(s); res = i / gf_extd(); break; } poly_free(s); poly_addto_coeff(r, 1, gf_unit()); poly_calcule_deg(r); // The degree may change } // No need for the exchange s s = p; p = r; r = s; } poly_free(p); poly_free(r); for (i = 0; i < d; ++i) { poly_free(u[i]); } free(u); return res; }
void poly_sqmod_init(poly_t g, poly_t * sq) { int i, d; d = poly_deg(g); for (i = 0; i < d / 2; ++i) { // sq[i] = x^(2i) mod g = x^(2i) poly_set_to_zero(sq[i]); poly_set_deg(sq[i], 2 * i); poly_set_coeff(sq[i], 2 * i, gf_unit()); } for (; i < d; ++i) { // sq[i] = x^(2i) mod g = (x^2 * sq[i-1]) mod g memset(sq[i]->coeff, 0, 2 * sizeof (gf_t)); memcpy(sq[i]->coeff + 2, sq[i - 1]->coeff, d * sizeof (gf_t)); poly_set_deg(sq[i], poly_deg(sq[i - 1]) + 2); poly_rem(sq[i], g); } }
// p contiendra son reste modulo g void poly_rem(poly_t p, poly_t g) { int i, j, d; gf_t a, b; d = poly_deg(p) - poly_deg(g); if (d >= 0) { a = gf_inv(poly_tete(g)); for (i = poly_deg(p); d >= 0; --i, --d) { if (poly_coeff(p, i) != gf_zero()) { b = gf_mul_fast(a, poly_coeff(p, i)); for (j = 0; j < poly_deg(g); ++j) poly_addto_coeff(p, j + d, gf_mul_fast(b, poly_coeff(g, j))); poly_set_coeff(p, i, gf_zero()); } } poly_set_deg(p, poly_deg(g) - 1); while ((poly_deg(p) >= 0) && (poly_coeff(p, poly_deg(p)) == gf_zero())) poly_set_deg(p, poly_deg(p) - 1); } }
// carré de p modulo un certain polynôme g, sq[] contient les carrés // modulo g de la base canonique des polynômes de degré < d, où d est // le degré de g. La table sq[] sera calculée par poly_sqmod_init() void poly_sqmod(poly_t res, poly_t p, poly_t * sq, int d) { int i, j; gf_t a; poly_set_to_zero(res); // termes de bas degré for (i = 0; i < d / 2; ++i) poly_set_coeff(res, i * 2, gf_square(poly_coeff(p, i))); // termes de haut degré for (; i < d; ++i) { if (poly_coeff(p, i) != gf_zero()) { a = gf_square(poly_coeff(p, i)); for (j = 0; j < d; ++j) poly_addto_coeff(res, j, gf_mul_fast(a, poly_coeff(sq[i], j))); } } // mise à jour du degré poly_set_deg(res, d - 1); while ((poly_deg(res) >= 0) && (poly_coeff(res, poly_deg(res)) == gf_zero())) poly_set_deg(res, poly_deg(res) - 1); }
void poly_sqmod(poly_t res, poly_t p, poly_t * sq, int d) { int i, j; gf_t a; poly_set_to_zero(res); // terms of low degree for (i = 0; i < d / 2; ++i) poly_set_coeff(res, i * 2, gf_square(poly_coeff(p, i))); // terms of high degree for (; i < d; ++i) { if (poly_coeff(p, i) != gf_zero()) { a = gf_square(poly_coeff(p, i)); for (j = 0; j < d; ++j) poly_addto_coeff(res, j, gf_mul_fast(a, poly_coeff(sq[i], j))); } } // Update degre poly_set_deg(res, d - 1); while ((poly_deg(res) >= 0) && (poly_coeff(res, poly_deg(res)) == gf_zero())) poly_set_deg(res, poly_deg(res) - 1); }
int main(void) { field_t fp, fx; mpz_t prime; darray_t list; int p = 7; // Exercise poly_is_irred() with a sieve of Erastosthenes for polynomials. darray_init(list); mpz_init(prime); mpz_set_ui(prime, p); field_init_fp(fp, prime); field_init_poly(fx, fp); element_t e; element_init(e, fp); // Enumerate polynomials in F_p[x] up to degree 2. int a[3], d; a[0] = a[1] = a[2] = 0; for(;;) { element_ptr f = pbc_malloc(sizeof(*f)); element_init(f, fx); int j; for(j = 0; j < 3; j++) { element_set_si(e, a[j]); poly_set_coeff(f, e, j); } // Test poly_degree(). for(j = 2; !a[j] && j >= 0; j--); EXPECT(poly_degree(f) == j); // Add monic polynomials to the list. if (j >= 0 && a[j] == 1) darray_append(list, f); else { element_clear(f); free(f); } // Next! d = 0; for(;;) { a[d]++; if (a[d] >= p) { a[d] = 0; d++; if (d > 2) goto break2; } else break; } } break2: ; // Find all composite monic polynomials of degree 3 or less. darray_t prodlist; darray_init(prodlist); void outer(void *data) { element_ptr f = data; void inner(void *data2) { element_ptr g = data2; if (!poly_degree(f) || !poly_degree(g)) return; if (poly_degree(f) + poly_degree(g) > 3) return; element_ptr h = pbc_malloc(sizeof(*h)); element_init(h, fx); element_mul(h, f, g); darray_append(prodlist, h); EXPECT(!poly_is_irred(h)); }
// On suppose deg(g) >= deg(p) void poly_eeaux(poly_t * u, poly_t * v, poly_t p, poly_t g, int t) { int i, j, dr, du, delta; gf_t a; poly_t aux, r0, r1, u0, u1; // initialisation des variables locales // r0 <- g, r1 <- p, u0 <- 0, u1 <- 1 dr = poly_deg(g); r0 = poly_alloc(dr); r1 = poly_alloc(dr - 1); u0 = poly_alloc(dr - 1); u1 = poly_alloc(dr - 1); poly_set(r0, g); poly_set(r1, p); poly_set_to_zero(u0); poly_set_to_zero(u1); poly_set_coeff(u1, 0, gf_unit()); poly_set_deg(u1, 0); // invariants: // r1 = u1 * p + v1 * g // r0 = u0 * p + v0 * g // et deg(u1) = deg(g) - deg(r0) // on s'arrête lorsque deg(r1) < t (et deg(r0) >= t) // et donc deg(u1) = deg(g) - deg(r0) < deg(g) - t du = 0; dr = poly_deg(r1); delta = poly_deg(r0) - dr; while (dr >= t) { for (j = delta; j >= 0; --j) { a = gf_div(poly_coeff(r0, dr + j), poly_coeff(r1, dr)); if (a != gf_zero()) { // u0(z) <- u0(z) + a * u1(z) * z^j for (i = 0; i <= du; ++i) { poly_addto_coeff(u0, i + j, gf_mul_fast(a, poly_coeff(u1, i))); } // r0(z) <- r0(z) + a * r1(z) * z^j for (i = 0; i <= dr; ++i) poly_addto_coeff(r0, i + j, gf_mul_fast(a, poly_coeff(r1, i))); } } // échanges aux = r0; r0 = r1; r1 = aux; aux = u0; u0 = u1; u1 = aux; du = du + delta; delta = 1; while (poly_coeff(r1, dr - delta) == gf_zero()) delta++; dr -= delta; } poly_set_deg(u1, du); poly_set_deg(r1, dr); //return u1 and r1; *u=u1; *v=r1; poly_free(r0); poly_free(u0); }