void nmod_poly_factor_cantor_zassenhaus(nmod_poly_factor_t res, const nmod_poly_t f) { nmod_poly_t h, v, g, x; slong i, j, num; nmod_poly_init_preinv(h, f->mod.n, f->mod.ninv); nmod_poly_init_preinv(g, f->mod.n, f->mod.ninv); nmod_poly_init_preinv(v, f->mod.n, f->mod.ninv); nmod_poly_init_preinv(x, f->mod.n, f->mod.ninv); nmod_poly_set_coeff_ui(h, 1, 1); nmod_poly_set_coeff_ui(x, 1, 1); nmod_poly_make_monic(v, f); i = 0; do { i++; nmod_poly_powmod_ui_binexp(h, h, f->mod.n, v); nmod_poly_sub(h, h, x); nmod_poly_gcd(g, h, v); nmod_poly_add(h, h, x); if (g->length != 1) { nmod_poly_make_monic(g, g); num = res->num; nmod_poly_factor_equal_deg(res, g, i); for (j = num; j < res->num; j++) res->exp[j] = nmod_poly_remove(v, res->p + j); } } while (v->length >= 2*i + 3); if (v->length > 1) nmod_poly_factor_insert(res, v, 1); nmod_poly_clear(g); nmod_poly_clear(h); nmod_poly_clear(v); nmod_poly_clear(x); }
int main (void) { double t; nmod_poly_t f, g, h; for (int i= 15001;i < 16000; i++) { nmod_poly_init2 (f, 17, i/2+1); nmod_poly_init2 (g, 17, i+1); nmod_poly_set_coeff_ui (f, i/2, 1); nmod_poly_set_coeff_ui (f, 1, 1); nmod_poly_set_coeff_ui (f, 0, ((i%17)*(i%17)+3) % 17); nmod_poly_set_coeff_ui (g, i, 1); nmod_poly_set_coeff_ui (g, i/2+1, 1); nmod_poly_set_coeff_ui (g, 1, ((i % 17)+1)%17); nmod_poly_set_coeff_ui (g, 0, 15); nmod_poly_init (h, 17); nmod_poly_gcd (h, f, g); if (!nmod_poly_is_one (h)) { flint_printf ("i= %d\n", i); nmod_poly_factor_t factors; nmod_poly_factor_init (factors); t= clock(); nmod_poly_factor (factors, h); t = (clock() - t) / CLOCKS_PER_SEC; flint_printf("factorization %.2lf\n", t); nmod_poly_factor_clear (factors); } nmod_poly_clear (f); nmod_poly_clear (g); nmod_poly_clear (h); } return EXIT_SUCCESS; }
void nmod_poly_factor_squarefree(nmod_poly_factor_t res, const nmod_poly_t f) { nmod_poly_t f_d, g, g_1; mp_limb_t p; slong deg, i; if (f->length <= 1) { res->num = 0; return; } if (f->length == 2) { nmod_poly_factor_insert(res, f, 1); return; } p = nmod_poly_modulus(f); deg = nmod_poly_degree(f); /* Step 1, look at f', if it is zero then we are done since f = h(x)^p for some particular h(x), clearly f(x) = sum a_k x^kp, k <= deg(f) */ nmod_poly_init(g_1, p); nmod_poly_init(f_d, p); nmod_poly_init(g, p); nmod_poly_derivative(f_d, f); /* Case 1 */ if (nmod_poly_is_zero(f_d)) { nmod_poly_factor_t new_res; nmod_poly_t h; nmod_poly_init(h, p); for (i = 0; i <= deg / p; i++) /* this will be an integer since f'=0 */ { nmod_poly_set_coeff_ui(h, i, nmod_poly_get_coeff_ui(f, i * p)); } /* Now run square-free on h, and return it to the pth power */ nmod_poly_factor_init(new_res); nmod_poly_factor_squarefree(new_res, h); nmod_poly_factor_pow(new_res, p); nmod_poly_factor_concat(res, new_res); nmod_poly_clear(h); nmod_poly_factor_clear(new_res); } else { nmod_poly_t h, z; nmod_poly_gcd(g, f, f_d); nmod_poly_div(g_1, f, g); i = 1; nmod_poly_init(h, p); nmod_poly_init(z, p); /* Case 2 */ while (!nmod_poly_is_one(g_1)) { nmod_poly_gcd(h, g_1, g); nmod_poly_div(z, g_1, h); /* out <- out.z */ if (z->length > 1) { nmod_poly_factor_insert(res, z, 1); nmod_poly_make_monic(res->p + (res->num - 1), res->p + (res->num - 1)); if (res->num) res->exp[res->num - 1] *= i; } i++; nmod_poly_set(g_1, h); nmod_poly_div(g, g, h); } nmod_poly_clear(h); nmod_poly_clear(z); nmod_poly_make_monic(g, g); if (!nmod_poly_is_one(g)) { /* so now we multiply res with square-free(g^1/p) ^ p */ nmod_poly_t g_p; /* g^(1/p) */ nmod_poly_factor_t new_res_2; nmod_poly_init(g_p, p); for (i = 0; i <= nmod_poly_degree(g) / p; i++) nmod_poly_set_coeff_ui(g_p, i, nmod_poly_get_coeff_ui(g, i*p)); nmod_poly_factor_init(new_res_2); /* square-free(g^(1/p)) */ nmod_poly_factor_squarefree(new_res_2, g_p); nmod_poly_factor_pow(new_res_2, p); nmod_poly_factor_concat(res, new_res_2); nmod_poly_clear(g_p); nmod_poly_factor_clear(new_res_2); } } nmod_poly_clear(g_1); nmod_poly_clear(f_d); nmod_poly_clear(g); }
int main(void) { int i, result; flint_rand_t state; flint_randinit(state); printf("xgcd_hgcd...."); fflush(stdout); /* Compare with result from gcd and check a*s + b*t = g */ for (i = 0; i < 1000; i++) { nmod_poly_t a, b, c, g1, g2, s, t, sum, temp; mp_limb_t n; do n = n_randtest_not_zero(state); while (!n_is_probabprime(n)); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(c, n); nmod_poly_init(g1, n); nmod_poly_init(g2, n); nmod_poly_init(s, n); nmod_poly_init(t, n); nmod_poly_init(sum, n); nmod_poly_init(temp, n); nmod_poly_randtest(a, state, n_randint(state, 600)); nmod_poly_randtest(b, state, n_randint(state, 600)); nmod_poly_randtest(c, state, n_randint(state, 400)); nmod_poly_mul(a, a, c); nmod_poly_mul(b, b, c); nmod_poly_gcd(g1, a, b); nmod_poly_xgcd_hgcd(g2, s, t, a, b); nmod_poly_mul(sum, s, a); nmod_poly_mul(temp, t, b); nmod_poly_add(sum, sum, temp); result = (nmod_poly_equal(g1, g2) && nmod_poly_equal(g1, sum) && (g1->length == 0 || g1->coeffs[g1->length - 1] == 1)); if (!result) { printf("FAIL:\n"); nmod_poly_print(a), printf("\n\n"); nmod_poly_print(b), printf("\n\n"); nmod_poly_print(c), printf("\n\n"); nmod_poly_print(g1), printf("\n\n"); nmod_poly_print(g2), printf("\n\n"); nmod_poly_print(sum), printf("\n\n"); nmod_poly_print(s), printf("\n\n"); nmod_poly_print(t), printf("\n\n"); printf("n = %ld\n", n); abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(c); nmod_poly_clear(g1); nmod_poly_clear(g2); nmod_poly_clear(s); nmod_poly_clear(t); nmod_poly_clear(sum); nmod_poly_clear(temp); } /* Check aliasing of a and g */ for (i = 0; i < 200; i++) { nmod_poly_t a, b, g, s, t; mp_limb_t n; do n = n_randtest(state); while (!n_is_probabprime(n)); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(g, n); nmod_poly_init(s, n); nmod_poly_init(t, n); nmod_poly_randtest(a, state, n_randint(state, 200)); nmod_poly_randtest(b, state, n_randint(state, 200)); nmod_poly_xgcd_hgcd(g, s, t, a, b); nmod_poly_xgcd_hgcd(a, s, t, a, b); result = (nmod_poly_equal(a, g)); if (!result) { printf("FAIL:\n"); nmod_poly_print(a), printf("\n\n"); nmod_poly_print(b), printf("\n\n"); nmod_poly_print(g), printf("\n\n"); printf("n = %ld\n", n); abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(g); nmod_poly_clear(s); nmod_poly_clear(t); } /* Check aliasing of b and g */ for (i = 0; i < 200; i++) { nmod_poly_t a, b, g, s, t; mp_limb_t n; do n = n_randtest(state); while (!n_is_probabprime(n)); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(g, n); nmod_poly_init(s, n); nmod_poly_init(t, n); nmod_poly_randtest(a, state, n_randint(state, 200)); nmod_poly_randtest(b, state, n_randint(state, 200)); nmod_poly_xgcd_hgcd(g, s, t, a, b); nmod_poly_xgcd_hgcd(b, s, t, a, b); result = (nmod_poly_equal(b, g)); if (!result) { printf("FAIL:\n"); nmod_poly_print(a), printf("\n\n"); nmod_poly_print(b), printf("\n\n"); nmod_poly_print(g), printf("\n\n"); printf("n = %ld\n", n); abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(g); nmod_poly_clear(s); nmod_poly_clear(t); } /* Check aliasing of s and a */ for (i = 0; i < 200; i++) { nmod_poly_t a, b, g, s, t; mp_limb_t n; do n = n_randtest(state); while (!n_is_probabprime(n)); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(g, n); nmod_poly_init(s, n); nmod_poly_init(t, n); nmod_poly_randtest(a, state, n_randint(state, 200)); nmod_poly_randtest(b, state, n_randint(state, 200)); nmod_poly_xgcd_hgcd(g, s, t, a, b); nmod_poly_xgcd_hgcd(g, a, t, a, b); result = (nmod_poly_equal(s, a)); if (!result) { printf("FAIL:\n"); nmod_poly_print(a), printf("\n\n"); nmod_poly_print(s), printf("\n\n"); printf("n = %ld\n", n); abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(g); nmod_poly_clear(s); nmod_poly_clear(t); } /* Check aliasing of s and b */ for (i = 0; i < 200; i++) { nmod_poly_t a, b, g, s, t; mp_limb_t n; do n = n_randtest(state); while (!n_is_probabprime(n)); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(g, n); nmod_poly_init(s, n); nmod_poly_init(t, n); nmod_poly_randtest(a, state, n_randint(state, 200)); nmod_poly_randtest(b, state, n_randint(state, 200)); nmod_poly_xgcd_hgcd(g, s, t, a, b); nmod_poly_xgcd_hgcd(g, b, t, a, b); result = (nmod_poly_equal(s, b)); if (!result) { printf("FAIL:\n"); nmod_poly_print(b), printf("\n\n"); nmod_poly_print(s), printf("\n\n"); printf("n = %ld\n", n); abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(g); nmod_poly_clear(s); nmod_poly_clear(t); } /* Check aliasing of t and a */ for (i = 0; i < 200; i++) { nmod_poly_t a, b, g, s, t; mp_limb_t n; do n = n_randtest(state); while (!n_is_probabprime(n)); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(g, n); nmod_poly_init(s, n); nmod_poly_init(t, n); nmod_poly_randtest(a, state, n_randint(state, 200)); nmod_poly_randtest(b, state, n_randint(state, 200)); nmod_poly_xgcd_hgcd(g, s, t, a, b); nmod_poly_xgcd_hgcd(g, s, a, a, b); result = (nmod_poly_equal(t, a)); if (!result) { printf("FAIL:\n"); nmod_poly_print(a), printf("\n\n"); nmod_poly_print(t), printf("\n\n"); printf("n = %ld\n", n); abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(g); nmod_poly_clear(s); nmod_poly_clear(t); } /* Check aliasing of t and b */ for (i = 0; i < 200; i++) { nmod_poly_t a, b, g, s, t; mp_limb_t n; do n = n_randtest(state); while (!n_is_probabprime(n)); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(g, n); nmod_poly_init(s, n); nmod_poly_init(t, n); nmod_poly_randtest(a, state, n_randint(state, 200)); nmod_poly_randtest(b, state, n_randint(state, 200)); nmod_poly_xgcd_hgcd(g, s, t, a, b); nmod_poly_xgcd_hgcd(g, s, b, a, b); result = (nmod_poly_equal(t, b)); if (!result) { printf("FAIL:\n"); nmod_poly_print(b), printf("\n\n"); nmod_poly_print(t), printf("\n\n"); printf("n = %ld\n", n); abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(g); nmod_poly_clear(s); nmod_poly_clear(t); } flint_randclear(state); printf("PASS\n"); return 0; }