void fmpz_mod_poly_sub(fmpz_mod_poly_t res, const fmpz_mod_poly_t poly1, const fmpz_mod_poly_t poly2) { long max = FLINT_MAX(poly1->length, poly2->length); fmpz_mod_poly_fit_length(res, max); _fmpz_mod_poly_sub(res->coeffs, poly1->coeffs, poly1->length, poly2->coeffs, poly2->length, &(res->p)); _fmpz_mod_poly_set_length(res, max); _fmpz_mod_poly_normalise(res); }
void fmpz_mod_poly_set(fmpz_mod_poly_t poly1, const fmpz_mod_poly_t poly2) { if (poly1 != poly2) /* Aliasing is trivial */ { slong i, len = poly2->length; fmpz_mod_poly_fit_length(poly1, len); for (i = 0; i < len; i++) fmpz_set(poly1->coeffs + i, poly2->coeffs + i); _fmpz_mod_poly_set_length(poly1, len); } }
void fmpz_mod_poly_mul(fmpz_mod_poly_t res, const fmpz_mod_poly_t poly1, const fmpz_mod_poly_t poly2) { const slong len1 = poly1->length; const slong len2 = poly2->length; const slong lenr = len1 + len2 - 1; if ((len1 == 0) || (len2 == 0)) { fmpz_mod_poly_zero(res); return; } if ((res == poly1) || (res == poly2)) { fmpz *t = _fmpz_vec_init(lenr); if (len1 >= len2) _fmpz_mod_poly_mul(t, poly1->coeffs, len1, poly2->coeffs, len2, &(res->p)); else _fmpz_mod_poly_mul(t, poly2->coeffs, len2, poly1->coeffs, len1, &(res->p)); _fmpz_vec_clear(res->coeffs, res->alloc); res->alloc = lenr; res->length = lenr; res->coeffs = t; } else { fmpz_mod_poly_fit_length(res, lenr); if (len1 >= len2) _fmpz_mod_poly_mul(res->coeffs, poly1->coeffs, len1, poly2->coeffs, len2, &(res->p)); else _fmpz_mod_poly_mul(res->coeffs, poly2->coeffs, len2, poly1->coeffs, len1, &(res->p)); _fmpz_mod_poly_set_length(res, lenr); } _fmpz_mod_poly_normalise(res); }
void fmpz_mod_poly_div_basecase(fmpz_mod_poly_t Q, const fmpz_mod_poly_t A, const fmpz_mod_poly_t B) { const long lenA = A->length, lenB = B->length, lenQ = lenA - lenB + 1; fmpz *q; fmpz_t invB; if (lenA < lenB) { fmpz_mod_poly_zero(Q); return; } fmpz_init(invB); fmpz_invmod(invB, B->coeffs + (lenB - 1), &(B->p)); if (Q == A || Q == B) { q = _fmpz_vec_init(lenQ); } else { fmpz_mod_poly_fit_length(Q, lenQ); q = Q->coeffs; } _fmpz_mod_poly_div_basecase(q, NULL, A->coeffs, lenA, B->coeffs, lenB, invB, &(B->p)); if (Q == A || Q == B) { _fmpz_vec_clear(Q->coeffs, Q->alloc); Q->coeffs = q; Q->alloc = lenQ; Q->length = lenQ; } else { _fmpz_mod_poly_set_length(Q, lenQ); } fmpz_clear(invB); }
void fmpz_mod_poly_shift_right(fmpz_mod_poly_t res, const fmpz_mod_poly_t poly, long n) { if (n == 0) { fmpz_mod_poly_set(res, poly); return; } if (poly->length <= n) { fmpz_mod_poly_zero(res); return; } fmpz_mod_poly_fit_length(res, poly->length - n); _fmpz_mod_poly_shift_right(res->coeffs, poly->coeffs, poly->length, n); _fmpz_mod_poly_set_length(res, poly->length - n); }
void fmpz_mod_poly_compose_horner(fmpz_mod_poly_t res, const fmpz_mod_poly_t poly1, const fmpz_mod_poly_t poly2) { const long len1 = poly1->length; const long len2 = poly2->length; if (len1 == 0) { fmpz_mod_poly_zero(res); } else if (len1 == 1 || len2 == 0) { fmpz_mod_poly_set_fmpz(res, poly1->coeffs); } else { const long lenr = (len1 - 1) * (len2 - 1) + 1; if ((res != poly1) && (res != poly2)) { fmpz_mod_poly_fit_length(res, lenr); _fmpz_mod_poly_compose_horner(res->coeffs, poly1->coeffs, len1, poly2->coeffs, len2, &(res->p)); } else { fmpz *t = _fmpz_vec_init(lenr); _fmpz_mod_poly_compose_horner(t, poly1->coeffs, len1, poly2->coeffs, len2, &(res->p)); _fmpz_vec_clear(res->coeffs, res->alloc); res->coeffs = t; res->alloc = lenr; res->length = lenr; } _fmpz_mod_poly_set_length(res, lenr); _fmpz_mod_poly_normalise(res); } }
void fmpz_mod_poly_make_monic(fmpz_mod_poly_t res, const fmpz_mod_poly_t poly) { const slong len = poly->length; fmpz_t inv; if (len == 0) { fmpz_mod_poly_zero(res); return; } fmpz_init(inv); fmpz_invmod(inv, fmpz_mod_poly_lead(poly), &(poly->p)); fmpz_mod_poly_fit_length(res, len); _fmpz_mod_poly_set_length(res, len); _fmpz_mod_poly_scalar_mul_fmpz(res->coeffs, poly->coeffs, len, inv, &(poly->p)); fmpz_clear(inv); }
void fmpz_mod_poly_divrem_f(fmpz_t f, fmpz_mod_poly_t Q, fmpz_mod_poly_t R, const fmpz_mod_poly_t A, const fmpz_mod_poly_t B) { const slong lenA = A->length; const slong lenB = B->length; const slong lenQ = lenA - lenB + 1; fmpz *q, *r; fmpz_t invB; fmpz_init(invB); fmpz_gcdinv(f, invB, fmpz_poly_lead(B), &(B->p)); if (!fmpz_is_one(f)) { fmpz_clear(invB); return; } if (lenA < lenB) { fmpz_mod_poly_set(R, A); fmpz_mod_poly_zero(Q); fmpz_clear(invB); return; } if (Q == A || Q == B) { q = _fmpz_vec_init(lenQ); } else { fmpz_mod_poly_fit_length(Q, lenQ); q = Q->coeffs; } if (R == A || R == B) { r = _fmpz_vec_init(lenA); } else { fmpz_mod_poly_fit_length(R, lenA); r = R->coeffs; } _fmpz_mod_poly_divrem_divconquer(q, r, A->coeffs, lenA, B->coeffs, lenB, invB, &(B->p)); if (Q == A || Q == B) { _fmpz_vec_clear(Q->coeffs, Q->alloc); Q->coeffs = q; Q->alloc = lenQ; Q->length = lenQ; } else { _fmpz_mod_poly_set_length(Q, lenQ); } if (R == A || R == B) { _fmpz_vec_clear(R->coeffs, R->alloc); R->coeffs = r; R->alloc = lenA; R->length = lenA; } _fmpz_mod_poly_set_length(R, lenB - 1); _fmpz_mod_poly_normalise(R); fmpz_clear(invB); }
void fmpz_mod_poly_radix(fmpz_mod_poly_struct **B, const fmpz_mod_poly_t F, const fmpz_mod_poly_radix_t D) { const long lenF = F->length; const long degF = F->length - 1; const long degR = D->degR; const long N = degF / degR; if (N == 0) { fmpz_mod_poly_set(B[0], F); } else { const long k = FLINT_BIT_COUNT(N); /* k := ceil{log{N+1}} */ const long lenG = (1L << k) * degR; /* Padded size */ const long t = (lenG - 1) / degR - N; /* Extra {degR}-blocks */ fmpz *G; /* Padded copy of F */ fmpz *T; /* Additional B[i] */ fmpz **C; /* Enlarged version of B */ fmpz *W; /* Temporary space */ long i; if (lenF < lenG) { G = flint_malloc(lenG * sizeof(fmpz)); for (i = 0; i < lenF; i++) G[i] = F->coeffs[i]; mpn_zero((mp_ptr) G + lenF, lenG - lenF); T = t ? _fmpz_vec_init(t * degR) : NULL; } else /* lenF == lenG */ { G = F->coeffs; T = NULL; } C = flint_malloc((N + 1 + t) * sizeof(fmpz *)); for (i = 0; i <= N; i++) { fmpz_mod_poly_fit_length(B[i], degR); C[i] = B[i]->coeffs; } for (i = 0; i < t; i++) { C[N + 1 + i] = T + i * degR; } W = _fmpz_vec_init(lenG); _fmpz_mod_poly_radix(C, G, D->Rpow, D->Rinv, degR, 0, k-1, W, &(F->p)); _fmpz_vec_clear(W, lenG); for (i = 0; i <= N; i++) { _fmpz_mod_poly_set_length(B[i], degR); _fmpz_mod_poly_normalise(B[i]); } flint_free(C); if (lenF < lenG) { flint_free(G); } if (t) { _fmpz_vec_clear(T, t * degR); } } }