void nmod_poly_cosh_series(nmod_poly_t g, const nmod_poly_t h, long n) { mp_ptr g_coeffs, h_coeffs; nmod_poly_t t1; long h_len; h_len = h->length; if (h_len > 0 && h->coeffs[0] != 0UL) { printf("Exception: nmod_poly_cosh_series: constant term != 0\n"); abort(); } if (h_len == 1 || n < 2) { nmod_poly_zero(g); if (n > 0) nmod_poly_set_coeff_ui(g, 0, 1UL); return; } if (h_len < n) { h_coeffs = _nmod_vec_init(n); mpn_copyi(h_coeffs, h->coeffs, h_len); mpn_zero(h_coeffs + h_len, n - h_len); } else h_coeffs = h->coeffs; if (h == g && h_len >= n) { nmod_poly_init2(t1, h->mod.n, n); g_coeffs = t1->coeffs; } else { nmod_poly_fit_length(g, n); g_coeffs = g->coeffs; } _nmod_poly_cosh_series(g_coeffs, h_coeffs, n, h->mod); if (h == g && h_len >= n) { nmod_poly_swap(g, t1); nmod_poly_clear(t1); } g->length = n; if (h_len < n) _nmod_vec_free(h_coeffs); _nmod_poly_normalise(g); }
void nmod_poly_compose_series_horner(nmod_poly_t res, const nmod_poly_t poly1, const nmod_poly_t poly2, long n) { long len1 = poly1->length; long len2 = poly2->length; long lenr; if (len2 != 0 && poly2->coeffs[0] != 0) { printf("exception: nmod_poly_compose_series_horner: inner polynomial " "must have zero constant term\n"); abort(); } if (len1 == 0 || n == 0) { nmod_poly_zero(res); return; } if (len2 == 0 || len1 == 1) { nmod_poly_fit_length(res, 1); res->coeffs[0] = poly1->coeffs[0]; res->length = 1; _nmod_poly_normalise(res); return; } lenr = FLINT_MIN((len1 - 1) * (len2 - 1) + 1, n); len1 = FLINT_MIN(len1, lenr); len2 = FLINT_MIN(len2, lenr); if ((res != poly1) && (res != poly2)) { nmod_poly_fit_length(res, lenr); _nmod_poly_compose_series_horner(res->coeffs, poly1->coeffs, len1, poly2->coeffs, len2, lenr, res->mod); res->length = lenr; _nmod_poly_normalise(res); } else { nmod_poly_t t; nmod_poly_init2_preinv(t, res->mod.n, res->mod.ninv, lenr); _nmod_poly_compose_series_horner(t->coeffs, poly1->coeffs, len1, poly2->coeffs, len2, lenr, res->mod); t->length = lenr; _nmod_poly_normalise(t); nmod_poly_swap(res, t); nmod_poly_clear(t); } }
void nmod_poly_div_basecase(nmod_poly_t Q, const nmod_poly_t A, const nmod_poly_t B) { mp_ptr Q_coeffs, W; nmod_poly_t t1; long Alen, Blen; Blen = B->length; if (Blen == 0) { printf("Exception: division by zero in nmod_poly_div_basecase\n"); abort(); } Alen = A->length; if (Alen < Blen) { nmod_poly_zero(Q); return; } if (Q == A || Q == B) { nmod_poly_init2_preinv(t1, B->mod.n, B->mod.ninv, Alen - Blen + 1); Q_coeffs = t1->coeffs; } else { nmod_poly_fit_length(Q, Alen - Blen + 1); Q_coeffs = Q->coeffs; } W = _nmod_vec_init(NMOD_DIV_BC_ITCH(Alen, Blen, A->mod)); _nmod_poly_div_basecase(Q_coeffs, W, A->coeffs, Alen, B->coeffs, Blen, B->mod); if (Q == A || Q == B) { nmod_poly_swap(Q, t1); nmod_poly_clear(t1); } Q->length = Alen - Blen + 1; _nmod_vec_clear(W); _nmod_poly_normalise(Q); }
void nmod_poly_revert_series_lagrange(nmod_poly_t Qinv, const nmod_poly_t Q, long n) { mp_ptr Qinv_coeffs, Q_coeffs; nmod_poly_t t1; long Qlen; Qlen = Q->length; if (Qlen < 2 || Q->coeffs[0] != 0 || Q->coeffs[1] == 0) { printf("exception: nmod_poly_revert_series_lagrange: input must have " "zero constant and an invertible coefficient of x^1"); abort(); } if (Qlen < n) { Q_coeffs = _nmod_vec_init(n); mpn_copyi(Q_coeffs, Q->coeffs, Qlen); mpn_zero(Q_coeffs + Qlen, n - Qlen); } else Q_coeffs = Q->coeffs; if (Q == Qinv && Qlen >= n) { nmod_poly_init2(t1, Q->mod.n, n); Qinv_coeffs = t1->coeffs; } else { nmod_poly_fit_length(Qinv, n); Qinv_coeffs = Qinv->coeffs; } _nmod_poly_revert_series_lagrange(Qinv_coeffs, Q_coeffs, n, Q->mod); if (Q == Qinv && Qlen >= n) { nmod_poly_swap(Qinv, t1); nmod_poly_clear(t1); } Qinv->length = n; if (Qlen < n) _nmod_vec_clear(Q_coeffs); _nmod_poly_normalise(Qinv); }
void nmod_poly_inv_series_basecase(nmod_poly_t Qinv, const nmod_poly_t Q, long n) { mp_ptr Qinv_coeffs, Q_coeffs; nmod_poly_t t1; long Qlen; Qlen = Q->length; if (n == 0 || Q->length == 0 || Q->coeffs[0] == 0) { printf("Exception: division by zero in nmod_poly_inv_series_basecase\n"); abort(); } if (Qlen < n) { Q_coeffs = _nmod_vec_init(n); mpn_copyi(Q_coeffs, Q->coeffs, Qlen); mpn_zero(Q_coeffs + Qlen, n - Qlen); } else Q_coeffs = Q->coeffs; if (Q == Qinv && Qlen >= n) { nmod_poly_init2(t1, Q->mod.n, n); Qinv_coeffs = t1->coeffs; } else { nmod_poly_fit_length(Qinv, n); Qinv_coeffs = Qinv->coeffs; } _nmod_poly_inv_series_basecase(Qinv_coeffs, Q_coeffs, n, Q->mod); if (Q == Qinv && Qlen >= n) { nmod_poly_swap(Qinv, t1); nmod_poly_clear(t1); } Qinv->length = n; if (Qlen < n) _nmod_vec_free(Q_coeffs); _nmod_poly_normalise(Qinv); }
void nmod_poly_pow(nmod_poly_t res, const nmod_poly_t poly, ulong e) { const slong len = poly->length; slong rlen; if ((len < 2) | (e < UWORD(3))) { if (len == 0) nmod_poly_zero(res); else if (len == 1) { nmod_poly_fit_length(res, 1); res->coeffs[0] = n_powmod2_ui_preinv(poly->coeffs[0], e, poly->mod.n, poly->mod.ninv); res->length = 1; _nmod_poly_normalise(res); } else if (e == UWORD(0)) { nmod_poly_set_coeff_ui(res, 0, UWORD(1)); res->length = 1; _nmod_poly_normalise(res); } else if (e == UWORD(1)) nmod_poly_set(res, poly); else /* e == UWORD(2) */ nmod_poly_mul(res, poly, poly); return; } rlen = (slong) e * (len - 1) + 1; if (res != poly) { nmod_poly_fit_length(res, rlen); _nmod_poly_pow(res->coeffs, poly->coeffs, len, e, poly->mod); } else { nmod_poly_t t; nmod_poly_init2(t, poly->mod.n, rlen); _nmod_poly_pow(t->coeffs, poly->coeffs, len, e, poly->mod); nmod_poly_swap(res, t); nmod_poly_clear(t); } res->length = rlen; _nmod_poly_normalise(res); }
void nmod_poly_mulhigh(nmod_poly_t res, const nmod_poly_t poly1, const nmod_poly_t poly2, long n) { long len1, len2, len_out; len1 = poly1->length; len2 = poly2->length; len_out = poly1->length + poly2->length - 1; if (n > len_out) n = len_out; if (len1 == 0 || len2 == 0 || n == 0) { nmod_poly_zero(res); return; } if (res == poly1 || res == poly2) { nmod_poly_t temp; nmod_poly_init2(temp, poly1->mod.n, len_out); if (len1 >= len2) _nmod_poly_mulhigh(temp->coeffs, poly1->coeffs, len1, poly2->coeffs, len2, n, poly1->mod); else _nmod_poly_mulhigh(temp->coeffs, poly2->coeffs, len2, poly1->coeffs, len1, n, poly1->mod); nmod_poly_swap(temp, res); nmod_poly_clear(temp); } else { nmod_poly_fit_length(res, len_out); if (len1 >= len2) _nmod_poly_mulhigh(res->coeffs, poly1->coeffs, len1, poly2->coeffs, len2, n, poly1->mod); else _nmod_poly_mulhigh(res->coeffs, poly2->coeffs, len2, poly1->coeffs, len1, n, poly1->mod); } res->length = len_out; _nmod_poly_normalise(res); }
void nmod_poly_mullow_classical(nmod_poly_t res, const nmod_poly_t poly1, const nmod_poly_t poly2, slong trunc) { slong len_out; if (poly1->length == 0 || poly2->length == 0 || trunc == 0) { nmod_poly_zero(res); return; } len_out = poly1->length + poly2->length - 1; if (trunc > len_out) trunc = len_out; if (res == poly1 || res == poly2) { nmod_poly_t temp; nmod_poly_init2_preinv(temp, poly1->mod.n, poly1->mod.ninv, trunc); if (poly1->length >= poly2->length) _nmod_poly_mullow_classical(temp->coeffs, poly1->coeffs, poly1->length, poly2->coeffs, poly2->length, trunc, poly1->mod); else _nmod_poly_mullow_classical(temp->coeffs, poly2->coeffs, poly2->length, poly1->coeffs, poly1->length, trunc, poly1->mod); nmod_poly_swap(res, temp); nmod_poly_clear(temp); } else { nmod_poly_fit_length(res, trunc); if (poly1->length >= poly2->length) _nmod_poly_mullow_classical(res->coeffs, poly1->coeffs, poly1->length, poly2->coeffs, poly2->length, trunc, poly1->mod); else _nmod_poly_mullow_classical(res->coeffs, poly2->coeffs, poly2->length, poly1->coeffs, poly1->length, trunc, poly1->mod); } res->length = trunc; _nmod_poly_normalise(res); }
void nmod_poly_mullow_KS(nmod_poly_t res, const nmod_poly_t poly1, const nmod_poly_t poly2, mp_bitcnt_t bits, long n) { long len_out; if ((poly1->length == 0) || (poly2->length == 0)) { nmod_poly_zero(res); return; } len_out = poly1->length + poly2->length - 1; if (n > len_out) n = len_out; if (res == poly1 || res == poly2) { nmod_poly_t temp; nmod_poly_init2_preinv(temp, poly1->mod.n, poly1->mod.ninv, len_out); if (poly1->length >= poly2->length) _nmod_poly_mullow_KS(temp->coeffs, poly1->coeffs, poly1->length, poly2->coeffs, poly2->length, bits, n, poly1->mod); else _nmod_poly_mullow_KS(temp->coeffs, poly2->coeffs, poly2->length, poly1->coeffs, poly1->length, bits, n, poly1->mod); nmod_poly_swap(res, temp); nmod_poly_clear(temp); } else { nmod_poly_fit_length(res, len_out); if (poly1->length >= poly2->length) _nmod_poly_mullow_KS(res->coeffs, poly1->coeffs, poly1->length, poly2->coeffs, poly2->length, bits, n, poly1->mod); else _nmod_poly_mullow_KS(res->coeffs, poly2->coeffs, poly2->length, poly1->coeffs, poly1->length, bits, n, poly1->mod); } res->length = n; _nmod_poly_normalise(res); }
void nmod_poly_div_divconquer(nmod_poly_t Q, const nmod_poly_t A, const nmod_poly_t B) { nmod_poly_t tQ; mp_ptr q; long Alen, Blen; Blen = B->length; if (Blen == 0) { printf("Exception: division by zero in nmod_poly_div_divconquer\n"); abort(); } Alen = A->length; if (Alen < Blen) { nmod_poly_zero(Q); return; } if (Q == A || Q == B) { nmod_poly_init2(tQ, A->mod.n, Alen - Blen + 1); q = tQ->coeffs; } else { nmod_poly_fit_length(Q, Alen - Blen + 1); q = Q->coeffs; } _nmod_poly_div_divconquer(q, A->coeffs, Alen, B->coeffs, Blen, A->mod); if (Q == A || Q == B) { nmod_poly_swap(tQ, Q); nmod_poly_clear(tQ); } Q->length = Alen - Blen + 1; }
void nmod_poly_rem_basecase(nmod_poly_t R, const nmod_poly_t A, const nmod_poly_t B) { const long lenA = A->length, lenB = B->length; mp_ptr r, W; nmod_poly_t t; if (lenB == 0) { printf("Exception: division by zero in nmod_poly_rem_basecase\n"); abort(); } if (lenA < lenB) { nmod_poly_set(R, A); return; } if (R == A || R == B) { nmod_poly_init2_preinv(t, B->mod.n, B->mod.ninv, lenB - 1); r = t->coeffs; } else { nmod_poly_fit_length(R, lenB - 1); r = R->coeffs; } W = _nmod_vec_init(NMOD_DIVREM_BC_ITCH(lenA, lenB, A->mod)); _nmod_poly_rem_basecase(r, W, A->coeffs, lenA, B->coeffs, lenB, B->mod); if (R == A || R == B) { nmod_poly_swap(R, t); nmod_poly_clear(t); } R->length = lenB - 1; _nmod_vec_clear(W); _nmod_poly_normalise(R); }
void nmod_poly_compose_divconquer(nmod_poly_t res, const nmod_poly_t poly1, const nmod_poly_t poly2) { const long len1 = poly1->length; const long len2 = poly2->length; long lenr; if (len1 == 0) { nmod_poly_zero(res); return; } if (len1 == 1 || len2 == 0) { nmod_poly_set_coeff_ui(res, 0, poly1->coeffs[0]); nmod_poly_truncate(res, 1); return; } lenr = (len1 - 1) * (len2 - 1) + 1; if (res != poly1 && res != poly2) { nmod_poly_fit_length(res, lenr); _nmod_poly_compose_divconquer(res->coeffs, poly1->coeffs, len1, poly2->coeffs, len2, poly1->mod); } else { nmod_poly_t t; nmod_poly_init2(t, poly1->mod.n, lenr); _nmod_poly_compose_divconquer(t->coeffs, poly1->coeffs, len1, poly2->coeffs, len2, poly1->mod); nmod_poly_swap(res, t); nmod_poly_clear(t); } res->length = lenr; _nmod_poly_normalise(res); }
void nmod_poly_exp_series(nmod_poly_t f, const nmod_poly_t h, long n) { mp_ptr f_coeffs, h_coeffs; nmod_poly_t t1; long hlen, k; nmod_poly_fit_length(f, n); hlen = h->length; if (hlen > 0 && h->coeffs[0] != 0UL) { printf("Exception: nmod_poly_exp_series: constant term != 0\n"); abort(); } if (n <= 1 || hlen == 0) { if (n == 0) { nmod_poly_zero(f); } else { f->coeffs[0] = 1UL; f->length = 1; } return; } /* Handle monomials */ for (k = 0; h->coeffs[k] == 0UL && k < n - 1; k++); if (k == hlen - 1 || k == n - 1) { hlen = FLINT_MIN(hlen, n); _nmod_poly_exp_series_monomial_ui(f->coeffs, h->coeffs[hlen-1], hlen - 1, n, f->mod); f->length = n; _nmod_poly_normalise(f); return; } if (n < NMOD_NEWTON_EXP_CUTOFF2) { _nmod_poly_exp_series_basecase(f->coeffs, h->coeffs, hlen, n, f->mod); f->length = n; _nmod_poly_normalise(f); return; } if (hlen < n) { h_coeffs = _nmod_vec_init(n); mpn_copyi(h_coeffs, h->coeffs, hlen); mpn_zero(h_coeffs + hlen, n - hlen); } else h_coeffs = h->coeffs; if (h == f && hlen >= n) { nmod_poly_init2(t1, h->mod.n, n); f_coeffs = t1->coeffs; } else { nmod_poly_fit_length(f, n); f_coeffs = f->coeffs; } _nmod_poly_exp_series(f_coeffs, h_coeffs, n, f->mod); if (h == f && hlen >= n) { nmod_poly_swap(f, t1); nmod_poly_clear(t1); } f->length = n; if (hlen < n) _nmod_vec_free(h_coeffs); _nmod_poly_normalise(f); }
void nmod_poly_xgcd(nmod_poly_t G, nmod_poly_t S, nmod_poly_t T, const nmod_poly_t A, const nmod_poly_t B) { const long lenA = A->length, lenB = B->length; mp_limb_t inv; if (lenA == 0) { if (lenB == 0) { nmod_poly_zero(G); nmod_poly_zero(S); nmod_poly_zero(T); } else { inv = n_invmod(B->coeffs[lenB - 1], B->mod.n); nmod_poly_scalar_mul_nmod(G, B, inv); nmod_poly_zero(S); nmod_poly_set_coeff_ui(T, 0, inv); T->length = 1; } } else if (lenB == 0) { inv = n_invmod(A->coeffs[lenA - 1], A->mod.n); nmod_poly_scalar_mul_nmod(G, A, inv); nmod_poly_zero(T); nmod_poly_set_coeff_ui(S, 0, inv); S->length = 1; } else { nmod_poly_t tG, tS, tT; mp_ptr g, s, t; long lenG; if (G == A || G == B) { nmod_poly_init2(tG, A->mod.n, FLINT_MIN(lenA, lenB)); g = tG->coeffs; } else { nmod_poly_fit_length(G, FLINT_MIN(lenA, lenB)); g = G->coeffs; } if (S == A || S == B) { nmod_poly_init2(tS, A->mod.n, lenB - 1); s = tS->coeffs; } else { nmod_poly_fit_length(S, lenB - 1); s = S->coeffs; } if (T == A || T == B) { nmod_poly_init2(tT, A->mod.n, lenA - 1); t = tT->coeffs; } else { nmod_poly_fit_length(T, lenA - 1); t = T->coeffs; } if (lenA >= lenB) lenG = _nmod_poly_xgcd(g, s, t, A->coeffs, lenA, B->coeffs, lenB, A->mod); else lenG = _nmod_poly_xgcd(g, t, s, B->coeffs, lenB, A->coeffs, lenA, A->mod); if (G == A || G == B) { nmod_poly_swap(tG, G); nmod_poly_clear(tG); } if (S == A || S == B) { nmod_poly_swap(tS, S); nmod_poly_clear(tS); } if (T == A || T == B) { nmod_poly_swap(tT, T); nmod_poly_clear(tT); } G->length = lenG; S->length = lenB - lenG; T->length = lenA - lenG; MPN_NORM(S->coeffs, S->length); MPN_NORM(T->coeffs, T->length); if (G->coeffs[lenG - 1] != 1) { inv = n_invmod(G->coeffs[lenG - 1], A->mod.n); nmod_poly_scalar_mul_nmod(G, G, inv); nmod_poly_scalar_mul_nmod(S, S, inv); nmod_poly_scalar_mul_nmod(T, T, inv); } } }
void nmod_poly_compose_mod_horner(nmod_poly_t res, const nmod_poly_t poly1, const nmod_poly_t poly2, const nmod_poly_t poly3) { long len1 = poly1->length; long len2 = poly2->length; long len3 = poly3->length; long len = len3 - 1; mp_ptr ptr2; if (len3 == 0) { printf("exception: division by zero in nmod_poly_compose_mod_horner\n"); abort(); } if (len1 == 0 || len3 == 1) { nmod_poly_zero(res); return; } if (len1 == 1) { nmod_poly_set(res, poly1); return; } if (res == poly3 || res == poly1) { nmod_poly_t tmp; nmod_poly_init_preinv(tmp, res->mod.n, res->mod.ninv); nmod_poly_compose_mod_horner(tmp, poly1, poly2, poly3); nmod_poly_swap(tmp, res); nmod_poly_clear(tmp); return; } ptr2 = _nmod_vec_init(len); if (len2 <= len) { mpn_copyi(ptr2, poly2->coeffs, len2); mpn_zero(ptr2 + len2, len - len2); } else { _nmod_poly_rem(ptr2, poly2->coeffs, len2, poly3->coeffs, len3, res->mod); } nmod_poly_fit_length(res, len); _nmod_poly_compose_mod_horner(res->coeffs, poly1->coeffs, len1, ptr2, poly3->coeffs, len3, res->mod); res->length = len; _nmod_poly_normalise(res); _nmod_vec_clear(ptr2); }
void nmod_poly_compose_mod_brent_kung(nmod_poly_t res, const nmod_poly_t poly1, const nmod_poly_t poly2, const nmod_poly_t poly3) { long len1 = poly1->length; long len2 = poly2->length; long len3 = poly3->length; long len = len3 - 1; mp_ptr ptr2; if (len3 == 0) { printf("exception: division by zero in " "nmod_poly_compose_mod_brent_kung\n"); abort(); } if (len1 >= len3) { printf("exception: nmod_poly_compose_brent_kung: the degree of the" " first polynomial must be smaller than that of the modulus\n"); abort(); } if (len1 == 0 || len3 == 1) { nmod_poly_zero(res); return; } if (len1 == 1) { nmod_poly_set(res, poly1); return; } if (res == poly3 || res == poly1) { nmod_poly_t tmp; nmod_poly_init_preinv(tmp, res->mod.n, res->mod.ninv); nmod_poly_compose_mod_brent_kung(tmp, poly1, poly2, poly3); nmod_poly_swap(tmp, res); nmod_poly_clear(tmp); return; } ptr2 = _nmod_vec_init(len); if (len2 <= len) { mpn_copyi(ptr2, poly2->coeffs, len2); mpn_zero(ptr2 + len2, len - len2); } else { _nmod_poly_rem(ptr2, poly2->coeffs, len2, poly3->coeffs, len3, res->mod); } nmod_poly_fit_length(res, len); _nmod_poly_compose_mod_brent_kung(res->coeffs, poly1->coeffs, len1, ptr2, poly3->coeffs, len3, res->mod); res->length = len; _nmod_poly_normalise(res); _nmod_vec_clear(ptr2); }
void nmod_poly_divrem_basecase(nmod_poly_t Q, nmod_poly_t R, const nmod_poly_t A, const nmod_poly_t B) { const slong lenA = A->length, lenB = B->length; mp_ptr Q_coeffs, R_coeffs, W; nmod_poly_t t1, t2; TMP_INIT; if (lenB == 0) { flint_printf("Exception (nmod_poly_divrem). Division by zero.\n"); abort(); } if (lenA < lenB) { nmod_poly_set(R, A); nmod_poly_zero(Q); return; } if (Q == A || Q == B) { nmod_poly_init2_preinv(t1, B->mod.n, B->mod.ninv, lenA - lenB + 1); Q_coeffs = t1->coeffs; } else { nmod_poly_fit_length(Q, lenA - lenB + 1); Q_coeffs = Q->coeffs; } if (R == A || R == B) { nmod_poly_init2_preinv(t2, B->mod.n, B->mod.ninv, lenB - 1); R_coeffs = t2->coeffs; } else { nmod_poly_fit_length(R, lenB - 1); R_coeffs = R->coeffs; } TMP_START; W = TMP_ALLOC(NMOD_DIVREM_BC_ITCH(lenA, lenB, A->mod)*sizeof(mp_limb_t)); _nmod_poly_divrem_basecase(Q_coeffs, R_coeffs, W, A->coeffs, lenA, B->coeffs, lenB, B->mod); if (Q == A || Q == B) { nmod_poly_swap(Q, t1); nmod_poly_clear(t1); } if (R == A || R == B) { nmod_poly_swap(R, t2); nmod_poly_clear(t2); } Q->length = lenA - lenB + 1; R->length = lenB - 1; TMP_END; _nmod_poly_normalise(R); }
int nmod_poly_mat_inv(nmod_poly_mat_t Ainv, nmod_poly_t den, const nmod_poly_mat_t A) { slong n = nmod_poly_mat_nrows(A); if (n == 0) { nmod_poly_one(den); return 1; } else if (n == 1) { nmod_poly_set(den, E(A, 0, 0)); nmod_poly_one(E(Ainv, 0, 0)); return !nmod_poly_is_zero(den); } else if (n == 2) { nmod_poly_mat_det(den, A); if (nmod_poly_is_zero(den)) { return 0; } else if (Ainv == A) { nmod_poly_swap(E(A, 0, 0), E(A, 1, 1)); nmod_poly_neg(E(A, 0, 1), E(A, 0, 1)); nmod_poly_neg(E(A, 1, 0), E(A, 1, 0)); return 1; } else { nmod_poly_set(E(Ainv, 0, 0), E(A, 1, 1)); nmod_poly_set(E(Ainv, 1, 1), E(A, 0, 0)); nmod_poly_neg(E(Ainv, 0, 1), E(A, 0, 1)); nmod_poly_neg(E(Ainv, 1, 0), E(A, 1, 0)); return 1; } } else { nmod_poly_mat_t LU, I; slong * perm; int result; perm = _perm_init(n); nmod_poly_mat_init_set(LU, A); result = (nmod_poly_mat_fflu(LU, den, perm, LU, 1) == n); if (result) { nmod_poly_mat_init(I, n, n, nmod_poly_mat_modulus(A)); nmod_poly_mat_one(I); nmod_poly_mat_solve_fflu_precomp(Ainv, perm, LU, I); nmod_poly_mat_clear(I); } else nmod_poly_zero(den); if (_perm_parity(perm, n)) { nmod_poly_mat_neg(Ainv, Ainv); nmod_poly_neg(den, den); } _perm_clear(perm); nmod_poly_mat_clear(LU); return result; } }