void nmod_poly_mat_det(nmod_poly_t det, const nmod_poly_mat_t A) { slong n = A->r; if (n == 0) { nmod_poly_one(det); } else if (n == 1) { nmod_poly_set(det, nmod_poly_mat_entry(A, 0, 0)); } else if (n == 2) { nmod_poly_t tmp; nmod_poly_init(tmp, nmod_poly_mat_modulus(A)); nmod_poly_mul(det, nmod_poly_mat_entry(A, 0, 0), nmod_poly_mat_entry(A, 1, 1)); nmod_poly_mul(tmp, nmod_poly_mat_entry(A, 0, 1), nmod_poly_mat_entry(A, 1, 0)); nmod_poly_sub(det, det, tmp); nmod_poly_clear(tmp); } else if (n < 15) /* should be entry sensitive too */ { nmod_poly_mat_det_fflu(det, A); } else { nmod_poly_mat_det_interpolate(det, A); } }
void nmod_poly_factor_set(nmod_poly_factor_t res, const nmod_poly_factor_t fac) { if (res != fac) { if (fac->num == 0) { nmod_poly_factor_clear(res); nmod_poly_factor_init(res); } else { slong i; nmod_poly_factor_fit_length(res, fac->num); for (i = 0; i < fac->num; i++) { nmod_poly_set(res->p + i, fac->p + i); (res->p + i)->mod = (fac->p + i)->mod; res->exp[i] = fac->exp[i]; } for ( ; i < res->num; i++) { nmod_poly_zero(res->p + i); res->exp[i] = 0; } res->num = fac->num; } } }
void nmod_poly_divrem_newton(nmod_poly_t Q, nmod_poly_t R, const nmod_poly_t A, const nmod_poly_t B) { const long lenA = A->length, lenB = B->length; mp_ptr q, r; if (lenB == 0) { printf("Exception: division by zero in nmod_poly_divrem_newton\n"); abort(); } if (lenA < lenB) { nmod_poly_set(R, A); nmod_poly_zero(Q); return; } if (Q == A || Q == B) { q = _nmod_vec_init(lenA - lenB + 1); } else { nmod_poly_fit_length(Q, lenA - lenB + 1); q = Q->coeffs; } if (R == A || R == B) { r = _nmod_vec_init(lenB - 1); } else { nmod_poly_fit_length(R, lenB - 1); r = R->coeffs; } _nmod_poly_divrem_newton(q, r, A->coeffs, lenA, B->coeffs, lenB, B->mod); if (Q == A || Q == B) { _nmod_vec_clear(Q->coeffs); Q->coeffs = q; Q->alloc = lenA - lenB + 1; } if (R == A || R == B) { _nmod_vec_clear(R->coeffs); R->coeffs = r; R->alloc = lenB - 1; } Q->length = lenA - lenB + 1; R->length = lenB - 1; _nmod_poly_normalise(R); }
void nmod_poly_taylor_shift_convolution(nmod_poly_t g, const nmod_poly_t f, mp_limb_t c) { if (f != g) nmod_poly_set(g, f); _nmod_poly_taylor_shift_convolution(g->coeffs, c, g->length, g->mod); }
void nmod_poly_mat_set(nmod_poly_mat_t B, const nmod_poly_mat_t A) { if (A != B) { long i, j; for (i = 0; i < A->r; i++) for (j = 0; j < A->c; j++) nmod_poly_set(nmod_poly_mat_entry(B, i, j), nmod_poly_mat_entry(A, i, j)); } }
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_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); }
long nmod_poly_mat_nullspace(nmod_poly_mat_t res, const nmod_poly_mat_t mat) { long i, j, k, m, n, rank, nullity; long * pivots; long * nonpivots; nmod_poly_mat_t tmp; nmod_poly_t den; m = mat->r; n = mat->c; nmod_poly_init(den, nmod_poly_mat_modulus(mat)); nmod_poly_mat_init_set(tmp, mat); rank = nmod_poly_mat_rref(tmp, den, NULL, tmp); nullity = n - rank; nmod_poly_mat_zero(res); if (rank == 0) { for (i = 0; i < nullity; i++) nmod_poly_one(res->rows[i] + i); } else if (nullity) { pivots = flint_malloc(rank * sizeof(long)); nonpivots = flint_malloc(nullity * sizeof(long)); for (i = j = k = 0; i < rank; i++) { while (nmod_poly_is_zero(tmp->rows[i] + j)) { nonpivots[k] = j; k++; j++; } pivots[i] = j; j++; } while (k < nullity) { nonpivots[k] = j; k++; j++; } nmod_poly_set(den, tmp->rows[0] + pivots[0]); for (i = 0; i < nullity; i++) { for (j = 0; j < rank; j++) nmod_poly_set(res->rows[pivots[j]] + i, tmp->rows[j] + nonpivots[i]); nmod_poly_neg(res->rows[nonpivots[i]] + i, den); } flint_free(pivots); flint_free(nonpivots); } nmod_poly_clear(den); nmod_poly_mat_clear(tmp); return nullity; }
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 main(void) { int i, result; flint_rand_t state; flint_randinit(state); printf("shift_left_right...."); fflush(stdout); /* Check a << shift >> shift == a */ for (i = 0; i < 10000; i++) { nmod_poly_t a, b; mp_limb_t n = n_randtest_not_zero(state); long shift = n_randint(state, 100); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_randtest(a, state, n_randint(state, 100)); nmod_poly_shift_left(b, a, shift); nmod_poly_shift_right(b, b, shift); result = (nmod_poly_equal(a, b)); if (!result) { printf("FAIL:\n"); printf("shift = %ld, a->length = %ld, n = %lu\n", shift, a->length, a->mod.n); nmod_poly_print(a), printf("\n\n"); nmod_poly_print(b), printf("\n\n"); abort(); } nmod_poly_clear(a); nmod_poly_clear(b); } /* Check a << shift >> shift == a aliasing the other way */ for (i = 0; i < 10000; i++) { nmod_poly_t a, b, c; mp_limb_t n = n_randtest_not_zero(state); long shift = n_randint(state, 100); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(c, n); nmod_poly_randtest(c, state, n_randint(state, 100)); nmod_poly_set(a, c); nmod_poly_shift_left(c, c, shift); nmod_poly_shift_right(b, c, shift); result = (nmod_poly_equal(a, b)); if (!result) { printf("FAIL:\n"); printf("shift = %ld, c->length = %ld, n = %lu\n", shift, c->length, a->mod.n); nmod_poly_print(a), printf("\n\n"); nmod_poly_print(b), printf("\n\n"); abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(c); } flint_randclear(state); printf("PASS\n"); return 0; }
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 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 pq_nmod_elt_set_mono(pq_nmod_elt_t x, const nmod_poly_t val) { nmod_poly_set(x->mono, val); nmod_poly_zero(x->dual); }
void _pq_nmod_elt_set_dual(pq_nmod_elt_t x, const nmod_poly_t val) { nmod_poly_zero(x->mono); nmod_poly_set(x->dual, val); }
void pq_nmod_elt_set(pq_nmod_elt_t x, const pq_nmod_elt_t y) { nmod_poly_set(x->mono, y->mono); nmod_poly_set(x->dual, y->dual); }
slong nmod_poly_mat_rref(nmod_poly_mat_t R, nmod_poly_t den, const nmod_poly_mat_t A) { slong i, j, k, m, n, rank; slong *pivots, *nonpivots; rank = nmod_poly_mat_fflu(R, den, NULL, A, 0); m = nmod_poly_mat_nrows(R); n = nmod_poly_mat_ncols(R); /* clear bottom */ for (i = rank; i < m; i++) for (j = 0; j < n; j++) nmod_poly_zero(nmod_poly_mat_entry(R, i, j)); /* Convert row echelon form to reduced row echelon form */ if (rank > 1) { nmod_poly_t tmp, tmp2; nmod_poly_init(tmp, nmod_poly_mat_modulus(R)); nmod_poly_init(tmp2, nmod_poly_mat_modulus(R)); pivots = flint_malloc(sizeof(slong) * n); nonpivots = pivots + rank; /* find pivot positions */ for (i = j = k = 0; i < rank; i++) { while (nmod_poly_is_zero(nmod_poly_mat_entry(R, i, j))) { nonpivots[k] = j; k++; j++; } pivots[i] = j; j++; } while (k < n - rank) { nonpivots[k] = j; k++; j++; } for (k = 0; k < n - rank; k++) { for (i = rank - 2; i >= 0; i--) { nmod_poly_mul(tmp, den, nmod_poly_mat_entry(R, i, nonpivots[k])); for (j = i + 1; j < rank; j++) { nmod_poly_mul(tmp2, nmod_poly_mat_entry(R, i, pivots[j]), nmod_poly_mat_entry(R, j, nonpivots[k])); nmod_poly_sub(tmp, tmp, tmp2); } nmod_poly_div(nmod_poly_mat_entry(R, i, nonpivots[k]), tmp, nmod_poly_mat_entry(R, i, pivots[i])); } } /* clear pivot columns */ for (i = 0; i < rank; i++) { for (j = 0; j < rank; j++) { if (i == j) nmod_poly_set(nmod_poly_mat_entry(R, j, pivots[i]), den); else nmod_poly_zero(nmod_poly_mat_entry(R, j, pivots[i])); } } flint_free(pivots); nmod_poly_clear(tmp); nmod_poly_clear(tmp2); } return rank; }
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; } }
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); }