void _pq_nmod_insure_dual(const pq_nmod_elt_t x, const pq_nmod_t A) { if (nmod_poly_is_zero(x->dual) && !nmod_poly_is_zero(x->mono)) { pq_nmod_elt_struct* tmp = (pq_nmod_elt_struct*)x; nmod_poly_fit_length(tmp->dual, nmod_poly_degree(A->M)); nmod_poly_tmulmod(tmp->dual->coeffs, A->newton->coeffs, x->mono, A->M, A->S); tmp->dual->length = nmod_poly_degree(A->M); } }
void embeddings_isomorphism_inverse(mp_ptr F, const nmod_poly_t G, const embeddings_t FP, const embeddings_t FQ, const embeddings_t FR){ long m = nmod_poly_degree(FP->P); long n = nmod_poly_degree(FQ->P); mp_ptr ell = _nmod_vec_init(m*n); nmod_poly_tmulmod(ell, FR->TP->coeffs, G, FR->P, FR->SP); mp_ptr Ftrace = _nmod_vec_init(m*n); embeddings_tisomorphism(Ftrace, ell, FP, FQ, FR); nmod_poly_convert_from_trace_bi(F, Ftrace, FP->P, FP->iP, FQ->P, FQ->iP); _nmod_vec_clear(Ftrace); _nmod_vec_clear(ell); }
void embeddings_isomorphism(nmod_poly_t G, mp_srcptr F, const embeddings_t FP, const embeddings_t FQ, const embeddings_t FR){ long m = nmod_poly_degree(FP->P); long n = nmod_poly_degree(FQ->P); long i; nmod_poly_t tmpF, tmpG, S, X; nmod_t mod = FP->P->mod; nmod_poly_init(tmpF, mod.n); nmod_poly_init(tmpG, mod.n); nmod_poly_init(S, mod.n); nmod_poly_init(X, mod.n); nmod_poly_zero(G); nmod_poly_zero(X); nmod_poly_set_coeff_ui(X, 1, 1); embeddings_embed(S, X, FP, FQ, FR); for (i = m-1; i >= 0; i--){ nmod_poly_fit_length(tmpF, n); long j; long offset = i*n; for (j = 0; j < n; j++) tmpF->coeffs[j] = F[offset+j]; tmpF->length = n; _nmod_poly_normalise(tmpF); embeddings_embed(tmpG, tmpF, FQ, FP, FR); nmod_poly_mulmod(G, G, S, FR->P); nmod_poly_add(G, G, tmpG); } nmod_poly_clear(tmpF); nmod_poly_clear(tmpG); nmod_poly_clear(X); nmod_poly_clear(S); }
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); }
void embeddings_isomorphism_2(nmod_poly_t G, mp_srcptr F, const embeddings_t FP, const embeddings_t FQ, const embeddings_t FR){ nmod_t mod = G->mod; long m = nmod_poly_degree(FP->P); long n = nmod_poly_degree(FQ->P); long np = n + m - 1; long p = ceil(sqrt(np)); long q = ceil((1.0*np)/p); long i, j, k; nmod_poly_t iT, iTm, T, X, tmp; nmod_poly_struct *TT; nmod_poly_init(iTm, mod.n); nmod_poly_init(iT, mod.n); nmod_poly_init(T, mod.n); nmod_poly_init(X, mod.n); nmod_poly_init(tmp, mod.n); nmod_poly_mat_t MT, MH, MV; nmod_poly_mat_init(MT, q, n, mod.n); nmod_poly_mat_init(MH, p, q, mod.n); nmod_poly_mat_init(MV, p, n, mod.n); TT = flint_malloc(sizeof(nmod_poly_struct) * (q+1)); for (i = 0; i < q+1; i++) nmod_poly_init(TT+i, mod.n); nmod_poly_set_coeff_ui(X, 1, 1); embeddings_embed(T, X, FQ, FP, FR); nmod_poly_invmod(iT, T, FR->P); nmod_poly_powmod_ui_binexp(iTm, iT, m-1, FR->P); nmod_poly_zero(TT); nmod_poly_set_coeff_ui(TT, 0, 1); for (i = 1; i < q+1; i++) nmod_poly_mulmod(TT+i, TT+(i-1), T, FR->P); for (i = 0; i < q; i++) for (j = 0; j < n; j++){ long jm = j*m; for (k = 0; k < m; k++) nmod_poly_set_coeff_ui(nmod_poly_mat_entry(MT, i, j), k, nmod_poly_get_coeff_ui(TT+i, k+jm)); } for (i = 0; i < p; i++) for (j = 0; j < q; j++){ long idx = i*q+j; long lo = FLINT_MAX(0,m-1-idx); long hi = FLINT_MIN(m,n+m-1-idx); for (k = lo; k < hi; k++) nmod_poly_set_coeff_ui(nmod_poly_mat_entry(MH, i, j), k, F[k*n+k+idx-m+1]); } nmod_poly_mat_mul(MV, MH, MT); nmod_poly_zero(G); for (i = p-1; i >= 0; i--){ nmod_poly_zero(tmp); for (j = 0; j < n; j++){ long len = nmod_poly_mat_entry(MV, i, j)->length; mp_ptr coefs = nmod_poly_mat_entry(MV, i, j)->coeffs; long jm = j*m; for (k = 0; k < len; k++) nmod_poly_set_coeff_ui(tmp, k+jm, n_addmod(nmod_poly_get_coeff_ui(tmp, k+jm), coefs[k], mod.n)); } nmod_poly_rem(tmp, tmp, FR->P); nmod_poly_mulmod(G, G, TT+q, FR->P); nmod_poly_add(G, G, tmp); } nmod_poly_mulmod(G, G, iTm, FR->P); nmod_poly_clear(tmp); nmod_poly_mat_clear(MT); nmod_poly_mat_clear(MH); nmod_poly_mat_clear(MV); for (i = 0; i < q+1; i++) nmod_poly_clear(TT+i); flint_free(TT); nmod_poly_clear(iTm); nmod_poly_clear(iT); nmod_poly_clear(T); nmod_poly_clear(X); }